summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Adisumarta <madisuma@codeaurora.org>2019-12-04 14:43:42 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2020-02-13 03:55:18 -0800
commit0cacc4ff148565e65a00affab57a43a87960e0f1 (patch)
tree2d04ab068258bf97b0b31e2bac3cdef874d36c50
parentd68d7b123c14061dc8efb55f39109e42d63281a5 (diff)
downloadipacfg-mgr-0cacc4ff148565e65a00affab57a43a87960e0f1.tar.gz
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
-rw-r--r--ipacm/inc/IPACM_Config.h2
-rw-r--r--ipacm/inc/IPACM_Defs.h3
-rw-r--r--ipacm/inc/IPACM_Lan.h6
-rw-r--r--ipacm/inc/IPACM_Wan.h25
-rw-r--r--ipacm/src/IPACM_Iface.cpp7
-rw-r--r--ipacm/src/IPACM_Lan.cpp201
-rw-r--r--ipacm/src/IPACM_Wan.cpp58
-rw-r--r--ipacm/src/IPACM_Wlan.cpp8
8 files changed, 269 insertions, 41 deletions
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 @@ public:
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 @@ extern "C"
#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 @@ extern "C"
#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 @@ extern "C"
#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 @@ public:
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 @@ protected:
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 @@ private:
/* 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 @@ public:
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 @@ public:
#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 @@ private:
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 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
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 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
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 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
{
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 @@ int IPACM_Lan::handle_wan_down(ipacm_wan_iface_type backhaul_mode)
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 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type)
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 @@ int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop *ext_prop, ipa_ip_type iptype, ui
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 @@ int IPACM_Lan::handle_down_evt()
}
#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 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype)
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 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype)
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 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype)
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 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype)
}
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 IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
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 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
}
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 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
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 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
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 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
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 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
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 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
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 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
}
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 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
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 @@ fail:
}
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 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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_v4[IPA_MAX_IFACE_ENTRIES];
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 @@ IPACM_Wan::IPACM_Wan(int iface_index,
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 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
}
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 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
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 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
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 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
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 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
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 @@ int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype)
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 @@ int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype)
else
IPACMERR(" ipa_pm_q6_check becomes negative !!!\n");
}
-#else
-}
#endif
/* Delete the default route*/
if (iptype == IPA_IP_v6)
@@ -5554,6 +5565,9 @@ int IPACM_Wan::handle_down_evt_ex()
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 @@ fail:
}
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 @@ int IPACM_Wlan::handle_down_evt()
}
/* 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");