Merge 1ef0be7f97aca2460d597efea23846923f3b479e on remote branch
Change-Id: Iae0ce442371a9e3c44ae5e4ff0c475b8484669bc
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 9230f7d..2792f62 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -94,7 +94,7 @@
ipacm_alg *alg_table;
/* Store private subnet configuration from XML file */
- ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
+ ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
/* Store the non nat iface names */
NatIfaces *pNatIfaces;
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 65d5ce4..b1daf35 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -77,6 +77,7 @@
#define IPA_MAX_IFACE_ENTRIES 20
#define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3
+#define IPA_MAX_MTU_ENTRIES 3
#define IPA_MAX_ALG_ENTRIES 20
#define IPA_MAX_RM_ENTRY 6
@@ -106,6 +107,7 @@
#define TCP_SYN_SHIFT 17
#define TCP_RST_SHIFT 18
#define NUM_IPV6_PREFIX_FLT_RULE 1
+#define NUM_IPV6_PREFIX_MTU_RULE 1
/*---------------------------------------------------------------------------
Return values indicating error status
@@ -124,6 +126,7 @@
#define IPA_MAC_ADDR_SIZE 6
#define IPA_MAX_NUM_SW_PDNS 15
+#define DEFAULT_MTU_SIZE 1500
/*===========================================================================
GLOBAL DEFINITIONS AND DECLARATIONS
===========================================================================*/
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index bf815c5..605edb5 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -113,7 +113,7 @@
uint32_t lan_wan_fl_rule_hdl[IPA_WAN_DEFAULT_FILTER_RULE_HANDLES];
/* store private-subnet filter rule handlers */
- uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
+ uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
/* LAN-iface's callback function */
void event_callback(ipa_cm_event_id event, void *data);
@@ -258,7 +258,7 @@
uint32_t ipv4_icmp_flt_rule_hdl[NUM_IPV4_ICMP_FLT_RULE];
- uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE];
+ uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE];
uint32_t ipv6_icmp_flt_rule_hdl[NUM_IPV6_ICMP_FLT_RULE];
int num_wan_ul_fl_rule_v4;
@@ -464,6 +464,8 @@
/* for pcie modem */
virtual int add_connection(int client_index, int v6_num);
virtual int del_connection(int client_index, int v6_num);
+
+ int construct_mtu_rule(struct ipa_flt_rule *rule, enum ipa_ip_type iptype, uint16_t mtu);
};
#endif /* IPACM_LAN_H */
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 684bfb7..31949c5 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -105,6 +105,8 @@
static bool wan_up;
static bool wan_up_v6;
static uint8_t xlat_mux_id;
+ static uint16_t mtu_default_wan;
+ uint16_t mtu_size;
/* IPACM interface name */
static char wan_up_dev_name[IF_NAME_LEN];
static uint32_t curr_wan_ip;
@@ -137,6 +139,26 @@
#endif
}
+ static uint16_t queryMTU(int ipa_if_num_tether, enum ipa_ip_type iptype)
+ {
+ if (iptype == IPA_IP_v4)
+ {
+ if (isWanUP(ipa_if_num_tether))
+ {
+ return mtu_default_wan;
+ }
+ }
+ else if (iptype == IPA_IP_v6)
+ {
+ if (isWanUP_V6(ipa_if_num_tether))
+ {
+ return mtu_default_wan;
+
+ }
+ }
+ return DEFAULT_MTU_SIZE;
+ }
+
static bool isWanUP_V6(int ipa_if_num_tether)
{
#ifdef FEATURE_IPA_ANDROID
@@ -653,6 +675,9 @@
int add_tcp_fin_rst_exception_rule();
int delete_tcp_fin_rst_exception_rule();
+
+ /* Query mtu size */
+ int query_mtu_size();
};
#endif /* IPACM_WAN_H */
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index ec4a9ea..efa941c 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -938,15 +938,12 @@
memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
#ifdef FEATURE_IPA_ANDROID
- /* Add the ipv6 tcp fragment filtering rule. */
+ /* Add the ipv6 tcp/udp fragment filtering rule for MTU */
- IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
+ IPACMDBG_H("Adding IPv6 fragment filter rule\n");
flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
- flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
- flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
-
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 755d730..41c3723 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -129,8 +129,8 @@
memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_FLT_RULE * sizeof(uint32_t));
- memset(private_fl_rule_hdl, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t));
- memset(ipv6_prefix_flt_rule_hdl, 0, NUM_IPV6_PREFIX_FLT_RULE * sizeof(uint32_t));
+ memset(private_fl_rule_hdl, 0, (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) * sizeof(uint32_t));
+ memset(ipv6_prefix_flt_rule_hdl, 0, (NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE) * sizeof(uint32_t));
memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t));
memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
@@ -881,6 +881,11 @@
{
memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix));
install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix);
+
+ /* MTU might have changed. Need to update ipv4 MTU rule if up */
+ if (IPACM_Wan::isWanUP(ipa_if_num))
+ handle_private_subnet_android(IPA_IP_v4);
+
if (data_wan->backhaul_type == Q6_WAN)
{
ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
@@ -1306,6 +1311,9 @@
sta_ul_v4_set = false;
}
+ /* clean MTU rules if needed */
+ handle_private_subnet_android(IPA_IP_v4);
+
close(fd);
return IPACM_SUCCESS;
}
@@ -1644,6 +1652,18 @@
if(ip_type == IPA_IP_v4)
{
+ /* add MTU rules for ipv4 */
+ handle_private_subnet_android(IPA_IP_v4);
+
+ /* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */
+ if (IPACM_Wan::isWanUP_V6(ipa_if_num))
+ {
+ if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) {
+ delete_ipv6_prefix_flt_rule();
+ install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+ }
+ }
+
if(sta_ul_v4_set == true)
{
IPACMDBG_H("Filetring rule for IPV4 of STA mode is already configured, sta_ul_v4_set: %d\n",sta_ul_v4_set);
@@ -1886,6 +1906,18 @@
ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
modem_ul_v6_set = true;
} else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) {
+ /* add MTU rules for ipv4 */
+ handle_private_subnet_android(IPA_IP_v4);
+
+ /* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */
+ if (IPACM_Wan::isWanUP_V6(ipa_if_num))
+ {
+ if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) {
+ delete_ipv6_prefix_flt_rule();
+ install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+ }
+ }
+
IPACMDBG_H("check getXlat_Mux_Id:%d\n", IPACM_Wan::getXlat_Mux_Id());
IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set);
ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
@@ -3059,13 +3091,13 @@
}
#ifdef FEATURE_IPA_ANDROID
- if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false)
+ if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) == false)
{
IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
res = IPACM_FAILURE;
goto fail;
}
- IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+ IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
#else
if (m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false)
{
@@ -4044,7 +4076,7 @@
ipa_ioc_add_flt_rule* pFilteringTable;
bool result;
- len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add);
+ len = sizeof(struct ipa_ioc_add_flt_rule) + (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) * sizeof(struct ipa_flt_rule_add);
pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len);
if (pFilteringTable == NULL)
@@ -4058,7 +4090,7 @@
pFilteringTable->ep = rx_prop->rx[0].src_pipe;
pFilteringTable->global = false;
pFilteringTable->ip = iptype;
- pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES;
+ pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES;
memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add));
@@ -4081,7 +4113,7 @@
flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0;
flt_rule.rule.attrib.u.v4.dst_addr = ~0;
- for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+ for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
{
memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add));
}
@@ -4107,9 +4139,9 @@
}
else
{
- IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+ IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
/* copy filter rule hdls */
- for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+ for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
{
if (pFilteringTable->rules[i].status == 0)
{
@@ -4135,6 +4167,9 @@
int i, len, res = IPACM_SUCCESS;
struct ipa_flt_rule_mdfy flt_rule;
struct ipa_ioc_mdfy_flt_rule* pFilteringTable;
+ int mtu_rule_cnt = 0;
+ uint16_t mtu[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES] = { };
+ int mtu_rule_idx = IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
if (rx_prop == NULL)
{
@@ -4149,12 +4184,24 @@
}
else
{
- for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+ for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
{
reset_to_dummy_flt_rule(IPA_IP_v4, private_fl_rule_hdl[i]);
}
- len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy);
+ /* check how many MTU rules we need to add */
+ for(i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++)
+ {
+ mtu[i] = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v4);
+
+ if (mtu[i] > 0)
+ mtu_rule_cnt++;
+ else
+ IPACMERR("MTU is zero\n");
+ }
+ IPACMDBG_H("total %d MTU rules are needed\n", mtu_rule_cnt);
+
+ len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet + mtu_rule_cnt) * sizeof(struct ipa_flt_rule_mdfy);
pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len);
if (!pFilteringTable)
{
@@ -4165,7 +4212,7 @@
pFilteringTable->commit = 1;
pFilteringTable->ip = iptype;
- pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
+ pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet + mtu_rule_cnt;
/* Make LAN-traffic always go A5, use default IPA-RT table */
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
@@ -4185,16 +4232,32 @@
flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
- memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
- flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-
for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
{
+ /* add private subnet rule for ipv4 */
+ flt_rule.rule.action = IPA_PASS_TO_ROUTING;
+ flt_rule.rule.eq_attrib_type = 0;
flt_rule.rule_hdl = private_fl_rule_hdl[i];
+ memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
+ flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
IPACMDBG_H(" IPACM private subnet_addr as: 0x%x entry(%d)\n", flt_rule.rule.attrib.u.v4.dst_addr, i);
+
+ /* add corresponding MTU rule for ipv4 */
+ if (mtu[i] > 0)
+ {
+ flt_rule.rule_hdl = private_fl_rule_hdl[mtu_rule_idx + i];
+ memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
+ flt_rule.rule.attrib.u.v4.src_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
+ flt_rule.rule.attrib.u.v4.src_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
+ flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+ if (construct_mtu_rule(&flt_rule.rule, IPA_IP_v4, mtu[i]))
+ IPACMERR("Failed to modify MTU filtering rule.\n");
+ memcpy(&(pFilteringTable->rules[mtu_rule_idx + i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
+ IPACMDBG_H("Adding MTU rule for private subnet 0x%x.\n", flt_rule.rule.attrib.u.v4.src_addr);
+ }
}
if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
@@ -4225,12 +4288,17 @@
struct ipa_ioc_add_flt_rule* flt_rule;
struct ipa_flt_rule_add flt_rule_entry;
bool result;
+ int rule_cnt = 1;
+
+ uint16_t mtu = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v6);
+ if (mtu > 0)
+ rule_cnt ++;
if(rx_prop != NULL)
{
- len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
+ len = sizeof(struct ipa_ioc_add_flt_rule) + rule_cnt * sizeof(struct ipa_flt_rule_add);
- flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
+ flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(rule_cnt, len);
if (!flt_rule)
{
IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
@@ -4241,7 +4309,7 @@
flt_rule->ep = rx_prop->rx[0].src_pipe;
flt_rule->global = false;
flt_rule->ip = IPA_IP_v6;
- flt_rule->num_rules = 1;
+ flt_rule->num_rules = rule_cnt;
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
@@ -4267,6 +4335,30 @@
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0;
memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); // this will remove the IPA_FLT_DST_ADDR
+ flt_rule_entry.rule.attrib.u.v6.src_addr[3] = prefix[0];
+ flt_rule_entry.rule.attrib.u.v6.src_addr[2] = prefix[1];
+ flt_rule_entry.rule.attrib.u.v6.src_addr[1] = 0x0;
+ flt_rule_entry.rule.attrib.u.v6.src_addr[0] = 0x0;
+ flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF;
+ flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF;
+ flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = 0x0;
+ flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = 0x0;
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+
+ /* Add an MTU rule with every new private prefix */
+ if (mtu > 0)
+ {
+ if (construct_mtu_rule(&flt_rule_entry.rule, IPA_IP_v6, mtu))
+ {
+ IPACMERR("Failed to add MTU filtering rule.\n")
+ }
+ else
+ {
+ memcpy(&(flt_rule->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ }
+ }
+
#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
/* use index hw-counter */
if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
@@ -4288,9 +4380,14 @@
}
else
{
- IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
+ IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 2);
ipv6_prefix_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl;
IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]);
+ if (rule_cnt > 1)
+ {
+ ipv6_prefix_flt_rule_hdl[1] = flt_rule->rules[1].flt_rule_hdl;
+ IPACMDBG_H("IPv6 prefix MTU filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[1]);
+ }
free(flt_rule);
}
}
@@ -4299,12 +4396,12 @@
void IPACM_Lan::delete_ipv6_prefix_flt_rule()
{
- if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false)
+ if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE) == false)
{
- IPACMERR("Failed to delete ipv6 prefix flt rule.\n");
+ IPACMERR("Failed to delete ipv6 prefix flt rules.\n");
return;
}
- IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE);
+ IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE);
return;
}
@@ -6336,3 +6433,63 @@
}
return res;
}
+
+int IPACM_Lan::construct_mtu_rule(struct ipa_flt_rule *rule, ipa_ip_type iptype, uint16_t mtu)
+{
+ int res = IPACM_SUCCESS;
+ int fd;
+ ipa_ioc_generate_flt_eq flt_eq;
+
+ if (rule == NULL)
+ {
+ IPACMERR("rule is empty");
+ return IPACM_FAILURE;
+ }
+
+ if (mtu == 0)
+ {
+ IPACMERR("mtu is uninitialized");
+ return IPACM_FAILURE;
+ }
+
+ IPACMDBG_H("Adding MTU rule for iptype = %d\n", iptype);
+
+ rule->eq_attrib_type = 1;
+ rule->eq_attrib.rule_eq_bitmap = 0;
+ rule->action = IPA_PASS_TO_EXCEPTION;
+
+ /* generate eq */
+ memset(&flt_eq, 0, sizeof(flt_eq));
+ memcpy(&flt_eq.attrib, &rule->attrib, sizeof(flt_eq.attrib));
+ flt_eq.ip = iptype;
+
+ fd = open(IPA_DEVICE_NAME, O_RDWR);
+ if (fd < 0)
+ {
+ IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
+ return IPACM_FAILURE;
+ }
+
+ if (0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
+ {
+ IPACMERR("Failed to get eq_attrib\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ memcpy(&rule->eq_attrib,
+ &flt_eq.eq_attrib, sizeof(rule->eq_attrib));
+
+ //add IHL offsets
+ rule->eq_attrib.rule_eq_bitmap |= (1<<10);
+ rule->eq_attrib.num_ihl_offset_range_16 = 1;
+ if (iptype == IPA_IP_v4)
+ rule->eq_attrib.ihl_offset_range_16[0].offset = 0x82;
+ else
+ rule->eq_attrib.ihl_offset_range_16[0].offset = 0x84;
+ rule->eq_attrib.ihl_offset_range_16[0].range_low = mtu + 1;
+ rule->eq_attrib.ihl_offset_range_16[0].range_high = UINT16_MAX; //0xFFFF
+
+fail:
+ close(fd);
+ return res;
+}
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index db0304a..be3bffc 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -52,6 +52,7 @@
#include "linux/ipa_qmi_service_v01.h"
#ifdef FEATURE_IPACM_HAL
#include "IPACM_OffloadManager.h"
+#include <IPACM_Netlink.h>
#endif
bool IPACM_Wan::wan_up = false;
@@ -91,6 +92,8 @@
int IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES];
#endif
+uint16_t IPACM_Wan::mtu_default_wan = DEFAULT_MTU_SIZE;
+
IPACM_Wan::IPACM_Wan(int iface_index,
ipacm_wan_iface_type is_sta_mode,
uint8_t *mac_addr) : IPACM_Iface(iface_index)
@@ -129,6 +132,7 @@
ext_prop = NULL;
is_ipv6_frag_firewall_flt_rule_installed = false;
ipv6_frag_firewall_flt_rule_hdl = 0;
+ mtu_size = DEFAULT_MTU_SIZE;
num_wan_client = 0;
header_name_count = 0;
@@ -1818,6 +1822,9 @@
}
IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge);
+ /* query MTU size of the interface */
+ query_mtu_size();
+
if (m_is_sta_mode ==Q6_WAN)
{
IPACM_Wan::backhaul_mode = m_is_sta_mode;
@@ -1990,7 +1997,7 @@
IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
} else {
- result = m_routing.AddRoutingRule(rt_rule);
+ result = m_routing.AddRoutingRule(rt_rule);
}
#else
result = m_routing.AddRoutingRule(rt_rule);
@@ -2105,6 +2112,11 @@
wan_route_rule_v6_hdl_a5[0], 0, iptype);
}
+ /* set mtu_default_wan to current default wan instance */
+ mtu_default_wan = mtu_size;
+
+ IPACMDBG_H("replace the mtu_default_wan to %d\n", mtu_default_wan);
+
ipacm_event_iface_up *wanup_data;
wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
if (wanup_data == NULL)
@@ -2218,8 +2230,9 @@
IPACMDBG_H("dev %s add producer dependency\n", dev_name);
IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
+ }
#ifdef WAN_IOC_NOTIFY_WAN_STATE
- } else {
+ else {
if ((m_is_sta_mode == Q6_WAN && ipa_pm_q6_check == 0 ) || (m_is_sta_mode == Q6_MHI_WAN))
{
fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
@@ -2240,9 +2253,8 @@
ipa_pm_q6_check++;
IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
}
-#else
- }
#endif
+
if(rt_rule != NULL)
{
free(rt_rule);
@@ -4989,8 +5001,9 @@
IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+ }
#ifdef WAN_IOC_NOTIFY_WAN_STATE
- } else {
+ else {
IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
if(ipa_pm_q6_check == 1)
{
@@ -5012,8 +5025,6 @@
else
IPACMERR(" ipa_pm_q6_check becomes negative !!!\n");
}
-#else
-}
#endif
/* Delete the default route*/
if (iptype == IPA_IP_v6)
@@ -5554,6 +5565,9 @@
goto fail;
}
+ /* reset the mtu size */
+ mtu_size = DEFAULT_MTU_SIZE;
+
if(ip_type == IPA_IP_v4)
{
num_ipv4_modem_pdn--;
@@ -7913,3 +7927,33 @@
}
return res;
}
+
+int IPACM_Wan::query_mtu_size()
+{
+ int fd;
+ struct ifreq if_mtu;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if ( fd < 0 ) {
+ IPACMERR("ipacm: socket open failed [%d]\n", fd);
+ return IPACM_FAILURE;
+ }
+
+ strlcpy(if_mtu.ifr_name, dev_name, IFNAMSIZ);
+ IPACMDBG_H("device name: %s\n", dev_name);
+ if_mtu.ifr_name[IFNAMSIZ - 1] = '\0';
+
+ if ( ioctl(fd, SIOCGIFMTU, &if_mtu) < 0 ) {
+ IPACMERR("ioctl failed to get mtu\n");
+ close(fd);
+ return IPACM_FAILURE;
+ }
+ IPACMDBG_H("mtu=[%d]\n", if_mtu.ifr_mtu);
+ if (if_mtu.ifr_mtu < DEFAULT_MTU_SIZE) {
+ mtu_size = if_mtu.ifr_mtu;
+ IPACMDBG_H("replaced mtu=[%d] for (%s)\n", mtu_size, dev_name);
+ }
+
+ close(fd);
+ return IPACM_SUCCESS;
+}
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 395f951..d5d38ca 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1955,16 +1955,16 @@
}
/* delete private-ipv4 filter rules */
#ifdef FEATURE_IPA_ANDROID
- if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false)
+ if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) == false)
{
IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
res = IPACM_FAILURE;
goto fail;
}
- IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+ IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
#else
- num_private_subnet_fl_rule = IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_MAX_PRIVATE_SUBNET_ENTRIES?
- IPA_MAX_PRIVATE_SUBNET_ENTRIES : IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
+ num_private_subnet_fl_rule = IPACM_Iface::ipacmcfg->ipa_num_private_subnet > (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES)?
+ (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) : IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, num_private_subnet_fl_rule) == false)
{
IPACMERR("Error deleting private subnet flt rules, aborting...\n");