IPACM: add support for new QMI message

IPACM sends QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_V01 which can hold at
most 128 rules in IPA v3, while in IPA v2 it sends old QMI message
QMI_IPA_INSTALL_FILTER_RULE_REQ_V01 which can hold only 64 rules.

Change-Id: I8b8e3d7cbfd4adfec82edbeca9ca082480211e12
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index b613392..d2cc362 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -95,7 +95,13 @@
 #define WWAN_QMI_IOCTL_DEVICE_NAME "/dev/wwan_ioctl"
 #define IPA_DEVICE_NAME "/dev/ipa"
 #define MAX_NUM_PROP 2
+
+#ifndef FEATURE_IPA_V3
 #define IPA_MAX_FLT_RULE 50
+#else
+#define IPA_MAX_FLT_RULE 100
+#endif
+
 #define TCP_FIN_SHIFT 16
 #define TCP_SYN_SHIFT 17
 #define TCP_RST_SHIFT 18
diff --git a/ipacm/src/IPACM_Filtering.cpp b/ipacm/src/IPACM_Filtering.cpp
index 7faecad..78a1f91 100644
--- a/ipacm/src/IPACM_Filtering.cpp
+++ b/ipacm/src/IPACM_Filtering.cpp
@@ -260,6 +260,7 @@
 {
 	int ret = 0, cnt, num_rules = 0, pos = 0;
 	ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg;
+	ipa_install_fltr_rule_req_ex_msg_v01 qmi_rule_ex_msg;
 
 	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
 	if(fd_wwan_ioctl < 0)
@@ -279,6 +280,8 @@
 		IPACMDBG_H("Get %d WAN DL IPv6 filtering rules.\n", rule_table_v6->num_rules);
 	}
 
+	/* if it is not IPA v3, use old QMI format */
+#ifndef FEATURE_IPA_V3
 	if(num_rules > QMI_IPA_MAX_FILTERS_V01)
 	{
 		IPACMERR("The number of filtering rules exceed limit.\n");
@@ -291,27 +294,14 @@
 
 		if (num_rules > 0)
 		{
-#ifndef FEATURE_IPA_V3
 			qmi_rule_msg.filter_spec_list_valid = true;
-#else /* defined (FEATURE_IPA_V3) */
-			qmi_rule_msg.filter_spec_ex_list_valid = true;
-#endif
 		}
 		else
 		{
-#ifndef FEATURE_IPA_V3
 			qmi_rule_msg.filter_spec_list_valid = false;
-#else /* defined (FEATURE_IPA_V3) */
-			qmi_rule_msg.filter_spec_ex_list_valid = false;
-#endif
 		}
 
-#ifndef FEATURE_IPA_V3
 		qmi_rule_msg.filter_spec_list_len = num_rules;
-#else /* defined (FEATURE_IPA_V3) */
-		qmi_rule_msg.filter_spec_ex_list_len = num_rules;
-#endif
-
 		qmi_rule_msg.source_pipe_index_valid = 0;
 
 		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
@@ -322,7 +312,6 @@
 			{
 				if (pos < QMI_IPA_MAX_FILTERS_V01)
 				{
-#ifndef FEATURE_IPA_V3
 					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
 					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
 					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
@@ -333,19 +322,6 @@
 					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
 						&rule_table_v4->rules[cnt].rule.eq_attrib,
 						sizeof(struct ipa_filter_rule_type_v01));
-#else /* defined (FEATURE_IPA_V3) */
-					qmi_rule_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
-					qmi_rule_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
-					qmi_rule_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
-					qmi_rule_msg.filter_spec_ex_list[pos].mux_id = mux_id;
-					qmi_rule_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
-					qmi_rule_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
-					memcpy(&qmi_rule_msg.filter_spec_ex_list[pos].filter_rule,
-						&rule_table_v4->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-#endif
 					pos++;
 				}
 				else
@@ -361,7 +337,6 @@
 			{
 				if (pos < QMI_IPA_MAX_FILTERS_V01)
 				{
-#ifndef FEATURE_IPA_V3
 					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
 					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
 					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
@@ -372,19 +347,6 @@
 					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
 						&rule_table_v6->rules[cnt].rule.eq_attrib,
 						sizeof(struct ipa_filter_rule_type_v01));
-#else /* defined (FEATURE_IPA_V3) */
-					qmi_rule_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
-					qmi_rule_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
-					qmi_rule_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
-					qmi_rule_msg.filter_spec_ex_list[pos].mux_id = mux_id;
-					qmi_rule_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
-					qmi_rule_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
-					memcpy(&qmi_rule_msg.filter_spec_ex_list[pos].filter_rule,
-						&rule_table_v6->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-#endif
 					pos++;
 				}
 				else
@@ -402,7 +364,95 @@
 			return false;
 		}
 	}
-	IPACMDBG("Added Filtering rule %p\n", &qmi_rule_msg);
+	/* if it is IPA v3, use new QMI format */
+#else
+	if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01)
+	{
+		IPACMERR("The number of filtering rules exceed limit.\n");
+		close(fd_wwan_ioctl);
+		return false;
+	}
+	else
+	{
+		memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg));
+
+		if (num_rules > 0)
+		{
+			qmi_rule_ex_msg.filter_spec_ex_list_valid = true;
+		}
+		else
+		{
+			qmi_rule_ex_msg.filter_spec_ex_list_valid = false;
+		}
+		qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules;
+		qmi_rule_ex_msg.source_pipe_index_valid = 0;
+
+		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
+
+		if(rule_table_v4 != NULL)
+		{
+			for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
+			{
+				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
+				{
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
+					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
+						&rule_table_v4->rules[cnt].rule.eq_attrib,
+						sizeof(struct ipa_filter_rule_type_v01));
+
+					pos++;
+				}
+				else
+				{
+					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
+				}
+			}
+		}
+
+		if(rule_table_v6 != NULL)
+		{
+			for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
+			{
+				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
+				{
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
+					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
+					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
+						&rule_table_v6->rules[cnt].rule.eq_attrib,
+						sizeof(struct ipa_filter_rule_type_v01));
+
+					pos++;
+				}
+				else
+				{
+					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
+				}
+			}
+		}
+
+		ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg);
+		if (ret != 0)
+		{
+			IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_ex_msg, ret);
+			close(fd_wwan_ioctl);
+			return false;
+		}
+	}
+#endif
+
 	close(fd_wwan_ioctl);
 	return true;
 }