ipacm: add support for wan ip address change in scc mode3
In SCC Mode 3, WAN interface can have multiple IP addresses.
Make changes to offload traffic with old IP address till it
expires and then enable offload path with new IP address.
If new IP address expires first, continue with old IP
address till it is available.
Change-Id: I00b05b844743e46f6f923416ed20123621662bd0
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 20bef93..1c41dfa 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -146,7 +146,7 @@
IPA_BRIDGE_LINK_UP_EVENT, /* ipacm_event_data_all */
IPA_WAN_EMBMS_LINK_UP_EVENT, /* ipacm_event_data_mac */
IPA_ADDR_ADD_EVENT, /* ipacm_event_data_addr */
- IPA_ADDR_DEL_EVENT, /* no use */
+ IPA_ADDR_DEL_EVENT, /* ipacm_event_data_addr */
IPA_ROUTE_ADD_EVENT, /* ipacm_event_data_addr */
IPA_ROUTE_DEL_EVENT, /* ipacm_event_data_addr */
IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, /* ipacm_event_data_fid */
diff --git a/ipacm/inc/IPACM_Iface.h b/ipacm/inc/IPACM_Iface.h
index 35d12db..00c410a 100644
--- a/ipacm/inc/IPACM_Iface.h
+++ b/ipacm/inc/IPACM_Iface.h
@@ -103,7 +103,7 @@
uint32_t dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES];
/* create additional set of v6 RT-rules in Wanv6RT table*/
uint32_t dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*MAX_DEFAULT_v6_ROUTE_RULES];
-
+ uint32_t dft_rt_v6_glbl_idx;
ipa_ioc_query_intf *iface_query;
ipa_ioc_query_intf_tx_props *tx_prop;
ipa_ioc_query_intf_rx_props *rx_prop;
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 77954c7..e72c2be 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -60,6 +60,7 @@
#else
#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3
#endif
+#define MAX_DEFAULT_SEC_v6_ROUTE_RULES 1
#define NETWORK_STATS "%s %llu %llu %llu %llu"
#define IPA_NETWORK_STATS_FILE_NAME "/data/misc/ipa/network_stats"
@@ -351,6 +352,8 @@
uint32_t ODU_fl_hdl[IPA_NUM_DEFAULT_WAN_FILTER_RULES];
int num_firewall_v4,num_firewall_v6;
uint32_t wan_v4_addr;
+ uint32_t sec_wan_v4_addr;
+ bool sec_wan_v4_addr_set;
uint32_t wan_v4_addr_gw;
uint32_t wan_v6_addr_gw[4];
bool wan_v4_addr_set;
@@ -364,11 +367,19 @@
bool header_partial_default_wan_v6;
uint8_t ext_router_mac_addr[IPA_MAC_ADDR_SIZE];
uint8_t netdev_mac[IPA_MAC_ADDR_SIZE];
+ /* IPACM interface secondary v6 ip-addresses */
+ uint32_t sec_ipv6_addr[MAX_DEFAULT_SEC_v6_ROUTE_RULES][4];
/* create additional set of v4 Coalesce RT-rules: tcp udp */
uint32_t dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+ 2*MAX_DEFAULT_v6_ROUTE_RULES];
- /* create additional set of v4 low_lat RT-rules: tcp udp */
+ /* create additional set of v4 Coalesce RT-rules for secondary addresses: tcp udp */
+ uint32_t sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+ 2*MAX_DEFAULT_SEC_v6_ROUTE_RULES];
+
+ /* create additional set of v4/v6 low_lat RT-rules: tcp udp */
uint32_t dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+ MAX_DEFAULT_v6_ROUTE_RULES];
+ /* create additional set of v4/v6 low_lat RT-rules for seconday addresses: */
+ uint32_t sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+ MAX_DEFAULT_SEC_v6_ROUTE_RULES];
+
static int num_ipv4_modem_pdn;
static int num_ipv6_modem_pdn;
@@ -417,6 +428,12 @@
uint16_t mtu_v6;
bool mtu_v6_set;
+ /* IPACM number of default route rules for secondary ipv6 address*/
+ uint32_t sec_num_dft_rt_v6;
+
+ /* create additional set of v6 RT-rules for secondary addresses in Wanv6RT table*/
+ uint32_t sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*MAX_DEFAULT_SEC_v6_ROUTE_RULES];
+
inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt)
{
char *ret = ((char *)param) + (wan_client_len * cnt);
@@ -605,6 +622,9 @@
/* handle new_address event */
int handle_addr_evt(ipacm_event_data_addr *data);
+ /* handle del_address event */
+ int handle_addr_del_evt(ipacm_event_data_addr *data);
+
/* handle new_address event for q6_mhi */
int handle_addr_evt_mhi_q6(ipacm_event_data_addr *data);
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index a2e9b66..0be4695 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -470,6 +470,7 @@
IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, w);
if(is_sta_mode == Q6_WAN)
{
+ IPACM_EvtDispatcher::registr(IPA_ADDR_DEL_EVENT, w);
IPACM_EvtDispatcher::registr(IPA_NETWORK_STATS_UPDATE_EVENT, w);
#ifdef IPA_MTU_EVENT_MAX
IPACM_EvtDispatcher::registr(IPA_MTU_SET, w);
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index fa4b8b7..a32dd7f 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -878,6 +878,71 @@
}
break;
+ case RTM_DELADDR:
+ IPACMDBG("\n GOT RTM_DELADDR event\n");
+ if(IPACM_SUCCESS != ipa_nl_decode_rtm_addr(buffer, buflen, &(msg_ptr->nl_addr_info)))
+ {
+ IPACMERR("Failed to decode rtm addr message\n");
+ return IPACM_FAILURE;
+ }
+ else
+ {
+ ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_addr_info.metainfo.ifa_index);
+ if(ret_val != IPACM_SUCCESS)
+ {
+ IPACMERR("Error while getting interface name\n");
+ }
+ IPACMDBG("Interface %s \n", dev_name);
+
+ data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
+ if(data_addr == NULL)
+ {
+ IPACMERR("unable to allocate memory for event data_addr\n");
+ return IPACM_FAILURE;
+ }
+
+ if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family)
+ {
+ data_addr->iptype = IPA_IP_v6;
+ IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr );
+ IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr);
+ data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
+ data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
+ data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
+ data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
+ }
+ else
+ {
+ data_addr->iptype = IPA_IP_v4;
+ IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr );
+ IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr);
+ data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
+
+ }
+
+ evt_data.event = IPA_ADDR_DEL_EVENT;
+ data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index;
+ strlcpy(data_addr->iface_name, dev_name, sizeof(data_addr->iface_name));
+ if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family)
+ {
+ IPACMDBG("Posting IPA_ADDR_DEL_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
+ data_addr->if_index,
+ data_addr->ipv6_addr[0],
+ data_addr->ipv6_addr[1],
+ data_addr->ipv6_addr[2],
+ data_addr->ipv6_addr[3]);
+ }
+ else
+ {
+ IPACMDBG("Posting IPA_ADDR_DEL_EVENT with if index:%d, ipv4 addr:0x%x\n",
+ data_addr->if_index,
+ data_addr->ipv4_addr);
+ }
+ evt_data.evt_data = data_addr;
+ IPACM_EvtDispatcher::PostEvt(&evt_data);
+ }
+ break;
+
case RTM_NEWROUTE:
if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info)))
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index f0aef3c..1e01e5e 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -293,6 +293,7 @@
#ifdef FEATURE_IPACM_HAL
IPACM_OffloadManager* OffloadMng;
#endif
+ bool sec_addr = false;
memset(&hdr, 0, sizeof(hdr));
if(tx_prop == NULL || rx_prop == NULL)
@@ -306,18 +307,50 @@
if (data->iptype == IPA_IP_v6)
{
- for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
+ /* Check if Global address changed for WWAN backhaul. */
+ if ((m_is_sta_mode == Q6_WAN) && is_global_ipv6_addr(data->ipv6_addr) &&
+ (data->ipv6_addr[0] || data->ipv6_addr[1]) &&
+ (ipv6_prefix[0] || ipv6_prefix[1]) &&
+ !((ipv6_prefix[0] == data->ipv6_addr[0]) &&
+ (ipv6_prefix[1] == data->ipv6_addr[1])))
{
- if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
- (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
- (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
- (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
+ sec_addr = true;
+ }
+
+ if (sec_addr)
+ {
+ if (sec_num_dft_rt_v6 == MAX_DEFAULT_SEC_v6_ROUTE_RULES)
{
- IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
+ IPACMDBG_H("Secondary v6 addresses overflow:%d \n", sec_num_dft_rt_v6);
return IPACM_SUCCESS;
- break;
+ }
+ for(num_ipv6_addr=0;num_ipv6_addr<sec_num_dft_rt_v6;num_ipv6_addr++)
+ {
+ if((sec_ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
+ (sec_ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
+ (sec_ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
+ (sec_ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
+ {
+ IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
+ return IPACM_SUCCESS;
+ }
}
}
+ else
+ {
+ for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
+ {
+ if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
+ (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
+ (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
+ (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
+ {
+ IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
+ return IPACM_SUCCESS;
+ }
+ }
+ }
+
rt_rule = (struct ipa_ioc_add_rt_rule *)
calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
NUM_RULES * sizeof(struct ipa_rt_rule_add));
@@ -345,10 +378,21 @@
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
- ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
- ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
- ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
- ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
+ if (sec_addr)
+ {
+ sec_ipv6_addr[sec_num_dft_rt_v6][0] = data->ipv6_addr[0];
+ sec_ipv6_addr[sec_num_dft_rt_v6][1] = data->ipv6_addr[1];
+ sec_ipv6_addr[sec_num_dft_rt_v6][2] = data->ipv6_addr[2];
+ sec_ipv6_addr[sec_num_dft_rt_v6][3] = data->ipv6_addr[3];
+ }
+ else
+ {
+ ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
+ ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
+ ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
+ ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
+
+ }
if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
rt_rule_entry->rule.hashable = false;
if(m_is_sta_mode == Q6_WAN)
@@ -379,7 +423,10 @@
res = rt_rule_entry->status;
goto fail;
}
- dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
+ if (sec_addr)
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
+ else
+ dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
/* setup same rule for v6_wan table*/
strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
@@ -395,13 +442,24 @@
res = rt_rule_entry->status;
goto fail;
}
+ if (sec_addr)
+ {
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n",
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6],
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6+1],
+ MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6,
+ MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6+1);
+ }
+ else
+ {
dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
-
IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n",
dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],
MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6,
MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
+ }
/* RSC TCP rule*/
rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
@@ -423,10 +481,20 @@
res = rt_rule_entry->status;
goto fail;
}
+ if (sec_addr)
+ {
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d), entry %d", sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable,
+ 2*MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6);
+ }
+ else
+ {
dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
IPACMDBG_H("ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d), entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable,
2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6);
+ }
/* RSB UDP rule*/
rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
#ifdef IPA_RT_SUPPORT_COAL
@@ -446,11 +514,21 @@
IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
res = rt_rule_entry->status;
goto fail;
- }
+ }
+ if (sec_addr)
+ {
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d) entry %d", sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*sec_num_dft_rt_v6+1],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable,
+ 2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
+ }
+ else
+ {
dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
IPACMDBG_H("ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d) entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],
IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable,
2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
+ }
/* Low latency v6 rule*/
fd_wwan_ioctl = open(IPA_DEVICE_NAME, O_RDWR);
@@ -481,9 +559,20 @@
res = rt_rule_entry->status;
goto fail;
}
+
+ if (sec_addr)
+ {
+ sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv6 wan iface low lat udp rt-rule hdll=0x%x\n entry %d", sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES],
+ MAX_DEFAULT_v4_ROUTE_RULES + sec_num_dft_rt_v6);
+ }
+ else
+ {
dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
IPACMDBG_H("ipv6 wan iface low lat udp rt-rule hdll=0x%x\n entry %d", dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + num_dft_rt_v6],
MAX_DEFAULT_v4_ROUTE_RULES + num_dft_rt_v6);
+ }
+
}
}
else
@@ -528,7 +617,7 @@
}
/* add default filtering rules when wan-iface get global v6-prefix */
- if (num_dft_rt_v6 == 1)
+ if (!sec_addr && num_dft_rt_v6 == 1)
{
if(m_is_sta_mode == Q6_WAN)
{
@@ -619,12 +708,21 @@
}
}
}
- /* store ipv6 prefix if the ipv6 address is not link local */
- if(is_global_ipv6_addr(data->ipv6_addr))
+
+ if (sec_addr)
{
- memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix));
+ sec_num_dft_rt_v6++;
}
- num_dft_rt_v6++;
+ else
+ {
+ /* store ipv6 prefix if the ipv6 address is not link local */
+ if (is_global_ipv6_addr(data->ipv6_addr))
+ {
+ memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix));
+ dft_rt_v6_glbl_idx = num_dft_rt_v6;
+ }
+ num_dft_rt_v6++;
+ }
}
else
{
@@ -639,28 +737,19 @@
else
{
IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name);
- /* Delete default Coalese v4 RT rule */
if (m_is_sta_mode == Q6_WAN) {
- if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
- {
- IPACMERR("Routing old RSC TCP RT rule deletion failed!\n");
- res = IPACM_FAILURE;
- goto fail;
- }
- if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
- {
- IPACMERR("Routing old RSB UDP RT rule deletion failed!\n");
- res = IPACM_FAILURE;
- goto fail;
- }
+ sec_addr = true;
}
- /* Delete default v4 RT rule */
- IPACMDBG_H("Delete default v4 routing rules\n");
- if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ else
{
- IPACMERR("Routing old RT rule deletion failed!\n");
- res = IPACM_FAILURE;
- goto fail;
+ /* Delete default v4 RT rule */
+ IPACMDBG_H("Delete default v4 routing rules\n");
+ if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
}
}
}
@@ -716,9 +805,18 @@
IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
res = rt_rule_entry->status;
goto fail;
- }
- dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
- IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
+ }
+ if (sec_addr)
+ {
+ sec_dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv4 wan iface rt-rule hdll=0x%x\n",
+ sec_dft_rt_rule_hdl[0]);
+ }
+ else
+ {
+ dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
+ }
/* RSC TCP rule*/
rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
@@ -740,10 +838,19 @@
IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
res = rt_rule_entry->status;
goto fail;
- }
- dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
- IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0],
- IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
+ }
+ if (sec_addr)
+ {
+ sec_dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", sec_dft_coalesce_rt_rule_hdl[0],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
+ }
+ else
+ {
+ dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
+ }
/* RSB UDP rule*/
rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
@@ -765,9 +872,18 @@
res = rt_rule_entry->status;
goto fail;
}
- dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
- IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[1],
- IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
+ if (sec_addr)
+ {
+ sec_dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("Secondary ipv4 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", sec_dft_coalesce_rt_rule_hdl[1],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
+ }
+ else
+ {
+ dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[1],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
+ }
/* low latency v4 rule*/
fd_wwan_ioctl = open(IPA_DEVICE_NAME, O_RDWR);
@@ -798,9 +914,17 @@
res = rt_rule_entry->status;
goto fail;
}
+ if (sec_addr)
+ {
+ sec_dft_low_lat_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv4 low lat udp rt-rule hdll=0x%x\n", sec_dft_low_lat_rt_rule_hdl[0]);
+ }
+ else
+ {
dft_low_lat_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
IPACMDBG_H("ipv4 low lat udp rt-rule hdll=0x%x\n", dft_low_lat_rt_rule_hdl[0]);
}
+ }
}
else
{
@@ -845,13 +969,21 @@
}
}
- wan_v4_addr = data->ipv4_addr;
- wan_v4_addr_set = true;
+ if (m_is_sta_mode == Q6_WAN && sec_addr)
+ {
+ sec_wan_v4_addr = data->ipv4_addr;
+ sec_wan_v4_addr_set = true;
+ }
+ else
+ {
+ wan_v4_addr = data->ipv4_addr;
+ wan_v4_addr_set = true;
+ }
- if (m_is_sta_mode == Q6_WAN)
+ if (m_is_sta_mode == Q6_WAN && !sec_addr)
curr_wan_ip = data->ipv4_addr;
- IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr);
+ IPACMDBG_H("Receved wan ipv4-addr:0x%x, sec_addr:%d\n",data->ipv4_addr, sec_addr);
}
#ifdef FEATURE_IPACM_HAL
@@ -874,6 +1006,280 @@
return res;
}
+ /* handle del_address event */
+ int IPACM_Wan::handle_addr_del_evt(ipacm_event_data_addr *data)
+ {
+ bool result;
+
+ const int NUM_RULES = 1;
+ uint32_t num_ipv6_addr, rt_idx = 0;
+ int res = IPACM_SUCCESS,len;
+#ifdef FEATURE_IPACM_HAL
+ IPACM_OffloadManager* OffloadMng;
+#endif
+ bool sec_addr = false, pri_addr = false;
+ int i = 0;
+ bool wan_active = false;
+
+ if(tx_prop == NULL || rx_prop == NULL)
+ {
+ IPACMDBG_H("Either tx or rx property is NULL, return.\n");
+ return IPACM_SUCCESS;
+ }
+
+ if (data->iptype == IPA_IP_v6)
+ {
+ /* Check if the address deleted is primary or secondary address. */
+
+ for(num_ipv6_addr=0;num_ipv6_addr<sec_num_dft_rt_v6;num_ipv6_addr++)
+ {
+ if((sec_ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
+ (sec_ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
+ (sec_ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
+ (sec_ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
+ {
+ IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
+ sec_addr = true;
+ }
+ }
+
+ for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
+ {
+ if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
+ (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
+ (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
+ (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
+ {
+ IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
+ pri_addr = true;
+ rt_idx = num_ipv6_addr;
+ }
+ }
+
+ if (!sec_addr && !pri_addr)
+ {
+ IPACMDBG_H("Not matching Either Primary or Secondary addresses, return.\n");
+ return IPACM_SUCCESS;
+ }
+
+ if (sec_addr)
+ {
+ /* Clean up the rules. */
+ IPACMDBG_H("Delete Secondary v6 routing rules\n");
+ for (i = 0; i < 2; i++)
+ {
+ /* delete v6 colasce rules */
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Colasce Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ memset(sec_ipv6_addr, 0, sizeof(sec_ipv6_addr));
+ sec_num_dft_rt_v6 = 0;
+ return IPACM_SUCCESS;
+ }
+
+ if (pri_addr)
+ {
+ /* delete v6 colasce rules and copy secondary rules into Primary if applicable. */
+ IPACMDBG_H("Delete Primary v6 routing rules\n");
+ for (i = 0; i < MAX_DEFAULT_v6_ROUTE_RULES; i++)
+ {
+ if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*rt_idx+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Colasce Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ if (is_global_ipv6_addr(data->ipv6_addr) && sec_num_dft_rt_v6 > 0)
+ {
+ dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*rt_idx+i] =
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i];
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i] = 0;
+ IPACMDBG_H("Coalescing routing rule update, index: %d/%d, hdl:%d\n",
+ rt_idx, 2*rt_idx+i,
+ dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*rt_idx+i]);
+ }
+ if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*rt_idx+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ if (is_global_ipv6_addr(data->ipv6_addr) && sec_num_dft_rt_v6 > 0)
+ {
+ dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*rt_idx+i] =
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i];
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i] = 0;
+ IPACMDBG_H("Default routing rule update, index: %d/%d, hdl:%d\n",
+ rt_idx, 2*rt_idx+i,
+ dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*rt_idx+i]);
+ }
+ }
+
+ /* Delete low lat rules. */
+ if (m_routing.DeleteRoutingHdl(dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+rt_idx], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ /* Copy secondary rules into Primary. */
+ if (is_global_ipv6_addr(data->ipv6_addr) && sec_num_dft_rt_v6 > 0)
+ {
+ dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+rt_idx] =
+ sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES];
+ }
+
+ if (is_global_ipv6_addr(data->ipv6_addr) && sec_num_dft_rt_v6 > 0)
+ {
+ if (active_v6)
+ {
+ post_wan_down_tether_evt(IPA_IP_v6, 0);
+ del_wan_firewall_rule(IPA_IP_v6);
+ handle_route_del_evt_ex(IPA_IP_v6);
+ wan_active = true;
+ }
+ /* Copy Secondary Address onto Primary. */
+ ipv6_addr[rt_idx][0] = sec_ipv6_addr[sec_num_dft_rt_v6-1][0];
+ ipv6_addr[rt_idx][1] = sec_ipv6_addr[sec_num_dft_rt_v6-1][1];
+ ipv6_addr[rt_idx][2] = sec_ipv6_addr[sec_num_dft_rt_v6-1][2];
+ ipv6_addr[rt_idx][3] = sec_ipv6_addr[sec_num_dft_rt_v6-1][3];
+ memcpy(ipv6_prefix, sec_ipv6_addr[sec_num_dft_rt_v6-1], sizeof(ipv6_prefix));
+ memset(sec_ipv6_addr[sec_num_dft_rt_v6-1], 0, sizeof(sec_ipv6_addr[sec_num_dft_rt_v6-1]));
+ sec_num_dft_rt_v6--;
+ IPACMDBG_H("Secondary v6 num %d: \n",sec_num_dft_rt_v6);
+ if (wan_active)
+ {
+ handle_route_add_evt(IPA_IP_v6);
+ }
+ }
+ else
+ {
+ num_dft_rt_v6--;
+ IPACMDBG_H("v6 num %d: \n",num_dft_rt_v6);
+ }
+ }
+ }
+ else
+ {
+ if (data->ipv4_addr == sec_wan_v4_addr)
+ {
+ IPACMDBG_H("Delete Secondary coalescing v4 routing rules\n");
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RSC TCP RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ sec_dft_coalesce_rt_rule_hdl[0] = 0;
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RSB UDP RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ sec_dft_coalesce_rt_rule_hdl[1] = 0;
+ IPACMDBG_H("Delete Secondary v4 default routing rules\n");
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ sec_dft_rt_rule_hdl[0] = 0;
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule low lat deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ sec_dft_low_lat_rt_rule_hdl[0] = 0;
+ sec_wan_v4_addr_set = false;
+ sec_wan_v4_addr = 0;
+ return IPACM_SUCCESS;
+ }
+ else if (data->ipv4_addr == wan_v4_addr)
+ {
+
+ IPACMDBG_H("Delete default coalescing v4 routing rules\n");
+ if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RSC TCP RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ dft_coalesce_rt_rule_hdl[0] = sec_dft_coalesce_rt_rule_hdl[0];
+ sec_dft_coalesce_rt_rule_hdl[0] = 0;
+ if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RSB UDP RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ dft_coalesce_rt_rule_hdl[1] = sec_dft_coalesce_rt_rule_hdl[1];
+ sec_dft_coalesce_rt_rule_hdl[1] = 0;
+ IPACMDBG_H("New coalescing routing rule hdls:%d:%d\n",
+ dft_coalesce_rt_rule_hdl[0],dft_coalesce_rt_rule_hdl[1]);
+ IPACMDBG_H("Delete default v4 routing rules\n");
+ if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ dft_rt_rule_hdl[0] = sec_dft_rt_rule_hdl[0];
+ IPACMDBG_H("New default rule routing rule hdl:%d\n",
+ dft_rt_rule_hdl[0]);
+ if (m_routing.DeleteRoutingHdl(dft_low_lat_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RT rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ dft_low_lat_rt_rule_hdl[0] = sec_dft_low_lat_rt_rule_hdl[0];
+ IPACMDBG_H("New default rule low lat routing rule hdl:%d\n",
+ sec_dft_low_lat_rt_rule_hdl[0]);
+
+ /* Post WAN_DOWN with old ip address. */
+ if (active_v4)
+ {
+ post_wan_down_tether_evt(IPA_IP_v4, 0);
+ del_wan_firewall_rule(IPA_IP_v4);
+ handle_route_del_evt_ex(IPA_IP_v4);
+ wan_active = true;
+ }
+ wan_v4_addr = sec_wan_v4_addr;
+ IPACMDBG_H("WAN IPv4 address:0x%x\n",
+ wan_v4_addr);
+ sec_wan_v4_addr_set = false;
+ sec_wan_v4_addr = 0;
+ /* Post WAN_UP with new ip address. */
+ if (wan_active)
+ {
+ handle_route_add_evt(IPA_IP_v4);
+ }
+ }
+ }
+fail:
+ return res;
+ }
+
+
/* handle new_address event */
int IPACM_Wan::handle_addr_evt_mhi_q6(ipacm_event_data_addr *data)
{
@@ -1305,9 +1711,11 @@
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG_H("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype);
- /* check v4 not setup before, v6 can have 2 iface ip */
+ /* check v4 not setup before, v6 can have 2 iface ip or secondary ipv6 address. */
if( (data->iptype == IPA_IP_v4)
- || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES)))
+ || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))
+ || ((data->iptype==IPA_IP_v6) && is_global_ipv6_addr(data->ipv6_addr)
+ && (m_is_sta_mode == Q6_WAN) && sec_num_dft_rt_v6 != MAX_DEFAULT_SEC_v6_ROUTE_RULES) )
{
if (m_is_sta_mode == Q6_MHI_WAN)
{
@@ -1335,9 +1743,31 @@
handle_software_routing_enable(false);
}
}
-
+ }
}
}
+ break;
+
+ case IPA_ADDR_DEL_EVENT:
+ {
+ ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
+ ipa_interface_index = iface_ipa_index_query(data->if_index);
+
+ if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) ||
+ (data->iptype == IPA_IP_v6 &&
+ data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 &&
+ data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) )
+ {
+ IPACMDBG_H("Invalid address, ignore IPA_ADDR_DEL_EVENT event\n");
+ return;
+ }
+
+ if (ipa_interface_index == ipa_if_num)
+ {
+ IPACMDBG_H("Get IPA_ADDR_DEL_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype);
+ IPACMDBG_H("v6 num %d: \n",num_dft_rt_v6);
+ handle_addr_del_evt(data);
+ }
}
break;
@@ -5891,6 +6321,41 @@
res = IPACM_FAILURE;
goto fail;
}
+
+ if (sec_wan_v4_addr_set)
+ {
+ IPACMDBG_H("Delete Secondary v4 coalesce routing rules\n");
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule RSC TCP deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule RSB UDP deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule low lat deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ sec_wan_v4_addr_set = false;
+ sec_wan_v4_addr = 0;
+ }
}
else if(ip_type == IPA_IP_v6)
{
@@ -5957,6 +6422,7 @@
goto fail;
}
}
+
/* Delete v6 low lat rules */
for (i = 0; i < num_dft_rt_v6; i++)
{
@@ -5967,6 +6433,36 @@
goto fail;
}
}
+
+ if (sec_num_dft_rt_v6)
+ {
+ /* Clean up the rules. */
+ IPACMDBG_H("Delete Secondary v6 routing rules\n");
+ for (i = 0; i < 2; i++)
+ {
+ /* delete v6 colasce rules */
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Colasce Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ memset(sec_ipv6_addr, 0, sizeof(sec_ipv6_addr));
+ sec_num_dft_rt_v6 = 0;
+ }
}
else
{
@@ -6073,6 +6569,41 @@
goto fail;
}
+ if (sec_wan_v4_addr_set)
+ {
+ IPACMDBG_H("Delete Secondary v4 coalesce routing rules\n");
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule RSC TCP deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule RSB UDP deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Secondary Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ sec_wan_v4_addr_set = false;
+ sec_wan_v4_addr = 0;
+ }
+
for (i = 0; i < 2*num_dft_rt_v6; i++)
{
/* delete v6 colasce rules */
@@ -6089,6 +6620,7 @@
goto fail;
}
}
+
for (i = 0; i < num_dft_rt_v6; i++)
{
if (m_routing.DeleteRoutingHdl(dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
@@ -6098,6 +6630,36 @@
goto fail;
}
}
+
+ if (sec_num_dft_rt_v6)
+ {
+ /* Clean up the rules. */
+ IPACMDBG_H("Delete Secondary v6 routing rules\n");
+ for (i = 0; i < 2; i++)
+ {
+ /* delete v6 colasce rules */
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Colasce Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_low_lat_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ memset(sec_ipv6_addr, 0, sizeof(sec_ipv6_addr));
+ sec_num_dft_rt_v6 = 0;
+ }
}
// /* check software routing fl rule hdl */
@@ -7642,6 +8204,136 @@
fail:
free(rt_rule);
}
+
+ if(sec_wan_v4_addr_set)
+ {
+ /* Delete secondary default RSC v4 RT rule */
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Sec Routing old RSC TCP RT rule deletion failed!\n");
+ return IPACM_FAILURE;
+ }
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
+ {
+ IPACMERR("Sec Routing old RSB UDP RT rule deletion failed!\n");
+ return IPACM_FAILURE;
+ }
+ /* Delete secondary default v4 RT rule */
+ IPACMDBG_H("Delete Secondary default v4 routing rules\n");
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[0], IPA_IP_v4) == false)
+ {
+ IPACMERR("Routing old RT rule deletion failed!\n");
+ return IPACM_FAILURE;
+ }
+
+ /* apply the new coalesce configuration for secondary address. */
+ rt_rule = (struct ipa_ioc_add_rt_rule *)
+ calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
+ NUM_RULES * sizeof(struct ipa_rt_rule_add));
+ if (!rt_rule)
+ {
+ IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
+ return IPACM_FAILURE;
+ }
+ rt_rule->commit = 1;
+ rt_rule->num_rules = NUM_RULES;
+ rt_rule->ip = IPA_IP_v4;
+ rt_rule_entry = &rt_rule->rules[0];
+ rt_rule_entry->at_rear = true;
+ rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
+ /* still need setup v4 default routing rule to APPs*/
+ strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
+ rt_rule_entry->rule.attrib.u.v4.dst_addr = sec_wan_v4_addr;
+ rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
+ if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+ rt_rule_entry->rule.hashable = false;
+ /* query qmap header*/
+ memset(&hdr, 0, sizeof(hdr));
+ strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
+ hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+ if(m_header.GetHeaderHandle(&hdr) == false)
+ {
+ IPACMERR("Failed to get QMAP header.\n");
+ res = IPACM_FAILURE;
+ goto fail1;
+ }
+ rt_rule_entry->rule.hdr_hdl = hdr.hdl;
+ rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
+
+ /* RSB UDP rule*/
+ rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
+ rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
+#ifdef IPA_RT_SUPPORT_COAL
+ if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
+ rt_rule_entry->rule.coalesce = true;
+ else
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail1;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail1;
+ }
+ sec_dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv4 wan iface rsb udp rt-rule hdll=0x%x enable(%d)\n", sec_dft_coalesce_rt_rule_hdl[1],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
+
+ /* RSC TCP rule*/
+ rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
+#ifdef IPA_RT_SUPPORT_COAL
+ if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
+ rt_rule_entry->rule.coalesce = true;
+ else
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail1;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail1;
+ }
+ sec_dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", sec_dft_coalesce_rt_rule_hdl[0],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
+
+ /* secondary default v4 rt-rule */
+ rt_rule_entry->rule.attrib.attrib_mask &= ~IPA_FLT_PROTOCOL;
+#ifdef IPA_RT_SUPPORT_COAL
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ /* Secondary default v4 rt-rule */
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail1;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail1;
+ }
+ sec_dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv4 wan iface rt-rule hdll=0x%x\n", sec_dft_rt_rule_hdl[0]);
+
+fail1:
+ free(rt_rule);
+ }
+
/* v6 */
if (num_dft_rt_v6 !=0)
{
@@ -7793,6 +8485,159 @@
fail2:
free(rt_rule);
}
+
+ /* Secondary v6 */
+ if (sec_num_dft_rt_v6 !=0)
+ {
+ for (i = 0; i < 2*sec_num_dft_rt_v6; i++)
+ {
+ /* delete secondary v6 colasce rules */
+ if (m_routing.DeleteRoutingHdl(sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Colasce Routing rule deletion failed!\n");
+ return IPACM_FAILURE;
+ }
+ /* delete secondary v6 default rules */
+ if (m_routing.DeleteRoutingHdl(sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
+ {
+ IPACMERR("Routing rule deletion failed!\n");
+ return IPACM_FAILURE;
+ }
+ }
+
+ rt_rule = (struct ipa_ioc_add_rt_rule *)
+ calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
+ NUM_RULES * sizeof(struct ipa_rt_rule_add));
+ if (!rt_rule)
+ {
+ IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
+ return IPACM_FAILURE;
+ }
+ rt_rule->commit = 1;
+ rt_rule->num_rules = NUM_RULES;
+ rt_rule->ip = IPA_IP_v6;
+
+ for (i = 0; i < sec_num_dft_rt_v6; i++)
+ {
+ /* setup same rule for v6_wan table */
+ strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
+ rt_rule_entry = &rt_rule->rules[0];
+ rt_rule_entry->at_rear = true;
+ rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = sec_ipv6_addr[i][0];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = sec_ipv6_addr[i][1];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = sec_ipv6_addr[i][2];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = sec_ipv6_addr[i][3];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
+ if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+ rt_rule_entry->rule.hashable = false;
+ strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
+ hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+ if(m_header.GetHeaderHandle(&hdr) == false)
+ {
+ IPACMERR("Failed to get QMAP header.\n");
+ return IPACM_FAILURE;
+ }
+ rt_rule_entry->rule.hdr_hdl = hdr.hdl;
+ rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
+
+ /* Secondary RSB UDP rule*/
+ rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
+ rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
+#ifdef IPA_RT_SUPPORT_COAL
+ if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable)
+ rt_rule_entry->rule.coalesce = true;
+ else
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail3;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail3;
+ }
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
+
+ /* Secondary RSC TCP rule*/
+ rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
+#ifdef IPA_RT_SUPPORT_COAL
+ if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
+ rt_rule_entry->rule.coalesce = true;
+ else
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail3;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail3;
+ }
+ sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", sec_dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i],
+ IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
+
+ /* legacy default secondary v6 rt-rule */
+ rt_rule_entry->rule.attrib.attrib_mask &= ~IPA_FLT_NEXT_HDR;
+#ifdef IPA_RT_SUPPORT_COAL
+ rt_rule_entry->rule.coalesce = false;
+#endif
+ /* legacy default secondary v6 rt-rule */
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail3;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("secondary rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail3;
+ }
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl;
+
+ /* setup same rule for v6_lan table*/
+ strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ res = IPACM_FAILURE;
+ goto fail3;
+ }
+ else if (rt_rule_entry->status)
+ {
+ IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
+ res = rt_rule_entry->status;
+ goto fail3;
+ }
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl;
+ IPACMDBG_H("secondary ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n",
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i],
+ sec_dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1],
+ MAX_DEFAULT_v4_ROUTE_RULES + 2*i,
+ MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1);
+ }
+fail3:
+ free(rt_rule);
+ }
+
return res;
}