blob: 45b24fc07b0a3c4ca42b64130d95e14e961e7b51 [file] [log] [blame]
/*
Copyright (c) 2013, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*!
@file
IPACM_Wlan.cpp
@brief
This file implements the WLAN iface functionality.
@Author
Skylar Chang
*/
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <IPACM_Wlan.h>
#include <IPACM_Netlink.h>
#include <fcntl.h>
#include <sys/inotify.h>
#include <IPACM_Wan.h>
#include <IPACM_Lan.h>
#include <IPACM_IfaceManager.h>
/* static member to store the number of total wifi clients within all APs*/
int IPACM_Wlan::total_num_wifi_clients = 0;
IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index)
{
#define WLAN_AMPDU_DEFAULT_FILTER_RULES 3
num_wifi_client = 0;
header_name_count = 0;
/* one for WAN and two for Soft-routing */
wlan_ampdu_flt_rule.num_rules = WLAN_AMPDU_DEFAULT_FILTER_RULES;
wlan_ampdu_flt_rule.hdl[0] = 0; /* for WAN */
wlan_ampdu_flt_rule.ip[0] = IPA_IP_v4; /* for WAN */
wlan_ampdu_flt_rule.hdl[1] = 0; /* for Soft-routing */
wlan_ampdu_flt_rule.ip[1] = IPA_IP_v4; /* for Soft-routing */
wlan_ampdu_flt_rule.hdl[2] = 0; /* for Soft-routing */
wlan_ampdu_flt_rule.ip[2] = IPA_IP_v6; /* for Soft-routing */
wlan_client_len = (sizeof(ipa_wlan_client)) + (iface_query->num_tx_props * sizeof(wlan_client_rt_hdl));
wlan_client = (ipa_wlan_client *)calloc(IPA_MAX_NUM_WIFI_CLIENTS, wlan_client_len);
if (wlan_client == NULL)
{
IPACMERR("unable to allocate memory\n");
return;
}
Nat_App = NatApp::GetInstance();
if (Nat_App == NULL)
{
IPACMERR("unable to get Nat App instance \n");
return;
}
IPACMDBG("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props);
return;
}
IPACM_Wlan::~IPACM_Wlan()
{
IPACM_EvtDispatcher::deregistr(this);
IPACM_IfaceManager::deregistr(this);
return;
}
void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
{
int ipa_interface_index;
int wlan_index;
switch (event)
{
case IPA_LINK_DOWN_EVENT:
{
ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_LINK_DOWN_EVENT\n");
handle_down_evt();
IPACMDBG("ipa_WLAN (%s):ipa_index (%d) instance close \n",
IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
/* reset the AP-iface category to unknown */
IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat=UNKNOWN_IF;
IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
delete this;
return;
}
}
break;
case IPA_ADDR_ADD_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("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n");
return;
}
if (ipa_interface_index == ipa_if_num)
{
/* check v4 not setup before, v6 can have 2 iface ip */
if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX))
|| ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES)))
{
IPACMDBG("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6);
/* Post event to NAT */
if (data->iptype == IPA_IP_v4)
{
ipacm_cmd_q_data evt_data;
ipacm_event_iface_up *info;
info = (ipacm_event_iface_up *)
malloc(sizeof(ipacm_event_iface_up));
if (info == NULL)
{
IPACMERR("Unable to allocate memory\n");
return;
}
memcpy(info->ifname, dev_name, IF_NAME_LEN);
info->ipv4_addr = data->ipv4_addr;
info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask;
evt_data.event = IPA_HANDLE_WLAN_UP;
evt_data.evt_data = (void *)info;
/* Insert IPA_HANDLE_WLAN_UP to command queue */
IPACMDBG("posting IPA_HANDLE_WLAN_UP for IPv4 with below information\n");
IPACMDBG("IPv4 address:0x%x, IPv4 address mask:0x%x\n",
info->ipv4_addr, info->addr_mask);
IPACM_EvtDispatcher::PostEvt(&evt_data);
}
IPACM_Lan::handle_addr_evt(data);
handle_addr_evt(data);
IPACM_Lan::handle_private_subnet(data->iptype);
handle_private_subnet(data->iptype);
if (IPACM_Wan::isWanUP() && (data->iptype == IPA_IP_v4))
{
IPACM_Lan::handle_wan_up();
handle_wan_up();
}
IPACMDBG("posting IPA_HANDLE_WLAN_UP:Finished checking wan_up\n");
}
}
}
break;
case IPA_HANDLE_WAN_UP:
IPACMDBG("Received IPA_HANDLE_WAN_UP event\n");
IPACM_Lan::handle_wan_up();
handle_wan_up();
break;
case IPA_HANDLE_WAN_DOWN:
IPACMDBG("Received IPA_HANDLE_WAN_DOWN event\n");
if (rx_prop != NULL)
{
IPACM_Lan::handle_wan_down();
}
handle_wan_down();
break;
case IPA_WLAN_CLIENT_ADD_EVENT:
{
ipacm_event_data_mac *data = (ipacm_event_data_mac *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_WLAN_CLIENT_ADD_EVENT\n");
handle_wlan_client_init(data->mac_addr);
}
}
break;
case IPA_WLAN_CLIENT_DEL_EVENT:
{
ipacm_event_data_mac *data = (ipacm_event_data_mac *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_WLAN_CLIENT_DEL_EVENT\n");
handle_wlan_client_down_evt(data->mac_addr);
}
}
break;
case IPA_WLAN_CLIENT_POWER_SAVE_EVENT:
{
ipacm_event_data_mac *data = (ipacm_event_data_mac *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_WLAN_CLIENT_POWER_SAVE_EVENT\n");
handle_wlan_client_pwrsave(data->mac_addr);
}
}
break;
case IPA_WLAN_CLIENT_RECOVER_EVENT:
{
ipacm_event_data_mac *data = (ipacm_event_data_mac *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_WLAN_CLIENT_RECOVER_EVENT\n");
wlan_index = get_wlan_client_index(data->mac_addr);
if ((wlan_index != IPACM_INVALID_INDEX) &&
(get_client_memptr(wlan_client, wlan_index)->power_save_set == true))
{
IPACMDBG("change wlan client out of power safe mode \n");
get_client_memptr(wlan_client, wlan_index)->power_save_set = false;
/* First add route rules and then nat rules */
if(get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) /* for ipv4 */
{
IPACMDBG("recover client index(%d):ipv4 address: 0x%x\n",
wlan_index,
get_client_memptr(wlan_client, wlan_index)->v4_addr);
IPACMDBG("Adding Route Rules\n");
handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v4);
IPACMDBG("Adding Nat Rules\n");
Nat_App->ResetPwrSaveIf(get_client_memptr(wlan_client, wlan_index)->v4_addr);
}
if(get_client_memptr(wlan_client, wlan_index)->ipv6_set == true) /* for ipv6 */
{
handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v6);
}
}
}
}
break;
case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
{
ipacm_event_data_all *data = (ipacm_event_data_all *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT\n");
if (handle_wlan_client_ipaddr(data) == IPACM_FAILURE)
{
return;
}
handle_wlan_client_route_rule(data->mac_addr, data->iptype);
}
}
break;
/* handle software routing enable event, iface will update softwarerouting_act to true*/
case IPA_SW_ROUTING_ENABLE:
IPACMDBG("Received IPA_SW_ROUTING_ENABLE\n");
handle_software_routing_enable();
IPACM_Iface::handle_software_routing_enable();
break;
/* handle software routing disable event, iface will update softwarerouting_act to false*/
case IPA_SW_ROUTING_DISABLE:
IPACMDBG("Received IPA_SW_ROUTING_DISABLE\n");
handle_software_routing_disable();
IPACM_Iface::handle_software_routing_disable();
break;
default:
break;
}
return;
}
/* handle wifi client initial,copy all partial headers (tx property) */
int IPACM_Wlan::handle_wlan_client_init(uint8_t *mac_addr)
{
#define WLAN_IFACE_INDEX_LEN 2
int res = IPACM_SUCCESS, len = 0;
char index[WLAN_IFACE_INDEX_LEN];
struct ipa_ioc_copy_hdr sCopyHeader;
struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
uint32_t cnt;
int clnt_indx;
clnt_indx = get_wlan_client_index(mac_addr);
if (clnt_indx != IPACM_INVALID_INDEX)
{
IPACMERR("wlan is found/attached already with index %d \n", clnt_indx);
return IPACM_FAILURE;
}
/* start of adding header */
if ((num_wifi_client >= IPA_MAX_NUM_WIFI_CLIENTS) ||
(IPACM_Wlan::total_num_wifi_clients >= IPA_MAX_NUM_WIFI_CLIENTS))
{
IPACMERR("Reached maximum number of wlan clients\n");
return IPACM_FAILURE;
}
IPACMDBG("Wifi client number: %d\n", num_wifi_client);
IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac,
mac_addr,
sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac));
IPACMDBG("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
get_client_memptr(wlan_client, num_wifi_client)->mac[0],
get_client_memptr(wlan_client, num_wifi_client)->mac[1],
get_client_memptr(wlan_client, num_wifi_client)->mac[2],
get_client_memptr(wlan_client, num_wifi_client)->mac[3],
get_client_memptr(wlan_client, num_wifi_client)->mac[4],
get_client_memptr(wlan_client, num_wifi_client)->mac[5]);
/* add header to IPA */
if(tx_prop != NULL)
{
len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
if (pHeaderDescriptor == NULL)
{
IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
return IPACM_FAILURE;
}
/* copy partial header for v4*/
for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
{
if(tx_prop->tx[cnt].ip==IPA_IP_v4)
{
IPACMDBG("Got partial v4-header name from %d tx props\n", cnt);
memset(&sCopyHeader, 0, sizeof(sCopyHeader));
memcpy(sCopyHeader.name,
tx_prop->tx[cnt].hdr_name,
sizeof(sCopyHeader.name));
IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
if (m_header.CopyHeader(&sCopyHeader) == false)
{
PERROR("ioctl copy header failed");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
{
IPACMERR("header oversize\n");
res = IPACM_FAILURE;
goto fail;
}
else
{
memcpy(pHeaderDescriptor->hdr[0].hdr,
sCopyHeader.hdr,
sCopyHeader.hdr_len);
}
/* copy client mac_addr to partial header */
memcpy(&pHeaderDescriptor->hdr[0].hdr[IPA_WLAN_PARTIAL_HDR_OFFSET],
get_client_memptr(wlan_client, num_wifi_client)->mac,
IPA_MAC_ADDR_SIZE);
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
memset(pHeaderDescriptor->hdr[0].name, 0,
sizeof(pHeaderDescriptor->hdr[0].name));
sprintf(index, "%d", ipa_if_num);
strncpy(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
strncat(pHeaderDescriptor->hdr[0].name,
IPA_WLAN_PARTIAL_HDR_NAME_v4,
sizeof(IPA_WLAN_PARTIAL_HDR_NAME_v4));
sprintf(index, "%d", header_name_count);
strncat(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
pHeaderDescriptor->hdr[0].hdr_hdl = -1;
pHeaderDescriptor->hdr[0].is_partial = 0;
pHeaderDescriptor->hdr[0].status = -1;
if (m_header.AddHeader(pHeaderDescriptor) == false ||
pHeaderDescriptor->hdr[0].status != 0)
{
IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
res = IPACM_FAILURE;
goto fail;
}
get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
IPACMDBG("client(%d) v4 full header name:%s header handle:(0x%x)\n",
num_wifi_client,
pHeaderDescriptor->hdr[0].name,
get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4);
get_client_memptr(wlan_client, num_wifi_client)->ipv4_header_set=true;
break;
}
}
/* copy partial header for v6*/
for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
{
if(tx_prop->tx[cnt].ip==IPA_IP_v6)
{
IPACMDBG("Got partial v6-header name from %d tx props\n", cnt);
memset(&sCopyHeader, 0, sizeof(sCopyHeader));
memcpy(sCopyHeader.name,
tx_prop->tx[cnt].hdr_name,
sizeof(sCopyHeader.name));
IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
if (m_header.CopyHeader(&sCopyHeader) == false)
{
PERROR("ioctl copy header failed");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
{
IPACMERR("header oversize\n");
res = IPACM_FAILURE;
goto fail;
}
else
{
memcpy(pHeaderDescriptor->hdr[0].hdr,
sCopyHeader.hdr,
sCopyHeader.hdr_len);
}
/* copy client mac_addr to partial header */
memcpy(&pHeaderDescriptor->hdr[0].hdr[IPA_WLAN_PARTIAL_HDR_OFFSET],
get_client_memptr(wlan_client, num_wifi_client)->mac,
IPA_MAC_ADDR_SIZE);
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
memset(pHeaderDescriptor->hdr[0].name, 0,
sizeof(pHeaderDescriptor->hdr[0].name));
sprintf(index, "%d", ipa_if_num);
strncpy(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
strncat(pHeaderDescriptor->hdr[0].name,
IPA_WLAN_PARTIAL_HDR_NAME_v6,
sizeof(IPA_WLAN_PARTIAL_HDR_NAME_v6));
sprintf(index, "%d", header_name_count);
strncat(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
pHeaderDescriptor->hdr[0].hdr_hdl = -1;
pHeaderDescriptor->hdr[0].is_partial = 0;
pHeaderDescriptor->hdr[0].status = -1;
if (m_header.AddHeader(pHeaderDescriptor) == false ||
pHeaderDescriptor->hdr[0].status != 0)
{
IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
res = IPACM_FAILURE;
goto fail;
}
get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
IPACMDBG("client(%d) v6 full header name:%s header handle:(0x%x)\n",
num_wifi_client,
pHeaderDescriptor->hdr[0].name,
get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6);
get_client_memptr(wlan_client, num_wifi_client)->ipv6_header_set=true;
break;
}
}
}
/* initialize wifi client*/
get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false;
get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0;
get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false;
get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0;
get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false;
num_wifi_client++;
header_name_count++; //keep increasing header_name_count
IPACM_Wlan::total_num_wifi_clients++;
res = IPACM_SUCCESS;
IPACMDBG("Wifi client number: %d\n", num_wifi_client);
fail:
free(pHeaderDescriptor);
return res;
}
/*handle wifi client */
int IPACM_Wlan::handle_wlan_client_ipaddr(ipacm_event_data_all *data)
{
int clnt_indx;
int v6_num;
IPACMDBG("number of wifi clients: %d\n", num_wifi_client);
IPACMDBG(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
data->mac_addr[0],
data->mac_addr[1],
data->mac_addr[2],
data->mac_addr[3],
data->mac_addr[4],
data->mac_addr[5]);
clnt_indx = get_wlan_client_index(data->mac_addr);
if (clnt_indx == IPACM_INVALID_INDEX)
{
IPACMERR("wlan client not found/attached \n");
return IPACM_FAILURE;
}
IPACMDBG("Ip-type received %d\n", data->iptype);
if (data->iptype == IPA_IP_v4)
{
IPACMDBG("ipv4 address: 0x%x\n", data->ipv4_addr);
if (data->ipv4_addr != 0) /* not 0.0.0.0 */
{
if (get_client_memptr(wlan_client, clnt_indx)->ipv4_set == false)
{
get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr;
get_client_memptr(wlan_client, clnt_indx)->ipv4_set = true;
}
else
{
/* check if client got new IPv4 address*/
if(data->ipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr)
{
IPACMDBG("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
return IPACM_FAILURE;
}
else
{
IPACMDBG("ipv4 addr for client:%d is changed \n", clnt_indx);
delete_default_qos_rtrules(clnt_indx,IPA_IP_v4);
get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false;
get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr;
}
}
}
else
{
IPACMDBG("Invalid client IPv4 address \n");
return IPACM_FAILURE;
}
}
else
{
if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */
{
IPACMDBG("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
if(get_client_memptr(wlan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)
{
for(v6_num=0;v6_num < get_client_memptr(wlan_client, clnt_indx)->ipv6_set;v6_num++)
{
if( data->ipv6_addr[0] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][0] &&
data->ipv6_addr[1] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][1] &&
data->ipv6_addr[2]== get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][2] &&
data->ipv6_addr[3] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][3])
{
IPACMDBG("Already see this ipv6 addr for client:%d\n", clnt_indx);
return IPACM_FAILURE; /* not setup the RT rules*/
break;
}
}
/* not see this ipv6 before for wifi client*/
get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
get_client_memptr(wlan_client, clnt_indx)->ipv6_set++;
}
else
{
IPACMDBG("Already got 3 ipv6 addr for client:%d\n", clnt_indx);
return IPACM_FAILURE; /* not setup the RT rules*/
}
}
}
return IPACM_SUCCESS;
}
/*handle wifi client routing rule*/
int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
{
struct ipa_ioc_add_rt_rule *rt_rule;
struct ipa_rt_rule_add *rt_rule_entry;
uint32_t tx_index;
int wlan_index,v6_num;
const int NUM = 1;
if(tx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
IPACMDBG("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
wlan_index = get_wlan_client_index(mac_addr);
if (wlan_index == IPACM_INVALID_INDEX)
{
IPACMDBG("wlan client not found/attached \n");
return IPACM_SUCCESS;
}
/* during power_save mode, even receive IP_ADDR_ADD, not setting RT rules*/
if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true)
{
IPACMDBG("wlan client is in power safe mode \n");
return IPACM_SUCCESS;
}
if (iptype==IPA_IP_v4)
{
IPACMDBG("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wlan_index, iptype,
get_client_memptr(wlan_client, wlan_index)->ipv4_set,
get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4);
}
else
{
IPACMDBG("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype,
get_client_memptr(wlan_client, wlan_index)->ipv6_set,
get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6);
}
/* Add default Qos routing rules if not set yet */
if ((iptype == IPA_IP_v4
&& get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 == false
&& get_client_memptr(wlan_client, wlan_index)->ipv4_set == true)
|| (iptype == IPA_IP_v6
&& get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < get_client_memptr(wlan_client, wlan_index)->ipv6_set
))
{
rt_rule = (struct ipa_ioc_add_rt_rule *)
calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
NUM * sizeof(struct ipa_rt_rule_add));
if (rt_rule == NULL)
{
PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n");
return IPACM_FAILURE;
}
rt_rule->commit = 1;
rt_rule->num_rules = (uint8_t)NUM;
rt_rule->ip = iptype;
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
if(iptype != tx_prop->tx[tx_index].ip)
{
IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
tx_index, tx_prop->tx[tx_index].ip,iptype);
continue;
}
rt_rule_entry = &rt_rule->rules[0];
rt_rule_entry->at_rear = 0;
if (iptype == IPA_IP_v4)
{
IPACMDBG("client index(%d):ipv4 address: 0x%x\n", wlan_index,
get_client_memptr(wlan_client, wlan_index)->v4_addr);
IPACMDBG("client(%d): v4 header handle:(0x%x)\n",
wlan_index,
get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4);
strncpy(rt_rule->rt_tbl_name,
IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name,
sizeof(rt_rule->rt_tbl_name));
rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
memcpy(&rt_rule_entry->rule.attrib,
&tx_prop->tx[tx_index].attrib,
sizeof(rt_rule_entry->rule.attrib));
rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4;
rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr;
rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
if (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
/* copy ipv4 RT hdl */
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 =
rt_rule->rules[0].rt_rule_hdl;
IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype);
}
else
{
for(v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6;v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set;v6_num++)
{
IPACMDBG("client(%d): v6 header handle:(0x%x)\n",
wlan_index,
get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6);
/* v6 LAN_RT_TBL */
strncpy(rt_rule->rt_tbl_name,
IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
sizeof(rt_rule->rt_tbl_name));
/* Support QCMAP LAN traffic feature, send to A5 */
rt_rule_entry->rule.dst = IPA_CLIENT_A5_LAN_WAN_CONS;
memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
rt_rule_entry->rule.hdr_hdl = 0;
rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0];
rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1];
rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2];
rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][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 (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl;
IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num], iptype);
/*Copy same rule to v6 WAN RT TBL*/
strncpy(rt_rule->rt_tbl_name,
IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
sizeof(rt_rule->rt_tbl_name));
/* Downlink traffic from Wan iface, directly through IPA */
rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
memcpy(&rt_rule_entry->rule.attrib,
&tx_prop->tx[tx_index].attrib,
sizeof(rt_rule_entry->rule.attrib));
rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6;
rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0];
rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1];
rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2];
rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][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 (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl;
IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num], iptype);
}
}
} /* end of for loop */
free(rt_rule);
if (iptype == IPA_IP_v4)
{
get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 = true;
}
else
{
get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 = get_client_memptr(wlan_client, wlan_index)->ipv6_set;
}
}
return IPACM_SUCCESS;
}
/*handle wifi client power-save mode*/
int IPACM_Wlan::handle_wlan_client_pwrsave(uint8_t *mac_addr)
{
int clt_indx;
IPACMDBG("wlan->handle_wlan_client_pwrsave();\n");
clt_indx = get_wlan_client_index(mac_addr);
if (clt_indx == IPACM_INVALID_INDEX)
{
IPACMDBG("wlan client not attached\n");
return IPACM_SUCCESS;
}
if (get_client_memptr(wlan_client, clt_indx)->power_save_set == false)
{
/* First reset nat rules and then route rules */
if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true)
{
IPACMDBG("Deleting Nat Rules\n");
Nat_App->UpdatePwrSaveIf(get_client_memptr(wlan_client, clt_indx)->v4_addr);
}
IPACMDBG("Deleting default qos Route Rules\n");
delete_default_qos_rtrules(clt_indx, IPA_IP_v4);
delete_default_qos_rtrules(clt_indx, IPA_IP_v6);
get_client_memptr(wlan_client, clt_indx)->power_save_set = true;
}
else
{
IPACMDBG("wlan client already in power-save mode\n");
}
return IPACM_SUCCESS;
}
/*handle wifi client del mode*/
int IPACM_Wlan::handle_wlan_client_down_evt(uint8_t *mac_addr)
{
int clt_indx;
uint32_t tx_index;
int num_wifi_client_tmp = num_wifi_client;
int num_v6;
IPACMDBG("total client: %d\n", num_wifi_client_tmp);
clt_indx = get_wlan_client_index(mac_addr);
if (clt_indx == IPACM_INVALID_INDEX)
{
IPACMDBG("wlan client not attached\n");
return IPACM_SUCCESS;
}
if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4))
{
IPACMERR("unbale to delete v4 default qos route rules\n");
return IPACM_FAILURE;
}
if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6))
{
IPACMERR("unbale to delete v6 default qos route rules\n");
return IPACM_FAILURE;
}
/* Delete wlan client header */
if(get_client_memptr(wlan_client, clt_indx)->ipv4_header_set == true)
{
if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4)
== false)
{
return IPACM_FAILURE;
}
get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false;
}
if(get_client_memptr(wlan_client, clt_indx)->ipv6_header_set == true)
{
if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6)
== false)
{
return IPACM_FAILURE;
}
get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false;
}
/* Reset ip_set to 0*/
get_client_memptr(wlan_client, clt_indx)->ipv4_set = false;
get_client_memptr(wlan_client, clt_indx)->ipv6_set = 0;
get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false;
get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false;
get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false;
get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0;
for (; clt_indx < num_wifi_client_tmp - 1; clt_indx++)
{
memcpy(get_client_memptr(wlan_client, clt_indx)->mac,
get_client_memptr(wlan_client, (clt_indx + 1))->mac,
sizeof(get_client_memptr(wlan_client, clt_indx)->mac));
get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v4;
get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v6;
get_client_memptr(wlan_client, clt_indx)->v4_addr = get_client_memptr(wlan_client, (clt_indx + 1))->v4_addr;
get_client_memptr(wlan_client, clt_indx)->ipv4_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_set;
get_client_memptr(wlan_client, clt_indx)->ipv6_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_set;
get_client_memptr(wlan_client, clt_indx)->ipv4_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_header_set;
get_client_memptr(wlan_client, clt_indx)->ipv6_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_header_set;
get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v4;
get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v6;
for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->ipv6_set;num_v6++)
{
get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][0];
get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][1];
get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][2];
get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][3];
}
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 =
get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4;
for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++)
{
get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6] =
get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6];
get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6] =
get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6];
}
}
}
IPACMDBG(" %d wifi client deleted successfully \n", num_wifi_client);
num_wifi_client = num_wifi_client - 1;
IPACM_Wlan::total_num_wifi_clients = IPACM_Wlan::total_num_wifi_clients - 1;
IPACMDBG(" Number of wifi client: %d\n", num_wifi_client);
return IPACM_SUCCESS;
}
/* duplicate ampdu filter rules for wan_up event */
int IPACM_Wlan::handle_wan_up(void)
{
struct ipa_flt_rule_add flt_rule_entry;
IPACMDBG("Wlan->handle_wan_up(); \n");
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
ipa_ioc_add_flt_rule *m_pFilteringTable;
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
1 * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_flt_rule_add memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->ip = IPA_IP_v4;
m_pFilteringTable->num_rules = (uint8_t)1;
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4))
{
IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4);
return IPACM_FAILURE;
}
memset(&flt_rule_entry, 0, sizeof(ipa_flt_rule_add));
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
/* Match-all rule */
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry));
if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
{
IPACMERR("Error Adding Filtering Rule, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
}
/* copy filter hdls */
wlan_ampdu_flt_rule.hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
free(m_pFilteringTable);
return IPACM_SUCCESS;
}
/*delete ampdu filter rules for wan_down event*/
int IPACM_Wlan::handle_wan_down(void)
{
IPACMDBG("\n");
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[0],
IPA_IP_v4, 1) == false)
{
return IPACM_FAILURE;
}
wlan_ampdu_flt_rule.hdl[0] = 0;
return IPACM_SUCCESS;
}
/*duplicate ampdu filter rules for software_routing event*/
int IPACM_Wlan::handle_software_routing_enable(void)
{
struct ipa_flt_rule_add flt_rule_entry;
ipa_ioc_add_flt_rule *m_pFilteringTable;
int res = IPACM_SUCCESS;
if (softwarerouting_act == true)
{
IPACMDBG("already setup AMPDU software_routing rule for (%s)iface ip-family %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name,ip_type);
return IPACM_SUCCESS;
}
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
1 * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_ioc_add_flt_rule memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->num_rules = (uint8_t)1;
/* Configuring Software_routing Filtering Rule */
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.at_rear = false;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* check iface is v4 or v6 or both*/
if (ip_type == IPA_IP_MAX)
{
/* handle v4 */
m_pFilteringTable->ip = IPA_IP_v4;
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding Filtering rule, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
else if (m_pFilteringTable->rules[0].status)
{
IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
/* copy filter hdls */
wlan_ampdu_flt_rule.hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
/* handle v6*/
m_pFilteringTable->ip = IPA_IP_v6;
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding Filtering rule, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
else if (m_pFilteringTable->rules[0].status)
{
IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
/* copy filter hdls */
wlan_ampdu_flt_rule.hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
}
else
{
if (ip_type == IPA_IP_v4)
{
m_pFilteringTable->ip = IPA_IP_v4;
}
else
{
m_pFilteringTable->ip = IPA_IP_v6;
}
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding Filtering rule, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
else if (m_pFilteringTable->rules[0].status)
{
IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
/* copy filter hdls */
if (ip_type == IPA_IP_v4) wlan_ampdu_flt_rule.hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
else wlan_ampdu_flt_rule.hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
}
fail:
free(m_pFilteringTable);
return res;
}
/*delete ampdu filter rules for disabling software_routing event*/
int IPACM_Wlan::handle_software_routing_disable(void)
{
if (softwarerouting_act == false)
{
IPACMDBG("already delete AMPDU software_routing rule for (%s)iface ip-family %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name,ip_type);
return IPACM_SUCCESS;
}
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if (ip_type == IPA_IP_MAX)
{
/* ipv4 case */
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[1],
IPA_IP_v4, 1) == false)
{
return IPACM_FAILURE;
}
/* ipv6 case */
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[2],
IPA_IP_v6, 1) == false)
{
return IPACM_FAILURE;
}
}
else
{
if (ip_type == IPA_IP_v4)
{
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[1],
IPA_IP_v4, 1) == false)
{
return IPACM_FAILURE;
}
}
else if (ip_type == IPA_IP_v6)
{
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[2],
IPA_IP_v6, 1) == false)
{
return IPACM_FAILURE;
}
}
}
return IPACM_SUCCESS;
}
/*duplicate ampdu filter rules for initial iface configuration*/
int IPACM_Wlan::init_fl_rule(ipa_ip_type iptype)
{
int res = IPACM_SUCCESS;
struct ipa_flt_rule_add flt_rule_entry;
ipa_ioc_add_flt_rule *m_pFilteringTable;
if(rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
IPACMDBG("ip-type: %d\n", iptype);
if (iptype == IPA_IP_v4)
{
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_flt_rule_add memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->ip = iptype;
m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
/* Configuring Fragment Rule */
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring Multicast Filtering Rule */
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000; /* DST_IP == 224.0.0.0 */
memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring Broadcast Filtering Rule */
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; /* Filter DST_IP == 127.0.0.1 */
memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding RuleTable(2) to Filtering, aborting...\n");
res = IPACM_FAILURE;
}
else
{
/* copy filter hdls */
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules] = m_pFilteringTable->rules[0].flt_rule_hdl;
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules + 1] = m_pFilteringTable->rules[1].flt_rule_hdl;
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules + 2] = m_pFilteringTable->rules[2].flt_rule_hdl;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules] = IPA_IP_v4;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules + 1] = IPA_IP_v4;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules + 2] = IPA_IP_v4;
wlan_ampdu_flt_rule.num_rules += IPV4_DEFAULT_FILTERTING_RULES;
}
}
else
{
/* IPv6 filter rule configuration */
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_flt_rule_add memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->ip = iptype;
m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
/* Configuring Fragment Filtering Rule */
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
/* Configuring Multicast Filtering Rule */
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding Filtering Rule, aborting...\n");
res = IPACM_FAILURE;
}
else
{
/* copy filter hdls */
for (int i = 0;
i < IPV6_DEFAULT_FILTERTING_RULES;
i++)
{
if (m_pFilteringTable->rules[i].status == 0)
{
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules+i] = m_pFilteringTable->rules[i].flt_rule_hdl;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules+i] = IPA_IP_v6;
IPACMDBG("Default v6 Filter Rule %d HDL:0x%x\n", i, wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules+i]);
}
else
{
IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
}
}
wlan_ampdu_flt_rule.num_rules += IPV6_DEFAULT_FILTERTING_RULES;
}
}
free(m_pFilteringTable);
return res;
}
/*duplicate ampdu filter rules for new_address event*/
int IPACM_Wlan::handle_addr_evt(ipacm_event_data_addr *data)
{
ipa_ioc_add_flt_rule *m_pFilteringTable;
struct ipa_flt_rule_add flt_rule_entry;
int NUM_RULES = 1;
IPACMDBG(" set route/filter rule ip-type: %d \n", data->iptype);
if (data->iptype == IPA_IP_v6)
{
if (num_dft_rt_v6 == 1) /*LAN handle_addr_evt will update this to 1*/
{
/* configure ampdu multicast/broadcast/fragment filter rule */
init_fl_rule(data->iptype);
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
/* add default v6 filter rule */
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
NUM_RULES * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_ioc_add_flt_rule memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->ip = IPA_IP_v6;
m_pFilteringTable->num_rules = (uint8_t)NUM_RULES;
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6))
{
PERROR("m_routing.GetRoutingTable() Failed.\n");
return IPACM_FAILURE;
}
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding RuleTable(0) to Filtering, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
}
/* copy filter hdls */
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules] = m_pFilteringTable->rules[0].flt_rule_hdl;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules] = IPA_IP_v6;
wlan_ampdu_flt_rule.num_rules++;
free(m_pFilteringTable);
}
}
else
{
init_fl_rule(data->iptype);
}
return IPACM_SUCCESS;
}
/*duplicate ampdu filter rules for private subnet configuration*/
int IPACM_Wlan::handle_private_subnet(ipa_ip_type iptype)
{
struct ipa_flt_rule_add flt_rule_entry;
int i;
IPACMDBG("wlan->handle_private_subnet(); set route/filter rule \n");
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if (iptype == IPA_IP_v4)
{
/* construct ipa_ioc_add_flt_rule with 1 rules */
ipa_ioc_add_flt_rule *m_pFilteringTable;
m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
calloc(1,
sizeof(struct ipa_ioc_add_flt_rule) +
(IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_add)
);
if (!m_pFilteringTable)
{
PERROR("Error Locate ipa_ioc_add_flt_rule memory...\n");
return IPACM_FAILURE;
}
m_pFilteringTable->commit = 1;
m_pFilteringTable->ep = IPA_CLIENT_A5_WLAN_AMPDU_PROD;
m_pFilteringTable->global = false;
m_pFilteringTable->ip = IPA_IP_v4;
m_pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
{
PERROR("WLAN m_routing.GetRoutingTable(IPACM_Iface::ipacmcfg->rt_tbl_lan_v4) Failed.\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
/* Make LAN-traffic always go A5, use default IPA-RT table */
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
{
IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4);
free(m_pFilteringTable);
return IPACM_FAILURE;
}
for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++)
{
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
/* Support priave subnet feature including guest-AP can't talk to primary AP etc */
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
IPACMDBG(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
flt_rule_entry.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
memcpy(&(m_pFilteringTable->rules[i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
}
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
PERROR("Error Adding RuleTable(0) to Filtering, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
};
/* copy filter hdls */
for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
{
wlan_ampdu_flt_rule.hdl[wlan_ampdu_flt_rule.num_rules + i] = m_pFilteringTable->rules[i].flt_rule_hdl;
wlan_ampdu_flt_rule.ip[wlan_ampdu_flt_rule.num_rules + i] = IPA_IP_v4;
}
wlan_ampdu_flt_rule.num_rules += IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
IPACMDBG("wlan handle private ok~\n");
free(m_pFilteringTable);
}
return IPACM_SUCCESS;
}
/*handle wlan iface down event*/
int IPACM_Wlan::handle_down_evt()
{
int res = IPACM_SUCCESS, i;
IPACMDBG("WLAN ip-type: %d \n", ip_type);
/* no iface address up, directly close iface*/
if (ip_type == IPACM_IP_NULL)
{
IPACMERR("Invalid iptype: 0x%x\n", ip_type);
goto fail;
}
/* Delete v6 filtering rules */
if (ip_type != IPA_IP_v6 && rx_prop != NULL)
{
IPACMDBG("Delete default v4 filter rules\n");
/* delete default filter rules */
if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl,
IPA_IP_v4,
IPV4_DEFAULT_FILTERTING_RULES) == false)
{
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Delete private v4 filter rules\n");
/* free private-ipv4 filter rules */
if (m_filtering.DeleteFilteringHdls(
private_fl_rule_hdl,
IPA_IP_v4,
IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false)
{
res = IPACM_FAILURE;
goto fail;
}
}
/* Delete v4 filtering rules */
if (ip_type != IPA_IP_v4 && rx_prop != NULL)
{
IPACMDBG("Delete default %d v6 filter rules\n", IPV6_DEFAULT_FILTERTING_RULES);
/* delete default filter rules */
if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl,
IPA_IP_v6,
(IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES)) == false)
{
res = IPACM_FAILURE;
goto fail;
}
}
IPACMDBG("finished delte default filtering rules\n ");
if (rx_prop != NULL)
{
/* delete WLAN IPA_CLIENT_A5_WLAN_AMPDU_PROD filter rules*/
for (i = 3; i < wlan_ampdu_flt_rule.num_rules; i++)
{
IPACMDBG("Delete WLAN IPA_CLIENT_A5_WLAN_AMPDU_PROD filter rules\n");
if (m_filtering.DeleteFilteringHdls(&wlan_ampdu_flt_rule.hdl[i],
wlan_ampdu_flt_rule.ip[i], 1) == false)
{
res = IPACM_FAILURE;
goto fail;
}
}
IPACMDBG("finished delte AMPDU filtering rules\n ");
}
/* Delete default v4 RT rule */
if (ip_type != IPA_IP_v6)
{
IPACMDBG("Delete default v4 routing rules\n");
if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4)
== false)
{
IPACMERR("Routing rule deletion failed!\n");
res = IPACM_FAILURE;
goto fail;
}
}
/* Delete default v6 RT rule */
if (ip_type != IPA_IP_v4)
{
IPACMDBG("Delete default v6 routing rules\n");
/* May have multiple ipv6 iface-RT rules */
for (i = 0; i < 2*num_dft_rt_v6; i++)
{
if (m_routing.DeleteRoutingHdl(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;
}
}
}
IPACMDBG("finished deleting default RT rules\n ");
/* delete wan filter rule */
if (IPACM_Wan::isWanUP() && rx_prop != NULL)
{
IPACMDBG("Delete wan filtering rules\n");
IPACM_Lan::handle_wan_down();
handle_wan_down();
}
IPACMDBG("finished deleting wan filtering rules\n ");
/* check software routing fl rule hdl */
if (softwarerouting_act == true && rx_prop != NULL )
{
IPACMDBG("Delete sw routing filtering rules\n");
IPACM_Iface::handle_software_routing_disable();
handle_software_routing_disable();
}
IPACMDBG("finished delete software-routing filtering rules\n ");
/* clean wifi-client header, routing rules */
/* clean wifi client rule*/
IPACMDBG("left %d wifi clients need to be deleted \n ", num_wifi_client);
for (i = 0; i < num_wifi_client; i++)
{
delete_default_qos_rtrules(i, IPA_IP_v4);
delete_default_qos_rtrules(i, IPA_IP_v6);
IPACMDBG("Delete %d client header\n", num_wifi_client);
if(get_client_memptr(wlan_client, i)->ipv4_header_set == true)
{
if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v4)
== false)
{
res = IPACM_FAILURE;
goto fail;
}
}
if(get_client_memptr(wlan_client, i)->ipv6_header_set == true)
{
if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v6)
== false)
{
res = IPACM_FAILURE;
goto fail;
}
}
} /* end of for loop */
/* free the wlan clients cache */
IPACMDBG("Free wlan clients cache\n");
fail:
/* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */
IPACM_Iface::ipacmcfg->DelRmDepend(IPA_RM_RESOURCE_HSIC_PROD);
free(wlan_client);
if (tx_prop != NULL)
{
free(tx_prop);
}
if (rx_prop != NULL)
{
free(rx_prop);
}
if (iface_query != NULL)
{
free(iface_query);
}
return res;
}