ipacm: Add MTU rule for every new private subnet or prefix
Always add IPv6 frag rule on LAN pipes.
Add an MTU rule based on new PDNs based on their mtu. If packets
are bigger than the mtu of the new PDNS, then IPA will not offload
the packets.
Change-Id: I2751cc733a10a3fc79e20348644d42630fa6762c
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");