Promotion of data.lnx.3.0-00087.
CRs Change ID Subject
--------------------------------------------------------------------------------------------------------------
2069634 Ic01e10eaf35195da8b55e25f779a13669d0d1dae IPACM: fix L2TP issues
2066430 I296aee0fe857a7db4fc29f87c833224d7c0ffd9d IPACM: add support for L2TP
2064317 Ifbeacfb9bc5148d399dace97dabfe63d2939b066 IPACM: add filtering rule for unique local address
Change-Id: I1ee00dd218eae7d742d69ba5cd25ef825c0fd07c
CRs-Fixed: 2066430, 2064317, 2069634
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 74ed3bf..31d8543 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -187,6 +187,12 @@
IPA_LAN_DELETE_SELF, /* ipacm_event_data_fid */
IPA_DOWNSTREAM_ADD, /* ipacm_event_ipahal_stream */
IPA_DOWNSTREAM_DEL, /* ipacm_event_ipahal_stream */
+ IPA_ADD_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */
+ IPA_DEL_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */
+ IPA_ADD_L2TP_VLAN_MAPPING, /* ipa_ioc_l2tp_vlan_mapping_info */
+ IPA_DEL_L2TP_VLAN_MAPPING, /* ipa_ioc_l2tp_vlan_mapping_info */
+ IPA_HANDLE_VLAN_CLIENT_INFO, /* ipacm_event_data_all */
+ IPA_HANDLE_VLAN_IFACE_INFO, /* ipacm_event_data_all */
IPACM_EVENT_MAX
} ipa_cm_event_id;
@@ -249,6 +255,7 @@
uint32_t ipv4_addr;
uint32_t ipv6_addr[4];
uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
+ char iface_name[IPA_IFACE_NAME_LEN];
} ipacm_event_data_all;
class IPACM_Lan;
@@ -263,6 +270,7 @@
IPACM_Lan *p_iface;
ipa_ip_type iptype;
uint8_t mac_addr[6];
+ char iface_name[IPA_IFACE_NAME_LEN];
} ipacm_event_eth_bridge;
typedef struct
@@ -299,6 +307,7 @@
typedef struct _ipacm_event_data_addr
{
enum ipa_ip_type iptype;
+ char iface_name[IPA_IFACE_NAME_LEN];
int if_index;
uint32_t ipv4_addr_gw;
uint32_t ipv4_addr;
diff --git a/ipacm/inc/IPACM_Iface.h b/ipacm/inc/IPACM_Iface.h
index 43b0da6..0469699 100644
--- a/ipacm/inc/IPACM_Iface.h
+++ b/ipacm/inc/IPACM_Iface.h
@@ -59,9 +59,9 @@
#define IPV4_DEFAULT_FILTERTING_RULES 3
#ifdef FEATURE_IPA_ANDROID
-#define IPV6_DEFAULT_FILTERTING_RULES 6
+#define IPV6_DEFAULT_FILTERTING_RULES 7
#else
-#define IPV6_DEFAULT_FILTERTING_RULES 3
+#define IPV6_DEFAULT_FILTERTING_RULES 4
#endif
#define IPV6_DEFAULT_LAN_FILTERTING_RULES 1
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index 2e5f21b..280c830 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -169,7 +169,35 @@
/* delete header processing context */
int eth_bridge_del_hdr_proc_ctx(uint32_t hdr_proc_ctx_hdl);
+ /* add l2tp rt rule for l2tp client */
+ int add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, ipa_hdr_l2_type peer_l2_hdr_type,
+ uint32_t l2tp_session_id, uint32_t vlan_id, uint8_t *vlan_client_mac, uint32_t *vlan_iface_ipv6_addr,
+ uint32_t *vlan_client_ipv6_addr, uint32_t *first_pass_hdr_hdl, uint32_t *first_pass_hdr_proc_ctx_hdl,
+ uint32_t *second_pass_hdr_hdl, int *num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl);
+ /* delete l2tp rt rule for l2tp client */
+ int del_l2tp_rt_rule(ipa_ip_type iptype, uint32_t first_pass_hdr_hdl, uint32_t first_pass_hdr_proc_ctx_hdl,
+ uint32_t second_pass_hdr_hdl, int num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl);
+
+ /* add l2tp rt rule for non l2tp client */
+ int add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *hdr_proc_ctx_hdl,
+ int *num_rt_hdl, uint32_t *rt_rule_hdl);
+
+ /* delete l2tp rt rule for non l2tp client */
+ int del_l2tp_rt_rule(ipa_ip_type iptype, int num_rt_hdl, uint32_t *rt_rule_hdl);
+
+ /* add l2tp flt rule on l2tp interface */
+ int add_l2tp_flt_rule(uint8_t *dst_mac, uint32_t *flt_rule_hdl);
+
+ /* delete l2tp flt rule on l2tp interface */
+ int del_l2tp_flt_rule(uint32_t flt_rule_hdl);
+
+ /* add l2tp flt rule on non l2tp interface */
+ int add_l2tp_flt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *vlan_client_ipv6_addr,
+ uint32_t *first_pass_flt_rule_hdl, uint32_t *second_pass_flt_rule_hdl);
+
+ /* delete l2tp flt rule on non l2tp interface */
+ int del_l2tp_flt_rule(ipa_ip_type iptype, uint32_t first_pass_flt_rule_hdl, uint32_t second_pass_flt_rule_hdl);
protected:
@@ -178,9 +206,17 @@
uint32_t eth_bridge_flt_rule_offset[IPA_IP_MAX];
/* mac address has to be provided for client related events */
- void eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac);
+ void eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac,
+ uint32_t *ipv6_addr, char *iface_name);
+ /* check if the event is associated with vlan interface */
+ bool is_vlan_event(char *event_iface_name);
+ /* check if the event is associated with l2tp interface */
+ bool is_l2tp_event(char *event_iface_name);
+
+ /* check if the IPv6 address is unique local address */
+ bool is_unique_local_ipv6_addr(uint32_t *ipv6_addr);
virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype);
diff --git a/ipacm/inc/IPACM_LanToLan.h b/ipacm/inc/IPACM_LanToLan.h
index a28631e..b055cdd 100644
--- a/ipacm/inc/IPACM_LanToLan.h
+++ b/ipacm/inc/IPACM_LanToLan.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014, The Linux Foundation. All rights reserved.
+Copyright (c) 2014-2017, 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
@@ -53,23 +53,63 @@
#define MAX_NUM_IFACE 10
#define MAX_NUM_CLIENT 16
+struct vlan_iface_info
+{
+ char vlan_iface_name[IPA_RESOURCE_NAME_MAX];
+ uint8_t vlan_id;
+ uint32_t vlan_iface_ipv6_addr[4];
+ uint8_t vlan_client_mac[6];
+ uint32_t vlan_client_ipv6_addr[4];
+};
+
+struct l2tp_vlan_mapping_info
+{
+ /* the following are l2tp iface info (name, session id) */
+ char l2tp_iface_name[IPA_RESOURCE_NAME_MAX];
+ uint8_t l2tp_session_id;
+ /* the following are mdm vlan iface info (name, vlan id, ipv6 addr) */
+ char vlan_iface_name[IPA_RESOURCE_NAME_MAX];
+ uint8_t vlan_id;
+ uint32_t vlan_iface_ipv6_addr[4];
+ /* the following are MIB3 vlan client info (mac, ipv6 addr) */
+ uint8_t vlan_client_mac[6];
+ uint32_t vlan_client_ipv6_addr[4];
+ /* the following is MIB3 l2tp client info (mac) */
+ uint8_t l2tp_client_mac[6];
+};
+
struct rt_rule_info
{
int num_hdl[IPA_IP_MAX]; /* one client may need more than one routing rules on the same routing table depending on tx_prop */
uint32_t rule_hdl[IPA_IP_MAX][MAX_NUM_PROP];
};
+struct l2tp_rt_rule_info
+{
+ uint32_t first_pass_hdr_hdl; /* first pass hdr template (IPv4 and IPv6 use the same hdr template) */
+ uint32_t first_pass_hdr_proc_ctx_hdl[IPA_IP_MAX]; /* first pass hdr proc ctx */
+ uint32_t second_pass_hdr_hdl; /* second pass hdr template (IPv4 and IPv6 use the same hdr template) */
+ int num_rt_hdl[IPA_IP_MAX]; /* number of TX properties for IPv4 and IPv6 respectively */
+ uint32_t first_pass_rt_rule_hdl[IPA_IP_MAX][MAX_NUM_PROP]; /* first pass routing rule */
+ uint32_t second_pass_rt_rule_hdl[MAX_NUM_PROP]; /*second pass routing rule (only ipv6 rt rule is needed) */
+};
+
struct client_info
{
uint8_t mac_addr[6];
rt_rule_info inter_iface_rt_rule_hdl[IPA_HDR_L2_MAX]; /* routing rule handles of inter interface communication based on source l2 header type */
rt_rule_info intra_iface_rt_rule_hdl; /* routing rule handles of inter interface communication */
+ bool is_l2tp_client;
+ l2tp_vlan_mapping_info *mapping_info;
+ l2tp_rt_rule_info l2tp_rt_rule_hdl[IPA_HDR_L2_MAX];
};
struct flt_rule_info
{
client_info *p_client;
uint32_t flt_rule_hdl[IPA_IP_MAX];
+ uint32_t l2tp_first_pass_flt_rule_hdl[IPA_IP_MAX]; /* L2TP filtering rules are destination MAC based */
+ uint32_t l2tp_second_pass_flt_rule_hdl;
};
struct peer_iface_info
@@ -101,7 +141,7 @@
void handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX], char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX],
IPACM_LanToLan_Iface *peer_iface);
- void handle_client_add(uint8_t *mac);
+ void handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info);
void handle_client_del(uint8_t *mac);
@@ -121,16 +161,28 @@
void decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type);
+ void switch_to_l2tp_iface();
+
+ bool set_l2tp_iface(char *vlan_iface_name);
+
+ bool is_l2tp_iface();
+
+ void handle_l2tp_enable();
+
+ void handle_l2tp_disable();
+
private:
IPACM_Lan *m_p_iface;
bool m_is_ip_addr_assigned[IPA_IP_MAX];
bool m_support_inter_iface_offload;
bool m_support_intra_iface_offload;
+ bool m_is_l2tp_iface;
int ref_cnt_peer_l2_hdr_type[IPA_HDR_L2_MAX]; /* reference count of l2 header type of peer interfaces */
uint32_t hdr_proc_ctx_for_inter_interface[IPA_HDR_L2_MAX];
uint32_t hdr_proc_ctx_for_intra_interface;
+ uint32_t hdr_proc_ctx_for_l2tp; /* uc needs to remove 62 bytes IPv6 + L2TP + inner Ethernet header */
list<client_info> m_client_info; /* client list */
list<peer_iface_info> m_peer_iface_info; /* peer information list */
@@ -150,6 +202,8 @@
void del_client_rt_rule(peer_iface_info *peer, client_info *client);
+ void add_l2tp_client_rt_rule(peer_iface_info *peer, client_info *client);
+
void clear_all_flt_rule_for_one_peer_iface(peer_iface_info *peer);
void clear_all_rt_rule_for_one_peer_iface(peer_iface_info *peer);
@@ -167,16 +221,26 @@
public:
- IPACM_LanToLan();
+ static IPACM_LanToLan* p_instance;
+ static IPACM_LanToLan* get_instance();
+ bool has_l2tp_iface();
private:
+ IPACM_LanToLan();
+
~IPACM_LanToLan();
+ bool m_has_l2tp_iface;
+
list<class IPACM_LanToLan_Iface> m_iface;
list<ipacm_event_eth_bridge> m_cached_client_add_event;
+ list<vlan_iface_info> m_vlan_iface;
+
+ list<l2tp_vlan_mapping_info> m_l2tp_vlan_mapping;
+
void handle_iface_up(ipacm_event_eth_bridge *data);
void handle_iface_down(ipacm_event_eth_bridge *data);
@@ -187,6 +251,18 @@
void handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data);
+ void handle_add_vlan_iface(ipa_ioc_vlan_iface_info *data);
+
+ void handle_del_vlan_iface(ipa_ioc_vlan_iface_info *data);
+
+ void handle_add_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data);
+
+ void handle_del_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data);
+
+ void handle_vlan_client_info(ipacm_event_data_all *data);
+
+ void handle_vlan_iface_info(ipacm_event_data_all *data);
+
void handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface);
void event_callback(ipa_cm_event_id event, void* param);
diff --git a/ipacm/inc/IPACM_Neighbor.h b/ipacm/inc/IPACM_Neighbor.h
index 14e86e5..745b145 100644
--- a/ipacm/inc/IPACM_Neighbor.h
+++ b/ipacm/inc/IPACM_Neighbor.h
@@ -1,5 +1,5 @@
-/*
-Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/*
+Copyright (c) 2013-2017, 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
@@ -56,6 +56,8 @@
int iface_index;
uint32_t v4_addr;
int ipa_if_num;
+ /* add support for handling L2TP clients which associated with eth0 vlan interface */
+ char iface_name[IPA_IFACE_NAME_LEN];
};
class IPACM_Neighbor : public IPACM_Listener
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index a355883..52cc985 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -105,6 +105,12 @@
__stringify(IPA_ETH_BRIDGE_CLIENT_DEL), /* ipacm_event_eth_bridge*/
__stringify(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH), /* ipacm_event_eth_bridge*/
__stringify(IPA_LAN_DELETE_SELF), /* ipacm_event_data_fid */
+ __stringify(IPA_ADD_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */
+ __stringify(IPA_DEL_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */
+ __stringify(IPA_ADD_L2TP_VLAN_MAPPING), /* ipa_ioc_l2tp_vlan_mapping_info */
+ __stringify(IPA_DEL_L2TP_VLAN_MAPPING), /* ipa_ioc_l2tp_vlan_mapping_info */
+ __stringify(IPA_VLAN_CLIENT_INFO), /* ipacm_event_data_all */
+ __stringify(IPA_VLAN_IFACE_INFO), /* ipacm_event_data_all */
__stringify(IPACM_EVENT_MAX),
};
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index 8c37d80..717f6aa 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -450,12 +450,15 @@
freeifaddrs(myaddrs);
return ;
}
+ memset(data_addr, 0, sizeof(ipacm_event_data_addr));
data_addr->iptype = IPA_IP_v4;
data_addr->if_index = interface_index;
data_addr->ipv4_addr = iface_ipv4.s_addr;
data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
- IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n",
+ strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
+ IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv4 addr:0x%x\n",
data_addr->if_index,
+ data_addr->iface_name,
data_addr->ipv4_addr);
evt_data.event = IPA_ADDR_ADD_EVENT;
@@ -475,6 +478,7 @@
freeifaddrs(myaddrs);
return ;
}
+ memset(data_addr, 0, sizeof(ipacm_event_data_addr));
data_addr->iptype = IPA_IP_v6;
data_addr->if_index = interface_index;
memcpy(data_addr->ipv6_addr,
@@ -484,8 +488,10 @@
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]);
- IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
+ strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
+ IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv6 addr:0x%x:%x:%x:%x\n",
data_addr->if_index,
+ data_addr->iface_name,
data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
evt_data.event = IPA_ADDR_ADD_EVENT;
@@ -837,6 +843,21 @@
#endif
memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ /* Configuring fd00::/8 Unique Local Ipv6 Address */
+ 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] = 0xFD000000;
+ 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;
+#ifdef FEATURE_IPA_V3
+ flt_rule_entry.at_rear = true;
+ flt_rule_entry.rule.hashable = true;
+#endif
+ memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+
#ifdef FEATURE_IPA_ANDROID
IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
@@ -871,17 +892,17 @@
/* add TCP FIN rule*/
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
- memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* add TCP SYN rule*/
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
- memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* add TCP RST rule*/
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
- memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
#endif
if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
{
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index a561eef..2f561cc 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -331,8 +331,14 @@
IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n");
return;
}
-
-
+#ifdef FEATURE_L2TP
+ if(data->iptype == IPA_IP_v6 && is_vlan_event(data->iface_name) && is_unique_local_ipv6_addr(data->ipv6_addr))
+ {
+ IPACMDBG_H("Got IPv6 new addr event for a vlan iface %s.\n", data->iface_name);
+ eth_bridge_post_event(IPA_HANDLE_VLAN_IFACE_INFO, data->iptype, NULL,
+ data->ipv6_addr, data->iface_name);
+ }
+#endif
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG_H("Received IPA_ADDR_ADD_EVENT\n");
@@ -826,24 +832,46 @@
}
}
- if (ipa_interface_index == ipa_if_num)
+ if (ipa_interface_index == ipa_if_num || is_vlan_event(data->iface_name)
+ || (is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF))
{
IPACMDBG_H("ETH iface got client \n");
- /* first construc ETH full header */
- handle_eth_hdr_init(data->mac_addr);
- IPACMDBG_H("construct ETH header and route rules \n");
- /* Associate with IP and construct RT-rule */
- if (handle_eth_client_ipaddr(data) == IPACM_FAILURE)
+ if(ipa_interface_index == ipa_if_num)
{
- return;
+ /* first construc ETH full header */
+ handle_eth_hdr_init(data->mac_addr);
+ IPACMDBG_H("construct ETH header and route rules \n");
+ /* Associate with IP and construct RT-rule */
+ if (handle_eth_client_ipaddr(data) == IPACM_FAILURE)
+ {
+ return;
+ }
+ handle_eth_client_route_rule(data->mac_addr, data->iptype);
+ if (data->iptype == IPA_IP_v4)
+ {
+ /* Add NAT rules after ipv4 RT rules are set */
+ CtList->HandleNeighIpAddrAddEvt(data);
+ }
+ eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
}
- handle_eth_client_route_rule(data->mac_addr, data->iptype);
- if (data->iptype == IPA_IP_v4)
+#ifdef FEATURE_L2TP
+ else if(is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF)
{
- /* Add NAT rules after ipv4 RT rules are set */
- CtList->HandleNeighIpAddrAddEvt(data);
+ if(tx_prop != NULL)
+ {
+ IPACMDBG_H("add rm dependency for L2TP interface.\n");
+ IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
+ }
+ eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
}
- eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr);
+ else
+ {
+ if(data->iptype == IPA_IP_v6 && is_unique_local_ipv6_addr(data->ipv6_addr))
+ {
+ eth_bridge_post_event(IPA_HANDLE_VLAN_CLIENT_INFO, IPA_IP_MAX, data->mac_addr, data->ipv6_addr, data->iface_name);
+ }
+ }
+#endif
return;
}
}
@@ -863,18 +891,23 @@
return;
}
- if (ipa_interface_index == ipa_if_num)
+ if (ipa_interface_index == ipa_if_num
+ || (is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF))
{
- if (data->iptype == IPA_IP_v6)
+ if(ipa_interface_index == ipa_if_num)
{
- handle_del_ipv6_addr(data);
- return;
+ if (data->iptype == IPA_IP_v6)
+ {
+ handle_del_ipv6_addr(data);
+ return;
+ }
+ IPACMDBG_H("LAN iface delete client \n");
+ handle_eth_client_down_evt(data->mac_addr);
}
-
- eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr);
-
- IPACMDBG_H("LAN iface delete client \n");
- handle_eth_client_down_evt(data->mac_addr);
+ else
+ {
+ eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
+ }
return;
}
}
@@ -1166,7 +1199,7 @@
/* populate the flt rule offset for eth bridge */
eth_bridge_flt_rule_offset[data->iptype] = ipv4_icmp_flt_rule_hdl[0];
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL);
}
else
{
@@ -1257,7 +1290,7 @@
/* populate the flt rule offset for eth bridge */
eth_bridge_flt_rule_offset[data->iptype] = ipv6_icmp_flt_rule_hdl[0];
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL);
init_fl_rule(data->iptype);
}
@@ -2809,7 +2842,7 @@
IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
}
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
/* Delete private subnet*/
#ifdef FEATURE_IPA_ANDROID
@@ -4126,32 +4159,71 @@
}
/* mac address has to be provided for client related events */
-void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac)
+void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac, uint32_t *ipv6_addr, char *iface_name)
{
ipacm_cmd_q_data eth_bridge_evt;
- ipacm_event_eth_bridge *evt_data;
-
- evt_data = (ipacm_event_eth_bridge*)malloc(sizeof(ipacm_event_eth_bridge));
- if(evt_data == NULL)
- {
- IPACMERR("Failed to allocate memory.\n");
- return;
- }
- memset(evt_data, 0, sizeof(ipacm_event_eth_bridge));
-
- evt_data->p_iface = this;
- evt_data->iptype = iptype;
- if(mac)
- {
- IPACMDBG_H("Client mac: 0x%02x%02x%02x%02x%02x%02x \n",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
- memcpy(evt_data->mac_addr, mac, sizeof(evt_data->mac_addr));
- }
+ ipacm_event_eth_bridge *evt_data_eth_bridge;
+ ipacm_event_data_all *evt_data_all;
memset(ð_bridge_evt, 0, sizeof(ipacm_cmd_q_data));
- eth_bridge_evt.evt_data = (void*)evt_data;
eth_bridge_evt.event = evt;
+ if(evt == IPA_HANDLE_VLAN_CLIENT_INFO || evt == IPA_HANDLE_VLAN_IFACE_INFO)
+ {
+ evt_data_all = (ipacm_event_data_all*)malloc(sizeof(*evt_data_all));
+ if(evt_data_all == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return;
+ }
+ memset(evt_data_all, 0, sizeof(*evt_data_all));
+
+ if(ipv6_addr)
+ {
+ IPACMDBG_H("IPv6 addr: %08x:%08x:%08x:%08x \n", ipv6_addr[0],
+ ipv6_addr[1], ipv6_addr[2], ipv6_addr[3]);
+ memcpy(evt_data_all->ipv6_addr, ipv6_addr, sizeof(evt_data_all->ipv6_addr));
+ }
+ if(mac)
+ {
+ IPACMDBG_H("Mac: 0x%02x%02x%02x%02x%02x%02x \n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ memcpy(evt_data_all->mac_addr, mac, sizeof(evt_data_all->mac_addr));
+ }
+ if(iface_name)
+ {
+ IPACMDBG_H("Iface: %s\n", iface_name);
+ memcpy(evt_data_all->iface_name, iface_name, sizeof(evt_data_all->iface_name));
+ }
+ eth_bridge_evt.evt_data = (void*)evt_data_all;
+ }
+ else
+ {
+ evt_data_eth_bridge = (ipacm_event_eth_bridge*)malloc(sizeof(*evt_data_eth_bridge));
+ if(evt_data_eth_bridge == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return;
+ }
+ memset(evt_data_eth_bridge, 0, sizeof(*evt_data_eth_bridge));
+
+ evt_data_eth_bridge->p_iface = this;
+ evt_data_eth_bridge->iptype = iptype;
+ if(mac)
+ {
+ IPACMDBG_H("Mac: 0x%02x%02x%02x%02x%02x%02x \n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ memcpy(evt_data_eth_bridge->mac_addr, mac, sizeof(evt_data_eth_bridge->mac_addr));
+ }
+ if(iface_name)
+ {
+ IPACMDBG_H("Iface: %s\n", iface_name);
+ memcpy(evt_data_eth_bridge->iface_name, iface_name,
+ sizeof(evt_data_eth_bridge->iface_name));
+ }
+ eth_bridge_evt.evt_data = (void*)evt_data_eth_bridge;
+ }
+
IPACMDBG_H("Posting event %s\n",
IPACM_Iface::ipacmcfg->getEventName(evt));
IPACM_EvtDispatcher::PostEvt(ð_bridge_evt);
@@ -4494,3 +4566,817 @@
}
return IPACM_SUCCESS;
}
+
+/* check if the event is associated with vlan interface */
+bool IPACM_Lan::is_vlan_event(char *event_iface_name)
+{
+ int self_name_len, event_iface_name_len;
+ if(event_iface_name == NULL)
+ {
+ IPACMERR("Invalid input\n");
+ return false;
+ }
+
+ IPACMDBG_H("Self iface %s, event iface %s\n", dev_name, event_iface_name);
+ self_name_len = strlen(dev_name);
+ event_iface_name_len = strlen(event_iface_name);
+
+ if(event_iface_name_len > self_name_len && strncmp(dev_name, event_iface_name, self_name_len) == 0)
+ {
+ IPACMDBG_H("This is vlan event.\n");
+ return true;
+ }
+ return false;
+}
+
+/* check if the event is associated with l2tp interface */
+bool IPACM_Lan::is_l2tp_event(char *event_iface_name)
+{
+ if(event_iface_name == NULL)
+ {
+ IPACMERR("Invalid input\n");
+ return false;
+ }
+
+ IPACMDBG_H("Self iface %s, event iface %s\n", dev_name, event_iface_name);
+ if(strncmp(event_iface_name, "l2tp", 4) == 0)
+ {
+ IPACMDBG_H("This is l2tp event.\n");
+ return true;
+ }
+ return false;
+}
+
+/* add l2tp rt rule for l2tp client */
+int IPACM_Lan::add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, ipa_hdr_l2_type peer_l2_hdr_type,
+ uint32_t l2tp_session_id, uint32_t vlan_id, uint8_t *vlan_client_mac, uint32_t *vlan_iface_ipv6_addr,
+ uint32_t *vlan_client_ipv6_addr, uint32_t *first_pass_hdr_hdl, uint32_t *first_pass_hdr_proc_ctx_hdl,
+ uint32_t *second_pass_hdr_hdl, int *num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl)
+{
+ int i, size, position;
+ uint32_t vlan_iface_ipv6_addr_network[4], vlan_client_ipv6_addr_network[4];
+ ipa_ioc_add_hdr *hdr_table;
+ ipa_hdr_add *hdr;
+ ipa_ioc_add_hdr_proc_ctx *hdr_proc_ctx_table;
+ ipa_hdr_proc_ctx_add *hdr_proc_ctx;
+ ipa_ioc_add_rt_rule* rt_rule_table;
+ ipa_rt_rule_add *rt_rule;
+ ipa_ioc_copy_hdr copy_hdr;
+
+ if(tx_prop == NULL)
+ {
+ IPACMERR("No tx prop.\n");
+ return IPACM_FAILURE;
+ }
+
+ /* =========== install first pass hdr template (IPv6 + L2TP + inner ETH header = 62 bytes) ============= */
+ if(*first_pass_hdr_hdl != 0)
+ {
+ IPACMDBG_H("First pass hdr template was added before.\n");
+ }
+ else
+ {
+ size = sizeof(ipa_ioc_add_hdr) + sizeof(ipa_hdr_add);
+ hdr_table = (ipa_ioc_add_hdr*)malloc(size);
+ if(hdr_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(hdr_table, 0, size);
+
+ hdr_table->commit = 1;
+ hdr_table->num_hdrs = 1;
+ hdr = &hdr_table->hdr[0];
+
+ if(iptype == IPA_IP_v4)
+ {
+ snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_l2tp_%d_v4", vlan_id, l2tp_session_id);
+ }
+ else
+ {
+ snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_l2tp_%d_v6", vlan_id, l2tp_session_id);
+ }
+ hdr->hdr_len = 62;
+ hdr->type = IPA_HDR_L2_ETHERNET_II;
+ hdr->is_partial = 0;
+
+ hdr->hdr[0] = 0x60; /* version */
+ hdr->hdr[6] = 0x73; /* next header = L2TP */
+ hdr->hdr[7] = 0x40; /* hop limit = 64 */
+ for(i = 0; i < 4; i++)
+ {
+ vlan_iface_ipv6_addr_network[i] = htonl(vlan_iface_ipv6_addr[i]);
+ vlan_client_ipv6_addr_network[i] = htonl(vlan_client_ipv6_addr[i]);
+ }
+ memcpy(hdr->hdr + 8, vlan_iface_ipv6_addr_network, 16); /* source IPv6 addr */
+ memcpy(hdr->hdr + 24, vlan_client_ipv6_addr_network, 16); /* dest IPv6 addr */
+ hdr->hdr[43] = (uint8_t)(l2tp_session_id & 0xFF); /* l2tp header */
+ hdr->hdr[42] = (uint8_t)(l2tp_session_id >> 8 & 0xFF);
+ hdr->hdr[41] = (uint8_t)(l2tp_session_id >> 16 & 0xFF);
+ hdr->hdr[40] = (uint8_t)(l2tp_session_id >> 24 & 0xFF);
+
+ if(m_header.AddHeader(hdr_table) == false)
+ {
+ IPACMERR("Failed to add hdr with status: %d\n", hdr_table->hdr[0].status);
+ free(hdr_table);
+ return IPACM_FAILURE;
+ }
+ *first_pass_hdr_hdl = hdr_table->hdr[0].hdr_hdl;
+ IPACMDBG_H("Installed first pass hdr: hdl %d\n", *first_pass_hdr_hdl);
+ free(hdr_table);
+ }
+
+ /* =========== install first pass hdr proc ctx (populate src/dst MAC and Ether type) ============= */
+ size = sizeof(ipa_ioc_add_hdr_proc_ctx) + sizeof(ipa_hdr_proc_ctx_add);
+ hdr_proc_ctx_table = (ipa_ioc_add_hdr_proc_ctx*)malloc(size);
+ if(hdr_proc_ctx_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(hdr_proc_ctx_table, 0, size);
+
+ hdr_proc_ctx_table->commit = 1;
+ hdr_proc_ctx_table->num_proc_ctxs = 1;
+ hdr_proc_ctx = &hdr_proc_ctx_table->proc_ctx[0];
+
+ hdr_proc_ctx->type = IPA_HDR_PROC_L2TP_HEADER_ADD;
+ hdr_proc_ctx->hdr_hdl = *first_pass_hdr_hdl;
+ hdr_proc_ctx->l2tp_params.hdr_add_param.eth_hdr_retained = 1;
+ hdr_proc_ctx->l2tp_params.hdr_add_param.input_ip_version = iptype;
+ hdr_proc_ctx->l2tp_params.hdr_add_param.output_ip_version = IPA_IP_v6;
+ if(m_header.AddHeaderProcCtx(hdr_proc_ctx_table) == false)
+ {
+ IPACMERR("Failed to add hdr proc ctx with status: %d\n", hdr_proc_ctx_table->proc_ctx[0].status);
+ free(hdr_proc_ctx_table);
+ return IPACM_FAILURE;
+ }
+ *first_pass_hdr_proc_ctx_hdl = hdr_proc_ctx_table->proc_ctx[0].proc_ctx_hdl;
+ IPACMDBG_H("Installed first pass hdr proc ctx: hdl %d\n", *first_pass_hdr_proc_ctx_hdl);
+ free(hdr_proc_ctx_table);
+
+ /* =========== install first pass rt rules (match dst MAC then doing UCP) ============= */
+ *num_rt_hdl = each_client_rt_rule_count[iptype];
+ size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add);
+ rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size);
+ if (rt_rule_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(rt_rule_table, 0, size);
+
+ rt_rule_table->commit = 1;
+ rt_rule_table->ip = iptype;
+ rt_rule_table->num_rules = *num_rt_hdl;
+ snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp");
+ rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0;
+
+ position = 0;
+ for(i = 0; i < iface_query->num_tx_props; i++)
+ {
+ if(tx_prop->tx[i].ip == iptype)
+ {
+ if(position >= *num_rt_hdl || position >= MAX_NUM_PROP)
+ {
+ IPACMERR("Number of routing rules already exceeds limit.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+
+ rt_rule = &rt_rule_table->rules[position];
+ rt_rule->at_rear = false;
+ rt_rule->status = -1;
+ rt_rule->rt_rule_hdl = -1;
+ rt_rule->rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+ rt_rule->rule.hdr_hdl = 0;
+ rt_rule->rule.hdr_proc_ctx_hdl = *first_pass_hdr_proc_ctx_hdl;
+ rt_rule->rule.dst = IPA_CLIENT_DUMMY_CONS;
+
+ memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib));
+ if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II)
+ rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
+ else
+ rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
+ memcpy(rt_rule->rule.attrib.dst_mac_addr, dst_mac, sizeof(rt_rule->rule.attrib.dst_mac_addr));
+ memset(rt_rule->rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.dst_mac_addr_mask));
+ position++;
+ }
+ }
+ if(m_routing.AddRoutingRule(rt_rule_table) == false)
+ {
+ IPACMERR("Failed to add first pass rt rules.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+ for(i = 0; i < position; i++)
+ {
+ first_pass_rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl;
+ }
+ free(rt_rule_table);
+
+ /* =========== install second pass hdr (Ethernet header with L2TP tag = 18 bytes) ============= */
+ if(*second_pass_hdr_hdl != 0)
+ {
+ IPACMDBG_H("Second pass hdr was added before.\n");
+ }
+ else
+ {
+ size = sizeof(ipa_ioc_add_hdr) + sizeof(ipa_hdr_add);
+ hdr_table = (ipa_ioc_add_hdr*)malloc(size);
+ if(hdr_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(hdr_table, 0, size);
+
+ hdr_table->commit = 1;
+ hdr_table->num_hdrs = 1;
+ hdr = &hdr_table->hdr[0];
+
+ if(iptype == IPA_IP_v4)
+ {
+ snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_v4", vlan_id);
+ }
+ else
+ {
+ snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_v6", vlan_id);
+ }
+ hdr->type = IPA_HDR_L2_ETHERNET_II;
+ hdr->is_partial = 0;
+ for(i = 0; i < tx_prop->num_tx_props; i++)
+ {
+ if(tx_prop->tx[i].ip == IPA_IP_v6)
+ {
+ memset(©_hdr, 0, sizeof(copy_hdr));
+ strlcpy(copy_hdr.name, tx_prop->tx[i].hdr_name,
+ sizeof(copy_hdr.name));
+ IPACMDBG_H("Header name: %s in tx:%d\n", copy_hdr.name, i);
+ if(m_header.CopyHeader(©_hdr) == false)
+ {
+ IPACMERR("Failed to get partial header.\n");
+ free(hdr_table);
+ return IPACM_FAILURE;
+ }
+ IPACMDBG_H("Header length: %d\n", copy_hdr.hdr_len);
+ hdr->hdr_len = copy_hdr.hdr_len;
+ memcpy(hdr->hdr, copy_hdr.hdr, hdr->hdr_len);
+ break;
+ }
+ }
+ /* copy vlan client mac */
+ memcpy(hdr->hdr + hdr->hdr_len - 18, vlan_client_mac, 6);
+ hdr->hdr[hdr->hdr_len - 3] = (uint8_t)vlan_id & 0xFF;
+ hdr->hdr[hdr->hdr_len - 4] = (uint8_t)(vlan_id >> 8) & 0xFF;
+
+ if(m_header.AddHeader(hdr_table) == false)
+ {
+ IPACMERR("Failed to add hdr with status: %d\n", hdr->status);
+ free(hdr_table);
+ return IPACM_FAILURE;
+ }
+ *second_pass_hdr_hdl = hdr->hdr_hdl;
+ IPACMDBG_H("Installed second pass hdr: hdl %d\n", *second_pass_hdr_hdl);
+ free(hdr_table);
+ }
+
+ /* =========== install second pass rt rules (match VLAN interface IPv6 address at dst client side) ============= */
+ if(second_pass_rt_rule_hdl[0] != 0)
+ {
+ IPACMDBG_H("Second pass rt rule was added before, return.\n");
+ return IPACM_SUCCESS;
+ }
+
+ *num_rt_hdl = each_client_rt_rule_count[IPA_IP_v6];
+ size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add);
+ rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size);
+ if (rt_rule_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(rt_rule_table, 0, size);
+
+ rt_rule_table->commit = 1;
+ rt_rule_table->ip = IPA_IP_v6;
+ rt_rule_table->num_rules = *num_rt_hdl;
+ snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp");
+ rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0;
+
+ position = 0;
+ for(i = 0; i < iface_query->num_tx_props; i++)
+ {
+ if(tx_prop->tx[i].ip == IPA_IP_v6)
+ {
+ if(position >= *num_rt_hdl || position >= MAX_NUM_PROP)
+ {
+ IPACMERR("Number of routing rules already exceeds limit.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+
+ rt_rule = &rt_rule_table->rules[position];
+ rt_rule->at_rear = false;
+ rt_rule->status = -1;
+ rt_rule->rt_rule_hdl = -1;
+ rt_rule->rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+ rt_rule->rule.hdr_hdl = *second_pass_hdr_hdl;
+ rt_rule->rule.hdr_proc_ctx_hdl = 0;
+ rt_rule->rule.dst = tx_prop->tx[i].dst_pipe;
+
+ memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib));
+ rt_rule->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ memcpy(rt_rule->rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr,
+ sizeof(rt_rule->rule.attrib.u.v6.dst_addr));
+ memset(rt_rule->rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.u.v6.dst_addr_mask));
+ position++;
+ }
+ }
+ if(m_routing.AddRoutingRule(rt_rule_table) == false)
+ {
+ IPACMERR("Failed to add second pass rt rules.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+ for(i = 0; i < position; i++)
+ {
+ second_pass_rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl;
+ }
+ free(rt_rule_table);
+
+ return IPACM_SUCCESS;
+}
+
+/* delete l2tp rt rule for l2tp client */
+int IPACM_Lan::del_l2tp_rt_rule(ipa_ip_type iptype, uint32_t first_pass_hdr_hdl, uint32_t first_pass_hdr_proc_ctx_hdl,
+ uint32_t second_pass_hdr_hdl, int num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl)
+{
+ int i;
+
+ if(num_rt_hdl < 0)
+ {
+ IPACMERR("Invalid num rt rule: %d\n", num_rt_hdl);
+ return IPACM_FAILURE;
+ }
+
+ for(i = 0; i < num_rt_hdl; i++)
+ {
+ if(first_pass_rt_rule_hdl != NULL)
+ {
+ if(m_routing.DeleteRoutingHdl(first_pass_rt_rule_hdl[i], iptype) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+ if(second_pass_rt_rule_hdl != NULL)
+ {
+ if(m_routing.DeleteRoutingHdl(second_pass_rt_rule_hdl[i], IPA_IP_v6) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+ }
+
+ if(first_pass_hdr_proc_ctx_hdl != 0)
+ {
+ if(m_header.DeleteHeaderProcCtx(first_pass_hdr_proc_ctx_hdl) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ if(first_pass_hdr_hdl != 0)
+ {
+ if(m_header.DeleteHeaderHdl(first_pass_hdr_hdl) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+ if(second_pass_hdr_hdl != 0)
+ {
+ if(m_header.DeleteHeaderHdl(second_pass_hdr_hdl) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ return IPACM_SUCCESS;
+}
+
+/* add l2tp rt rule for non l2tp client */
+int IPACM_Lan::add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *hdr_proc_ctx_hdl,
+ int *num_rt_hdl, uint32_t *rt_rule_hdl)
+{
+ int i, size, position;
+ ipa_ioc_add_hdr_proc_ctx *hdr_proc_ctx_table;
+ ipa_hdr_proc_ctx_add *hdr_proc_ctx;
+ ipa_ioc_add_rt_rule* rt_rule_table;
+ ipa_rt_rule_add *rt_rule;
+ ipa_ioc_get_hdr hdr;
+
+ if(tx_prop == NULL)
+ {
+ IPACMERR("No tx prop.\n");
+ return IPACM_FAILURE;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ for(i = 0; i < tx_prop->num_tx_props; i++)
+ {
+ if(tx_prop->tx[i].ip == iptype)
+ {
+ strlcpy(hdr.name, tx_prop->tx[i].hdr_name,
+ sizeof(hdr.name));
+ break;
+ }
+ }
+ if(m_header.GetHeaderHandle(&hdr) == false)
+ {
+ IPACMERR("Failed to get template hdr hdl.\n");
+ return IPACM_FAILURE;
+ }
+
+ /* =========== install hdr proc ctx (uc needs to remove IPv6 + L2TP + inner ETH header = 62 bytes) ============= */
+ if(*hdr_proc_ctx_hdl != 0)
+ {
+ IPACMDBG_H("Hdr proc ctx was added before.\n");
+ }
+ else
+ {
+ size = sizeof(ipa_ioc_add_hdr_proc_ctx) + sizeof(ipa_hdr_proc_ctx_add);
+ hdr_proc_ctx_table = (ipa_ioc_add_hdr_proc_ctx*)malloc(size);
+ if(hdr_proc_ctx_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(hdr_proc_ctx_table, 0, size);
+
+ hdr_proc_ctx_table->commit = 1;
+ hdr_proc_ctx_table->num_proc_ctxs = 1;
+ hdr_proc_ctx = &hdr_proc_ctx_table->proc_ctx[0];
+
+ hdr_proc_ctx->type = IPA_HDR_PROC_L2TP_HEADER_REMOVE;
+ hdr_proc_ctx->hdr_hdl = hdr.hdl;
+ hdr_proc_ctx->l2tp_params.hdr_remove_param.hdr_len_remove = 62;
+ hdr_proc_ctx->l2tp_params.hdr_remove_param.eth_hdr_retained = 1;
+ if(m_header.AddHeaderProcCtx(hdr_proc_ctx_table) == false)
+ {
+ IPACMERR("Failed to add hdr proc ctx with status: %d\n", hdr_proc_ctx_table->proc_ctx[0].status);
+ free(hdr_proc_ctx_table);
+ return IPACM_FAILURE;
+ }
+ *hdr_proc_ctx_hdl = hdr_proc_ctx_table->proc_ctx[0].proc_ctx_hdl;
+ IPACMDBG_H("Installed hdr proc ctx: hdl %d\n", *hdr_proc_ctx_hdl);
+ free(hdr_proc_ctx_table);
+ }
+
+ /* =========== install rt rules (match dst MAC within 62 bytes header) ============= */
+ *num_rt_hdl = each_client_rt_rule_count[iptype];
+ size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add);
+ rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size);
+ if (rt_rule_table == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return IPACM_FAILURE;
+ }
+ memset(rt_rule_table, 0, size);
+
+ rt_rule_table->commit = 1;
+ rt_rule_table->ip = iptype;
+ rt_rule_table->num_rules = *num_rt_hdl;
+ snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp");
+ rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0;
+
+ position = 0;
+ for(i = 0; i < iface_query->num_tx_props; i++)
+ {
+ if(tx_prop->tx[i].ip == iptype)
+ {
+ if(position >= *num_rt_hdl || position >= MAX_NUM_PROP)
+ {
+ IPACMERR("Number of routing rules already exceeds limit.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+
+ rt_rule = &rt_rule_table->rules[position];
+ rt_rule->at_rear = false;
+ rt_rule->status = -1;
+ rt_rule->rt_rule_hdl = -1;
+ rt_rule->rule.hashable = false; //ETH->WLAN direction rules need to be non-hashable due to encapsulation
+
+ rt_rule->rule.hdr_hdl = 0;
+ rt_rule->rule.hdr_proc_ctx_hdl = *hdr_proc_ctx_hdl;
+ rt_rule->rule.dst = tx_prop->tx[i].dst_pipe;
+
+ memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib));
+
+ rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP;
+ memset(rt_rule->rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.dst_mac_addr_mask));
+ memcpy(rt_rule->rule.attrib.dst_mac_addr, dst_mac, sizeof(rt_rule->rule.attrib.dst_mac_addr));
+
+ position++;
+ }
+ }
+ if(m_routing.AddRoutingRule(rt_rule_table) == false)
+ {
+ IPACMERR("Failed to add first pass rt rules.\n");
+ free(rt_rule_table);
+ return IPACM_FAILURE;
+ }
+ for(i = 0; i < position; i++)
+ rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl;
+
+ free(rt_rule_table);
+ return IPACM_SUCCESS;
+}
+
+int IPACM_Lan::del_l2tp_rt_rule(ipa_ip_type iptype, int num_rt_hdl, uint32_t *rt_rule_hdl)
+{
+ int i;
+
+ if(num_rt_hdl < 0)
+ {
+ IPACMERR("Invalid num rt rule: %d\n", num_rt_hdl);
+ return IPACM_FAILURE;
+ }
+
+ for(i = 0; i < num_rt_hdl; i++)
+ {
+ if(m_routing.DeleteRoutingHdl(rt_rule_hdl[i], iptype) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ return IPACM_SUCCESS;
+}
+
+/* add l2tp flt rule on l2tp interface */
+int IPACM_Lan::add_l2tp_flt_rule(uint8_t *dst_mac, uint32_t *flt_rule_hdl)
+{
+ int len;
+ int fd_ipa;
+ struct ipa_flt_rule_add flt_rule_entry;
+ struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
+ ipa_ioc_get_rt_tbl rt_tbl;
+
+#ifdef FEATURE_IPA_V3
+ if (rx_prop == NULL || tx_prop == NULL)
+ {
+ IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
+ return IPACM_FAILURE;
+ }
+
+ len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
+ pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
+ if (!pFilteringTable)
+ {
+ IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
+ return IPACM_FAILURE;
+ }
+ memset(pFilteringTable, 0, len);
+
+ pFilteringTable->commit = 1;
+ pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+ pFilteringTable->ip = IPA_IP_v6;
+ pFilteringTable->num_rules = 1;
+ pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
+
+ fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
+ if(fd_ipa == 0)
+ {
+ IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
+ free(pFilteringTable);
+ return IPACM_FAILURE;
+ }
+
+ rt_tbl.ip = IPA_IP_v6;
+ snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+ rt_tbl.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+ IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+ if(m_routing.GetRoutingTable(&rt_tbl) == false)
+ {
+ IPACMERR("Failed to get routing table from name\n");
+ free(pFilteringTable);
+ close(fd_ipa);
+ return IPACM_FAILURE;
+ }
+
+ memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+ flt_rule_entry.at_rear = 1;
+
+ flt_rule_entry.rule.retain_hdr = 0;
+ flt_rule_entry.rule.to_uc = 0;
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ flt_rule_entry.rule.eq_attrib_type = 0;
+ flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+ flt_rule_entry.rule.hashable = false; //ETH->WLAN direction rules need to be non-hashable due to encapsulation
+
+ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+
+ /* flt rule is matching dst MAC within 62 bytes header */
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP;
+ memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
+ memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
+
+ memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+ if(m_filtering.AddFilteringRuleAfter(pFilteringTable) == false)
+ {
+ IPACMERR("Failed to add client filtering rules.\n");
+ free(pFilteringTable);
+ close(fd_ipa);
+ return IPACM_FAILURE;
+ }
+ *flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
+ free(pFilteringTable);
+ close(fd_ipa);
+#endif
+ return IPACM_SUCCESS;
+}
+
+/* delete l2tp flt rule on l2tp interface */
+int IPACM_Lan::del_l2tp_flt_rule(uint32_t flt_rule_hdl)
+{
+ if(m_filtering.DeleteFilteringHdls(&flt_rule_hdl, IPA_IP_v6, 1) == false)
+ {
+ return IPACM_FAILURE;
+ }
+
+ return IPACM_SUCCESS;
+}
+
+/* add l2tp flt rule on non l2tp interface */
+int IPACM_Lan::add_l2tp_flt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *vlan_client_ipv6_addr,
+ uint32_t *first_pass_flt_rule_hdl, uint32_t *second_pass_flt_rule_hdl)
+{
+ int len;
+ struct ipa_flt_rule_add flt_rule_entry;
+ struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
+ ipa_ioc_get_rt_tbl rt_tbl;
+
+#ifdef FEATURE_IPA_V3
+ if (rx_prop == NULL || tx_prop == NULL)
+ {
+ IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
+ return IPACM_FAILURE;
+ }
+
+ IPACMDBG_H("Dst client MAC 0x%02x%02x%02x%02x%02x%02x.\n", dst_mac[0], dst_mac[1],
+ dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]);
+
+ len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
+ pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
+ if (!pFilteringTable)
+ {
+ IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
+ return IPACM_FAILURE;
+ }
+ memset(pFilteringTable, 0, len);
+
+ pFilteringTable->commit = 1;
+ pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+ pFilteringTable->ip = iptype;
+ pFilteringTable->num_rules = 1;
+ pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
+
+ /* =========== add first pass flt rule (match dst MAC) ============= */
+ rt_tbl.ip = iptype;
+ snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+ IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+
+ if(m_routing.GetRoutingTable(&rt_tbl) == false)
+ {
+ IPACMERR("Failed to get routing table.\n");
+ return IPACM_FAILURE;
+ }
+
+ memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+ flt_rule_entry.at_rear = 1;
+
+ flt_rule_entry.rule.retain_hdr = 0;
+ flt_rule_entry.rule.to_uc = 0;
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ flt_rule_entry.rule.eq_attrib_type = 0;
+ flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+ flt_rule_entry.rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+
+ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+ if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
+ {
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
+ }
+ else
+ {
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
+ }
+
+ memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
+ memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
+
+ memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+ if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
+ {
+ IPACMERR("Failed to add first pass filtering rules.\n");
+ free(pFilteringTable);
+ return IPACM_FAILURE;
+ }
+ *first_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
+ /* =========== add second pass flt rule (match VLAN interface IPv6 address at client side) ============= */
+ if(*second_pass_flt_rule_hdl != 0)
+ {
+ IPACMDBG_H("Second pass flt rule was added before, return.\n");
+ free(pFilteringTable);
+ return IPACM_SUCCESS;
+ }
+
+ rt_tbl.ip = IPA_IP_v6;
+ snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+ IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+
+ if(m_routing.GetRoutingTable(&rt_tbl) == false)
+ {
+ IPACMERR("Failed to get routing table.\n");
+ return IPACM_FAILURE;
+ }
+
+ pFilteringTable->ip = IPA_IP_v6;
+ pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
+
+ memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+ flt_rule_entry.at_rear = 1;
+
+ flt_rule_entry.rule.retain_hdr = 0;
+ flt_rule_entry.rule.to_uc = 0;
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ flt_rule_entry.rule.eq_attrib_type = 0;
+ flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+ flt_rule_entry.rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+
+ 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;
+
+ memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr));
+ memset(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask));
+
+ memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+ if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
+ {
+ IPACMERR("Failed to add client filtering rules.\n");
+ free(pFilteringTable);
+ return IPACM_FAILURE;
+ }
+ *second_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
+ free(pFilteringTable);
+#endif
+ return IPACM_SUCCESS;
+}
+
+/* delete l2tp flt rule on non l2tp interface */
+int IPACM_Lan::del_l2tp_flt_rule(ipa_ip_type iptype, uint32_t first_pass_flt_rule_hdl, uint32_t second_pass_flt_rule_hdl)
+{
+ if(first_pass_flt_rule_hdl != 0)
+ {
+ if(m_filtering.DeleteFilteringHdls(&first_pass_flt_rule_hdl, iptype, 1) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ if(second_pass_flt_rule_hdl != 0)
+ {
+ if(m_filtering.DeleteFilteringHdls(&second_pass_flt_rule_hdl, iptype, 1) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ return IPACM_SUCCESS;
+}
+
+bool IPACM_Lan::is_unique_local_ipv6_addr(uint32_t* ipv6_addr)
+{
+ uint32_t ipv6_unique_local_prefix, ipv6_unique_local_prefix_mask;
+
+ if(ipv6_addr == NULL)
+ {
+ IPACMERR("IPv6 address is empty.\n");
+ return false;
+ }
+ IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]);
+
+ ipv6_unique_local_prefix = 0xFD000000;
+ ipv6_unique_local_prefix_mask = 0xFF000000;
+ if((ipv6_addr[0] & ipv6_unique_local_prefix_mask) == (ipv6_unique_local_prefix & ipv6_unique_local_prefix_mask))
+ {
+ IPACMDBG_H("This IPv6 address is unique local IPv6 address.\n");
+ return true;
+ }
+ return false;
+}
diff --git a/ipacm/src/IPACM_LanToLan.cpp b/ipacm/src/IPACM_LanToLan.cpp
index d77f389..799dfee 100644
--- a/ipacm/src/IPACM_LanToLan.cpp
+++ b/ipacm/src/IPACM_LanToLan.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014, The Linux Foundation. All rights reserved.
+Copyright (c) 2014-2017, 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
@@ -51,6 +51,8 @@
__stringify(L2_MAX)
};
+IPACM_LanToLan* IPACM_LanToLan::p_instance;
+
IPACM_LanToLan_Iface::IPACM_LanToLan_Iface(IPACM_Lan *p_iface)
{
int i;
@@ -59,12 +61,14 @@
memset(m_is_ip_addr_assigned, 0, sizeof(m_is_ip_addr_assigned));
m_support_inter_iface_offload = true;
m_support_intra_iface_offload = false;
+ m_is_l2tp_iface = false;
for(i = 0; i < IPA_HDR_L2_MAX; i++)
{
ref_cnt_peer_l2_hdr_type[i] = 0;
hdr_proc_ctx_for_inter_interface[i] = 0;
}
hdr_proc_ctx_for_intra_interface = 0;
+ hdr_proc_ctx_for_l2tp = 0;
if(p_iface->ipa_if_cate == WLAN_IF)
{
@@ -90,6 +94,14 @@
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_ADD, this);
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_DEL, this);
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, this);
+ IPACM_EvtDispatcher::registr(IPA_ADD_VLAN_IFACE, this);
+ IPACM_EvtDispatcher::registr(IPA_DEL_VLAN_IFACE, this);
+ IPACM_EvtDispatcher::registr(IPA_ADD_L2TP_VLAN_MAPPING, this);
+ IPACM_EvtDispatcher::registr(IPA_DEL_L2TP_VLAN_MAPPING, this);
+ IPACM_EvtDispatcher::registr(IPA_HANDLE_VLAN_CLIENT_INFO, this);
+ IPACM_EvtDispatcher::registr(IPA_HANDLE_VLAN_IFACE_INFO, this);
+
+ m_has_l2tp_iface = false;
return;
}
@@ -100,40 +112,115 @@
return;
}
+IPACM_LanToLan* IPACM_LanToLan::get_instance()
+{
+ if(p_instance == NULL)
+ {
+ p_instance = new IPACM_LanToLan();
+ IPACMDBG_H("Created LanToLan instance.\n");
+ }
+ return p_instance;
+}
+
+bool IPACM_LanToLan::has_l2tp_iface()
+{
+ list<IPACM_LanToLan_Iface>::iterator it;
+ bool has_l2tp_iface = false;
+
+ for(it = m_iface.begin(); it != m_iface.end(); it++)
+ {
+ if(it->is_l2tp_iface() == true)
+ {
+ has_l2tp_iface = true;
+ break;
+ }
+ }
+ return has_l2tp_iface;
+}
+
void IPACM_LanToLan::event_callback(ipa_cm_event_id event, void* param)
{
- ipacm_event_eth_bridge *data = (ipacm_event_eth_bridge*)param;
+ ipacm_event_eth_bridge *eth_bridge_data;
+ ipa_ioc_vlan_iface_info *vlan_iface_data;
+ ipa_ioc_l2tp_vlan_mapping_info *l2tp_vlan_mapping_data;
+ ipacm_event_data_all *vlan_data;
+
IPACMDBG_H("Get %s event.\n", IPACM_Iface::ipacmcfg->getEventName(event));
switch(event)
{
case IPA_ETH_BRIDGE_IFACE_UP:
{
- handle_iface_up(data);
+ eth_bridge_data = (ipacm_event_eth_bridge*)param;
+ handle_iface_up(eth_bridge_data);
break;
}
case IPA_ETH_BRIDGE_IFACE_DOWN:
{
- handle_iface_down(data);
+ eth_bridge_data = (ipacm_event_eth_bridge*)param;
+ handle_iface_down(eth_bridge_data);
break;
}
case IPA_ETH_BRIDGE_CLIENT_ADD:
{
- handle_client_add(data);
+ eth_bridge_data = (ipacm_event_eth_bridge*)param;
+ handle_client_add(eth_bridge_data);
break;
}
case IPA_ETH_BRIDGE_CLIENT_DEL:
{
- handle_client_del(data);
+ eth_bridge_data = (ipacm_event_eth_bridge*)param;
+ handle_client_del(eth_bridge_data);
break;
}
case IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH:
{
- handle_wlan_scc_mcc_switch(data);
+ eth_bridge_data = (ipacm_event_eth_bridge*)param;
+ handle_wlan_scc_mcc_switch(eth_bridge_data);
+ break;
+ }
+
+ case IPA_ADD_VLAN_IFACE:
+ {
+ vlan_iface_data = (ipa_ioc_vlan_iface_info*)param;
+ handle_add_vlan_iface(vlan_iface_data);
+ break;
+ }
+
+ case IPA_DEL_VLAN_IFACE:
+ {
+ vlan_iface_data = (ipa_ioc_vlan_iface_info*)param;
+ handle_del_vlan_iface(vlan_iface_data);
+ break;
+ }
+
+ case IPA_ADD_L2TP_VLAN_MAPPING:
+ {
+ l2tp_vlan_mapping_data = (ipa_ioc_l2tp_vlan_mapping_info*)param;
+ handle_add_l2tp_vlan_mapping(l2tp_vlan_mapping_data);
+ break;
+ }
+
+ case IPA_DEL_L2TP_VLAN_MAPPING:
+ {
+ l2tp_vlan_mapping_data = (ipa_ioc_l2tp_vlan_mapping_info*)param;
+ handle_del_l2tp_vlan_mapping(l2tp_vlan_mapping_data);
+ break;
+ }
+ case IPA_HANDLE_VLAN_CLIENT_INFO:
+ {
+ vlan_data = (ipacm_event_data_all*)param;
+ handle_vlan_client_info(vlan_data);
+ break;
+ }
+ case IPA_HANDLE_VLAN_IFACE_INFO:
+ {
+ vlan_data = (ipacm_event_data_all*)param;
+ handle_vlan_iface_info(vlan_data);
break;
}
default:
@@ -147,6 +234,8 @@
void IPACM_LanToLan::handle_iface_up(ipacm_event_eth_bridge *data)
{
list<IPACM_LanToLan_Iface>::iterator it;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+ bool has_l2tp_iface = false;
IPACMDBG_H("Interface name: %s IP type: %d\n", data->p_iface->dev_name, data->iptype);
for(it = m_iface.begin(); it != m_iface.end(); it++)
@@ -199,7 +288,28 @@
IPACMDBG_H("Now the total number of interfaces is %d.\n", m_iface.size());
IPACM_LanToLan_Iface &front_iface = m_iface.front();
+#ifdef FEATURE_L2TP
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(front_iface.set_l2tp_iface(it_mapping->vlan_iface_name) == true)
+ {
+ has_l2tp_iface = true;
+ }
+ }
+ if(m_has_l2tp_iface == false && has_l2tp_iface == true)
+ {
+ IPACMDBG_H("There is l2tp iface, add rt rules for l2tp iface.\n");
+ m_has_l2tp_iface = true;
+ for(it = ++m_iface.begin(); it != m_iface.end(); it++)
+ {
+ if(it->is_l2tp_iface() == false)
+ {
+ it->handle_l2tp_enable();
+ }
+ }
+ }
+#endif
/* install inter-interface rules */
if(front_iface.get_m_support_inter_iface_offload())
{
@@ -235,6 +345,7 @@
void IPACM_LanToLan::handle_iface_down(ipacm_event_eth_bridge *data)
{
list<IPACM_LanToLan_Iface>::iterator it_target_iface;
+ bool has_l2tp_iface = false;
IPACMDBG_H("Interface name: %s\n", data->p_iface->dev_name);
@@ -257,7 +368,29 @@
it_target_iface->handle_down_event();
m_iface.erase(it_target_iface);
+#ifdef FEATURE_L2TP
+ for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++)
+ {
+ if(it_target_iface->is_l2tp_iface() == true)
+ {
+ has_l2tp_iface = true;
+ break;
+ }
+ }
+ if(m_has_l2tp_iface == true && has_l2tp_iface == false)
+ {
+ IPACMDBG_H("There is no l2tp iface now, delete rt rules for l2tp iface.\n");
+ m_has_l2tp_iface = false;
+ for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++)
+ {
+ if(it_target_iface->is_l2tp_iface() == false)
+ {
+ it_target_iface->handle_l2tp_disable();
+ }
+ }
+ }
+#endif
return;
}
@@ -301,16 +434,35 @@
void IPACM_LanToLan::handle_client_add(ipacm_event_eth_bridge *data)
{
list<IPACM_LanToLan_Iface>::iterator it_iface;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+ l2tp_vlan_mapping_info *mapping_info = NULL;
+ bool is_l2tp_client = false;
IPACMDBG_H("Incoming client MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\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], data->p_iface->dev_name);
-
+#ifdef FEATURE_L2TP
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(strncmp(it_mapping->l2tp_iface_name, data->iface_name,
+ sizeof(it_mapping->l2tp_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found l2tp iface %s with l2tp client MAC 0x%02x%02x%02x%02x%02x%02x\n",
+ it_mapping->l2tp_iface_name, it_mapping->l2tp_client_mac[0], it_mapping->l2tp_client_mac[1],
+ it_mapping->l2tp_client_mac[2], it_mapping->l2tp_client_mac[3], it_mapping->l2tp_client_mac[4],
+ it_mapping->l2tp_client_mac[5]);
+ memcpy(it_mapping->l2tp_client_mac, data->mac_addr, sizeof(it_mapping->l2tp_client_mac));
+ mapping_info = &(*it_mapping);
+ is_l2tp_client = true;
+ break;
+ }
+ }
+#endif
for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
{
if(it_iface->get_iface_pointer() == data->p_iface) //find the interface
{
IPACMDBG_H("Found the interface.\n");
- it_iface->handle_client_add(data->mac_addr);
+ it_iface->handle_client_add(data->mac_addr, is_l2tp_client, mapping_info);
break;
}
}
@@ -373,6 +525,241 @@
return;
}
+void IPACM_LanToLan::handle_add_vlan_iface(ipa_ioc_vlan_iface_info *data)
+{
+ list<vlan_iface_info>::iterator it_vlan;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+ vlan_iface_info new_vlan_info;
+
+ IPACMDBG_H("Vlan iface: %s vlan id: %d\n", data->name, data->vlan_id);
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ if(strncmp(it_vlan->vlan_iface_name, data->name, sizeof(it_vlan->vlan_iface_name)) == 0)
+ {
+ IPACMERR("The vlan iface was added before with id %d\n", it_vlan->vlan_id);
+ return;
+ }
+ }
+
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(strncmp(data->name, it_mapping->vlan_iface_name, sizeof(data->name)) == 0)
+ {
+ IPACMDBG_H("Found a mapping: l2tp iface %s.\n", it_mapping->l2tp_iface_name);
+ it_mapping->vlan_id = data->vlan_id;
+ }
+ }
+
+ memset(&new_vlan_info, 0 , sizeof(new_vlan_info));
+ strlcpy(new_vlan_info.vlan_iface_name, data->name, sizeof(new_vlan_info.vlan_iface_name));
+ new_vlan_info.vlan_id = data->vlan_id;
+ m_vlan_iface.push_front(new_vlan_info);
+ return;
+}
+
+void IPACM_LanToLan::handle_del_vlan_iface(ipa_ioc_vlan_iface_info *data)
+{
+ list<vlan_iface_info>::iterator it_vlan;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+
+ IPACMDBG_H("Vlan iface: %s vlan id: %d\n", data->name, data->vlan_id);
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ if(strncmp(it_vlan->vlan_iface_name, data->name, sizeof(it_vlan->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found the vlan interface\n");
+ m_vlan_iface.erase(it_vlan);
+ break;
+ }
+ }
+
+ it_mapping = m_l2tp_vlan_mapping.begin();
+ while(it_mapping != m_l2tp_vlan_mapping.end())
+ {
+ if(strncmp(data->name, it_mapping->vlan_iface_name, sizeof(data->name)) == 0)
+ {
+ IPACMDBG_H("Delete mapping with l2tp iface %s\n", it_mapping->l2tp_iface_name);
+ it_mapping = m_l2tp_vlan_mapping.erase(it_mapping);
+ }
+ else
+ {
+ it_mapping++;
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan::handle_add_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data)
+{
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+ list<vlan_iface_info>::iterator it_vlan;
+ list<IPACM_LanToLan_Iface>::iterator it_iface;
+ l2tp_vlan_mapping_info new_mapping;
+ bool has_l2tp_iface = false;
+
+ IPACMDBG_H("L2tp iface: %s session id: %d vlan iface: %s \n",
+ data->l2tp_iface_name, data->l2tp_session_id, data->vlan_iface_name);
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(strncmp(data->l2tp_iface_name, it_mapping->l2tp_iface_name,
+ sizeof(data->l2tp_iface_name)) == 0)
+ {
+ IPACMERR("L2tp mapping was added before mapped to vlan %s.\n", it_mapping->vlan_iface_name);
+ return;
+ }
+ }
+ memset(&new_mapping, 0, sizeof(new_mapping));
+ strlcpy(new_mapping.l2tp_iface_name, data->l2tp_iface_name,
+ sizeof(new_mapping.l2tp_iface_name));
+ strlcpy(new_mapping.vlan_iface_name, data->vlan_iface_name,
+ sizeof(new_mapping.vlan_iface_name));
+ new_mapping.l2tp_session_id = data->l2tp_session_id;
+
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ if(strncmp(it_vlan->vlan_iface_name, data->vlan_iface_name, sizeof(it_vlan->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found vlan iface with id %d\n", it_vlan->vlan_id);
+ new_mapping.vlan_id = it_vlan->vlan_id;
+ memcpy(new_mapping.vlan_iface_ipv6_addr, it_vlan->vlan_iface_ipv6_addr,
+ sizeof(new_mapping.vlan_iface_ipv6_addr));
+ memcpy(new_mapping.vlan_client_mac, it_vlan->vlan_client_mac,
+ sizeof(new_mapping.vlan_client_mac));
+ memcpy(new_mapping.vlan_client_ipv6_addr, it_vlan->vlan_client_ipv6_addr,
+ sizeof(new_mapping.vlan_client_ipv6_addr));
+ break;
+ }
+ }
+ m_l2tp_vlan_mapping.push_front(new_mapping);
+
+ for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
+ {
+ if(it_iface->set_l2tp_iface(data->vlan_iface_name) == true)
+ {
+ has_l2tp_iface = true;
+ }
+ }
+
+ if(m_has_l2tp_iface == false && has_l2tp_iface == true)
+ {
+ IPACMDBG_H("There is l2tp iface, add rt rules for l2tp iface.\n");
+ m_has_l2tp_iface = true;
+ for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
+ {
+ if(it_iface->is_l2tp_iface() == false)
+ {
+ it_iface->handle_l2tp_enable();
+ }
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan::handle_del_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data)
+{
+ list<l2tp_vlan_mapping_info>::iterator it;
+ list<IPACM_LanToLan_Iface>::iterator it_iface;
+
+ IPACMDBG_H("L2tp iface: %s session id: %d vlan iface: %s \n",
+ data->l2tp_iface_name, data->l2tp_session_id, data->vlan_iface_name);
+ for(it = m_l2tp_vlan_mapping.begin(); it != m_l2tp_vlan_mapping.end(); it++)
+ {
+ if(strncmp(data->l2tp_iface_name, it->l2tp_iface_name,
+ sizeof(data->l2tp_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found l2tp iface mapped to vlan %s.\n", it->vlan_iface_name);
+ if(strncmp(data->vlan_iface_name, it->vlan_iface_name,
+ sizeof(data->vlan_iface_name)) == 0)
+ {
+ m_l2tp_vlan_mapping.erase(it);
+ }
+ else
+ {
+ IPACMERR("Incoming mapping is incorrect.\n");
+ }
+ break;
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan::handle_vlan_client_info(ipacm_event_data_all *data)
+{
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+ list<vlan_iface_info>::iterator it_vlan;
+
+ IPACMDBG_H("Incoming vlan client iface: %s IPv6 address: 0x%08x%08x%08x%08x\n", data->iface_name,
+ data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
+ IPACMDBG_H("MAC address: 0x%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]);
+
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ if(strncmp(it_vlan->vlan_iface_name, data->iface_name, sizeof(it_vlan->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found vlan iface in vlan list: %s\n", it_vlan->vlan_iface_name);
+ if(it_vlan->vlan_client_ipv6_addr[0] > 0 || it_vlan->vlan_client_ipv6_addr[1] > 0 ||
+ it_vlan->vlan_client_ipv6_addr[2] > 0 || it_vlan->vlan_client_ipv6_addr[3] > 0)
+ {
+ IPACMDBG_H("Vlan client info has been populated before, return.\n");
+ return;
+ }
+ memcpy(it_vlan->vlan_client_mac, data->mac_addr, sizeof(it_vlan->vlan_client_mac));
+ memcpy(it_vlan->vlan_client_ipv6_addr, data->ipv6_addr, sizeof(it_vlan->vlan_client_ipv6_addr));
+ }
+ }
+
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(strncmp(it_mapping->vlan_iface_name, data->iface_name, sizeof(it_mapping->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found vlan iface in l2tp mapping list: %s, l2tp iface: %s\n", it_mapping->vlan_iface_name,
+ it_mapping->l2tp_iface_name);
+ memcpy(it_mapping->vlan_client_mac, data->mac_addr, sizeof(it_mapping->vlan_client_mac));
+ memcpy(it_mapping->vlan_client_ipv6_addr, data->ipv6_addr, sizeof(it_mapping->vlan_client_ipv6_addr));
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan::handle_vlan_iface_info(ipacm_event_data_all *data)
+{
+ list<vlan_iface_info>::iterator it_vlan;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
+
+ IPACMDBG_H("Incoming vlan iface: %s IPv6 address: 0x%08x%08x%08x%08x\n", data->iface_name,
+ data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
+
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ if(strncmp(it_vlan->vlan_iface_name, data->iface_name,
+ sizeof(it_vlan->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found vlan iface: %s\n", it_vlan->vlan_iface_name);
+ memcpy(it_vlan->vlan_iface_ipv6_addr, data->ipv6_addr,
+ sizeof(it_vlan->vlan_iface_ipv6_addr));
+
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ if(strncmp(it_mapping->vlan_iface_name, it_vlan->vlan_iface_name,
+ sizeof(it_mapping->vlan_iface_name)) == 0)
+ {
+ IPACMDBG_H("Found the l2tp-vlan mapping: l2tp %s\n", it_mapping->l2tp_iface_name);
+ memcpy(it_mapping->vlan_iface_ipv6_addr, data->ipv6_addr,
+ sizeof(it_mapping->vlan_iface_ipv6_addr));
+ }
+ }
+ break;
+ }
+ }
+
+ if(it_vlan == m_vlan_iface.end())
+ {
+ IPACMDBG_H("Failed to find the vlan iface: %s\n", data->iface_name);
+ }
+ return;
+}
+
void IPACM_LanToLan::handle_cached_client_add_event(IPACM_Lan *p_iface)
{
list<ipacm_event_eth_bridge>::iterator it;
@@ -420,10 +807,42 @@
{
list<IPACM_LanToLan_Iface>::iterator it;
list<ipacm_event_eth_bridge>::iterator it_event;
+ list<vlan_iface_info>::iterator it_vlan;
+ list<l2tp_vlan_mapping_info>::iterator it_mapping;
int i;
- IPACMDBG_H("There are %d interfaces in total.\n", m_iface.size());
+ IPACMDBG_H("Is there l2tp interface? %d\n", m_has_l2tp_iface);
+ IPACMDBG_H("There are %d vlan interfaces.\n", m_vlan_iface.size());
+ for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++)
+ {
+ IPACMDBG_H("Vlan iface: %s, id: %d, ipv6 addr: 0x%08x%08x%08x%08x\n", it_vlan->vlan_iface_name,
+ it_vlan->vlan_id, it_vlan->vlan_iface_ipv6_addr[0], it_vlan->vlan_iface_ipv6_addr[1],
+ it_vlan->vlan_iface_ipv6_addr[2], it_vlan->vlan_iface_ipv6_addr[3]);
+ IPACMDBG_H("Vlan client mac: 0x%02x%02x%02x%02x%02x%02x, ipv6 addr: 0x%08x%08x%08x%08x\n",
+ it_vlan->vlan_client_mac[0], it_vlan->vlan_client_mac[1], it_vlan->vlan_client_mac[2],
+ it_vlan->vlan_client_mac[3], it_vlan->vlan_client_mac[4], it_vlan->vlan_client_mac[5],
+ it_vlan->vlan_client_ipv6_addr[0], it_vlan->vlan_client_ipv6_addr[1], it_vlan->vlan_client_ipv6_addr[2],
+ it_vlan->vlan_client_ipv6_addr[3]);
+ }
+
+ IPACMDBG_H("There are %d vlan-l2tp mapping.\n", m_l2tp_vlan_mapping.size());
+ for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++)
+ {
+ IPACMDBG_H("L2tp iface: %s, session id: %d\n", it_mapping->l2tp_iface_name, it_mapping->l2tp_session_id);
+ IPACMDBG_H("Vlan iface: %s, id: %d, ipv6 addr: 0x%08x%08x%08x%08x\n", it_mapping->vlan_iface_name,
+ it_mapping->vlan_id, it_mapping->vlan_iface_ipv6_addr[0], it_mapping->vlan_iface_ipv6_addr[1],
+ it_mapping->vlan_iface_ipv6_addr[2], it_mapping->vlan_iface_ipv6_addr[3]);
+ IPACMDBG_H("Vlan client mac: 0x%02x%02x%02x%02x%02x%02x, ipv6 addr: 0x%08x%08x%08x%08x\n",
+ it_mapping->vlan_client_mac[0], it_mapping->vlan_client_mac[1], it_mapping->vlan_client_mac[2],
+ it_mapping->vlan_client_mac[3], it_mapping->vlan_client_mac[4], it_mapping->vlan_client_mac[5],
+ it_mapping->vlan_client_ipv6_addr[0], it_mapping->vlan_client_ipv6_addr[1], it_mapping->vlan_client_ipv6_addr[2],
+ it_mapping->vlan_client_ipv6_addr[3]);
+ IPACMDBG_H("L2tp client mac: 0x%02x%02x%02x%02x%02x%02x\n", it_mapping->l2tp_client_mac[0], it_mapping->l2tp_client_mac[1],
+ it_mapping->l2tp_client_mac[2], it_mapping->l2tp_client_mac[3], it_mapping->l2tp_client_mac[4], it_mapping->l2tp_client_mac[5]);
+ }
+
+ IPACMDBG_H("There are %d interfaces in total.\n", m_iface.size());
for(it = m_iface.begin(); it != m_iface.end(); it++)
{
it->print_data_structure_info();
@@ -453,7 +872,16 @@
{
for(it = m_client_info.begin(); it != m_client_info.end(); it++)
{
+#ifdef FEATURE_L2TP
+ if(it->is_l2tp_client == false)
+ {
+ add_client_rt_rule(&peer, &(*it));
+ }
+ /* add l2tp rt rules */
+ add_l2tp_client_rt_rule(&peer, &(*it));
+#else
add_client_rt_rule(&peer, &(*it));
+#endif
}
}
@@ -524,6 +952,40 @@
return;
}
+void IPACM_LanToLan_Iface::add_l2tp_client_rt_rule(peer_iface_info *peer, client_info *client)
+{
+ ipa_hdr_l2_type peer_l2_hdr_type;
+ l2tp_vlan_mapping_info *mapping_info;
+
+ peer_l2_hdr_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
+ mapping_info = client->mapping_info;
+ if(client->is_l2tp_client)
+ {
+ m_p_iface->add_l2tp_rt_rule(IPA_IP_v4, client->mac_addr, peer_l2_hdr_type, mapping_info->l2tp_session_id,
+ mapping_info->vlan_id, mapping_info->vlan_client_mac, mapping_info->vlan_iface_ipv6_addr,
+ mapping_info->vlan_client_ipv6_addr, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl,
+ &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl,
+ &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v4],
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl);
+
+ m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, client->mac_addr, peer_l2_hdr_type, mapping_info->l2tp_session_id,
+ mapping_info->vlan_id, mapping_info->vlan_client_mac, mapping_info->vlan_iface_ipv6_addr,
+ mapping_info->vlan_client_ipv6_addr, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl,
+ &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6], &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl,
+ &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6],
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl);
+ }
+ else
+ {
+ if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true)
+ {
+ m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, client->mac_addr, &hdr_proc_ctx_for_l2tp, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6],
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6]);
+ }
+ }
+ return;
+}
+
void IPACM_LanToLan_Iface::add_all_inter_interface_client_flt_rule(ipa_ip_type iptype)
{
list<peer_iface_info>::iterator it_iface;
@@ -581,39 +1043,74 @@
{
list<flt_rule_info>::iterator it_flt;
uint32_t flt_rule_hdl;
+ uint32_t l2tp_first_pass_flt_rule_hdl = 0, l2tp_second_pass_flt_rule_hdl = 0;
flt_rule_info new_flt_info;
ipa_ioc_get_rt_tbl rt_tbl;
- rt_tbl.ip = iptype;
- memcpy(rt_tbl.name, peer->rt_tbl_name_for_flt[iptype], sizeof(rt_tbl.name));
- IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
-
- if(IPACM_Iface::m_routing.GetRoutingTable(&rt_tbl) == false)
+ if(m_is_l2tp_iface && iptype == IPA_IP_v4)
{
- IPACMERR("Failed to get routing table.\n");
+ IPACMDBG_H("No need to install IPv4 flt rule on l2tp interface.\n");
return;
}
- m_p_iface->eth_bridge_add_flt_rule(client->mac_addr, rt_tbl.hdl,
- iptype, &flt_rule_hdl);
- IPACMDBG_H("Installed flt rule for IP type %d: handle %d\n", iptype, flt_rule_hdl);
-
for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++)
{
if(it_flt->p_client == client) //the client is already in the flt info list
{
IPACMDBG_H("The client is found in flt info list.\n");
- it_flt->flt_rule_hdl[iptype] = flt_rule_hdl;
break;
}
}
- if(it_flt == peer->flt_rule.end()) //the client is not in the flt info list
+ if(it_flt != peer->flt_rule.end())
+ {
+ l2tp_first_pass_flt_rule_hdl = it_flt->l2tp_first_pass_flt_rule_hdl[iptype];
+ l2tp_second_pass_flt_rule_hdl = it_flt->l2tp_second_pass_flt_rule_hdl;
+ }
+
+ if(m_is_l2tp_iface)
+ {
+ m_p_iface->add_l2tp_flt_rule(client->mac_addr, &l2tp_first_pass_flt_rule_hdl);
+ }
+ else
+ {
+ if(client->is_l2tp_client)
+ {
+ m_p_iface->add_l2tp_flt_rule(iptype, client->mac_addr, client->mapping_info->vlan_client_ipv6_addr,
+ &l2tp_first_pass_flt_rule_hdl, &l2tp_second_pass_flt_rule_hdl);
+ }
+ else
+ {
+ rt_tbl.ip = iptype;
+ memcpy(rt_tbl.name, peer->rt_tbl_name_for_flt[iptype], sizeof(rt_tbl.name));
+ IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+
+ if(IPACM_Iface::m_routing.GetRoutingTable(&rt_tbl) == false)
+ {
+ IPACMERR("Failed to get routing table.\n");
+ return;
+ }
+
+ m_p_iface->eth_bridge_add_flt_rule(client->mac_addr, rt_tbl.hdl,
+ iptype, &flt_rule_hdl);
+ IPACMDBG_H("Installed flt rule for IP type %d: handle %d\n", iptype, flt_rule_hdl);
+ }
+ }
+
+ if(it_flt != peer->flt_rule.end())
+ {
+ it_flt->flt_rule_hdl[iptype] = flt_rule_hdl;
+ it_flt->l2tp_first_pass_flt_rule_hdl[iptype] = l2tp_first_pass_flt_rule_hdl;
+ it_flt->l2tp_second_pass_flt_rule_hdl = l2tp_second_pass_flt_rule_hdl;
+ }
+ else
{
IPACMDBG_H("The client is not found in flt info list, insert a new one.\n");
memset(&new_flt_info, 0, sizeof(new_flt_info));
new_flt_info.p_client = client;
new_flt_info.flt_rule_hdl[iptype] = flt_rule_hdl;
+ new_flt_info.l2tp_first_pass_flt_rule_hdl[iptype] = l2tp_first_pass_flt_rule_hdl;
+ new_flt_info.l2tp_second_pass_flt_rule_hdl = l2tp_second_pass_flt_rule_hdl;
peer->flt_rule.push_front(new_flt_info);
}
@@ -648,15 +1145,50 @@
IPACMDBG_H("Found the client in flt info list.\n");
if(m_is_ip_addr_assigned[IPA_IP_v4])
{
- m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
- IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
+ if(m_is_l2tp_iface)
+ {
+ IPACMDBG_H("No IPv4 client flt rule on l2tp iface.\n");
+ }
+ else
+ {
+ if(client->is_l2tp_client)
+ {
+ m_p_iface->del_l2tp_flt_rule(IPA_IP_v4, it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4],
+ it_flt->l2tp_second_pass_flt_rule_hdl);
+ it_flt->l2tp_second_pass_flt_rule_hdl = 0;
+ IPACMDBG_H("Deleted IPv4 first pass flt rule %d and second pass flt rule %d.\n",
+ it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], it_flt->l2tp_second_pass_flt_rule_hdl);
+ }
+ else
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
+ IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
+ }
+ }
}
if(m_is_ip_addr_assigned[IPA_IP_v6])
{
- m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
- IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
+ if(m_is_l2tp_iface)
+ {
+ m_p_iface->del_l2tp_flt_rule(it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
+ IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
+ }
+ else
+ {
+ if(client->is_l2tp_client)
+ {
+ m_p_iface->del_l2tp_flt_rule(IPA_IP_v6, it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6],
+ it_flt->l2tp_second_pass_flt_rule_hdl);
+ IPACMDBG_H("Deleted IPv6 first pass flt rule %d and second pass flt rule %d.\n",
+ it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], it_flt->l2tp_second_pass_flt_rule_hdl);
+ }
+ else
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
+ IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
+ }
+ }
}
-
peer->flt_rule.erase(it_flt);
break;
}
@@ -675,21 +1207,41 @@
{
IPACMDBG_H("Delete routing rules for inter interface communication.\n");
- num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4];
- for(i = 0; i < num_rules; i++)
+ if(client->is_l2tp_client == false)
{
- m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i], IPA_IP_v4);
- IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]);
- }
- client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = 0;
+ num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4];
+ for(i = 0; i < num_rules; i++)
+ {
+ m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i], IPA_IP_v4);
+ IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]);
+ }
+ client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = 0;
- num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6];
- for(i = 0; i < num_rules; i++)
- {
- m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i], IPA_IP_v6);
- IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]);
+ num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6];
+ for(i = 0; i < num_rules; i++)
+ {
+ m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i], IPA_IP_v6);
+ IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]);
+ }
+ client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = 0;
+
+ if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true)
+ {
+ m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6],
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6]);
+ }
}
- client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = 0;
+ else
+ {
+ m_p_iface->del_l2tp_rt_rule(IPA_IP_v4, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl,
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl,
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v4],
+ client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl);
+
+ m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, 0, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6],
+ 0, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6],
+ NULL);
+ }
}
else
{
@@ -786,13 +1338,49 @@
{
if(m_is_ip_addr_assigned[IPA_IP_v4])
{
- m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
- IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v4]);
+ if(m_is_l2tp_iface)
+ {
+ IPACMDBG_H("No IPv4 client flt rule on l2tp iface.\n");
+ }
+ else
+ {
+ if(it->p_client->is_l2tp_client)
+ {
+ m_p_iface->del_l2tp_flt_rule(IPA_IP_v4, it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4],
+ it->l2tp_second_pass_flt_rule_hdl);
+ it->l2tp_second_pass_flt_rule_hdl = 0;
+ IPACMDBG_H("Deleted IPv4 first pass flt rule %d and second pass flt rule %d.\n",
+ it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], it->l2tp_second_pass_flt_rule_hdl);
+ }
+ else
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
+ IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it->flt_rule_hdl[IPA_IP_v4]);
+ }
+ }
}
if(m_is_ip_addr_assigned[IPA_IP_v6])
{
- m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
- IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v6]);
+ if(m_is_l2tp_iface)
+ {
+ m_p_iface->del_l2tp_flt_rule(it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
+ IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
+ }
+ else
+ {
+ if(it->p_client->is_l2tp_client)
+ {
+ m_p_iface->del_l2tp_flt_rule(IPA_IP_v6, it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6],
+ it->l2tp_second_pass_flt_rule_hdl);
+ IPACMDBG_H("Deleted IPv6 first pass flt rule %d and second pass flt rule %d.\n",
+ it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], it->l2tp_second_pass_flt_rule_hdl);
+ }
+ else
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
+ IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it->flt_rule_hdl[IPA_IP_v6]);
+ }
+ }
}
}
peer->flt_rule.clear();
@@ -811,6 +1399,11 @@
{
del_client_rt_rule(peer, &(*it));
}
+ if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true)
+ {
+ m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_l2tp);
+ hdr_proc_ctx_for_l2tp = 0;
+ }
}
return;
@@ -944,7 +1537,7 @@
return;
}
-void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac)
+void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info)
{
list<client_info>::iterator it_client;
list<peer_iface_info>::iterator it_peer_info;
@@ -966,7 +1559,11 @@
return;
}
+ IPACMDBG_H("is_l2tp_client: %d, mapping_info: %p\n", is_l2tp_client, mapping_info);
+ memset(&new_client, 0, sizeof(new_client));
memcpy(new_client.mac_addr, mac, sizeof(new_client.mac_addr));
+ new_client.is_l2tp_client = is_l2tp_client;
+ new_client.mapping_info = mapping_info;
m_client_info.push_front(new_client);
client_info &front_client = m_client_info.front();
@@ -981,7 +1578,14 @@
if(flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] == false)
{
/* add client routing rule for each peer interface */
- add_client_rt_rule(&(*it_peer_info), &front_client);
+ if(front_client.is_l2tp_client == false)
+ {
+ add_client_rt_rule(&(*it_peer_info), &front_client);
+ }
+#ifdef FEATURE_L2TP
+ /* add l2tp rt rules */
+ add_l2tp_client_rt_rule(&(*it_peer_info), &front_client);
+#endif
flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true;
}
@@ -1042,6 +1646,12 @@
{
IPACMDBG_H("Delete client routing rule for peer interface.\n");
del_client_rt_rule(&(*it_peer_info), &(*it_client));
+ if(it_client->is_l2tp_client == false && IPACM_LanToLan::get_instance()->has_l2tp_iface() == true
+ && m_client_info.size() == 1)
+ {
+ m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_l2tp);
+ hdr_proc_ctx_for_l2tp = 0;
+ }
flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true;
}
}
@@ -1105,6 +1715,7 @@
IPACMDBG_H("Is IPv6 addr assigned? %d\n", m_is_ip_addr_assigned[IPA_IP_v6]);
IPACMDBG_H("Support inter interface offload? %d\n", m_support_inter_iface_offload);
IPACMDBG_H("Support intra interface offload? %d\n", m_support_intra_iface_offload);
+ IPACMDBG_H("Is l2tp interface? %d\n", m_is_l2tp_iface);
if(m_support_inter_iface_offload)
{
@@ -1123,12 +1734,19 @@
IPACMDBG_H("Hdr proc ctx for intra-interface: %d\n", hdr_proc_ctx_for_intra_interface);
}
+ IPACMDBG_H("Hdr proc ctx for l2tp: %d\n", hdr_proc_ctx_for_l2tp);
+
i = 1;
IPACMDBG_H("There are %d clients in total.\n", m_client_info.size());
for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
{
IPACMDBG_H("Client %d MAC: 0x%02x%02x%02x%02x%02x%02x Pointer: 0x%08x\n", i, it_client->mac_addr[0], it_client->mac_addr[1],
it_client->mac_addr[2], it_client->mac_addr[3], it_client->mac_addr[4], it_client->mac_addr[5], &(*it_client));
+ IPACMDBG_H("Is l2tp client? %d\n", it_client->is_l2tp_client);
+ if(it_client->is_l2tp_client && it_client->mapping_info)
+ {
+ IPACMDBG_H("Vlan iface associated with this client: %s\n", it_client->mapping_info->vlan_iface_name);
+ }
if(m_support_inter_iface_offload)
{
@@ -1149,6 +1767,54 @@
{
IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[j].rule_hdl[IPA_IP_v6][k]);
}
+
+ if(it_client->is_l2tp_client)
+ {
+ IPACMDBG_H("Printing l2tp hdr info for l2tp client.\n");
+ IPACMDBG_H("First pass hdr hdl: %d, IPv4 hdr proc ctx hdl: IPv6 hdr proc ctx hdl: %d\n",
+ it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_hdl, it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4],
+ it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6]);
+ IPACMDBG_H("Second pass hdr hdl: %d\n", it_client->l2tp_rt_rule_hdl[j].second_pass_hdr_hdl);
+
+ IPACMDBG_H("Printing l2tp routing rule info for l2tp client.\n");
+ IPACMDBG_H("Number of IPv4 routing rules is %d, first pass handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]);
+ for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]; k++)
+ {
+ IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v4][k]);
+ }
+ IPACMDBG_H("Number of IPv6 routing rules is %d, first pass handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]);
+ for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++)
+ {
+ IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v6][k]);
+ }
+ IPACMDBG_H("Second pass handles:\n");
+ for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++)
+ {
+ IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].second_pass_rt_rule_hdl[k]);
+ }
+ }
+ else
+ {
+ if(IPACM_LanToLan::get_instance()->has_l2tp_iface())
+ {
+ IPACMDBG_H("Printing l2tp hdr info for non l2tp client.\n");
+ IPACMDBG_H("Hdr hdl: %d, IPv4 hdr proc ctx hdl: IPv6 hdr proc ctx hdl: %d\n",
+ it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_hdl, it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4],
+ it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6]);
+
+ IPACMDBG_H("Printing l2tp routing rule info for non l2tp client.\n");
+ IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]);
+ for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]; k++)
+ {
+ IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v4][k]);
+ }
+ IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]);
+ for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++)
+ {
+ IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v6][k]);
+ }
+ }
+ }
}
}
}
@@ -1200,11 +1866,14 @@
if(m_is_ip_addr_assigned[IPA_IP_v4])
{
IPACMDBG_H("IPv4 %d\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
+ IPACMDBG_H("IPv4 l2tp first pass flt rule: %d\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4]);
}
if(m_is_ip_addr_assigned[IPA_IP_v6])
{
IPACMDBG_H("IPv6 %d\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
+ IPACMDBG_H("IPv6 l2tp first pass flt rule: %d\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
}
+ IPACMDBG_H("L2tp second pass flt rule: %d\n", it_flt->l2tp_second_pass_flt_rule_hdl);
}
return;
@@ -1260,3 +1929,120 @@
return;
}
+
+bool IPACM_LanToLan_Iface::set_l2tp_iface(char *vlan_iface_name)
+{
+ IPACMDBG_H("Self iface %s, vlan iface %s\n", m_p_iface->dev_name,
+ vlan_iface_name);
+
+ if(m_is_l2tp_iface == false)
+ {
+ if(strncmp(m_p_iface->dev_name, vlan_iface_name, strlen(m_p_iface->dev_name)) == 0)
+ {
+ IPACMDBG_H("This interface is l2tp interface.\n");
+ m_is_l2tp_iface = true;
+ switch_to_l2tp_iface();
+ }
+ }
+ return m_is_l2tp_iface;
+}
+
+bool IPACM_LanToLan_Iface::is_l2tp_iface()
+{
+ return m_is_l2tp_iface;
+}
+
+void IPACM_LanToLan_Iface::switch_to_l2tp_iface()
+{
+ list<peer_iface_info>::iterator it_peer;
+ list<flt_rule_info>::iterator it_flt;
+
+ for(it_peer = m_peer_iface_info.begin(); it_peer != m_peer_iface_info.end(); it_peer++)
+ {
+ for(it_flt = it_peer->flt_rule.begin(); it_flt != it_peer->flt_rule.end(); it_flt++)
+ {
+ if(m_is_ip_addr_assigned[IPA_IP_v4])
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
+ IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
+ }
+ if(m_is_ip_addr_assigned[IPA_IP_v6])
+ {
+ m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
+ m_p_iface->add_l2tp_flt_rule(it_flt->p_client->mac_addr, &it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]);
+ IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
+ }
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan_Iface::handle_l2tp_enable()
+{
+ int i;
+ ipa_hdr_l2_type peer_l2_hdr_type;
+ list<peer_iface_info>::iterator it_peer_info;
+ list<client_info>::iterator it_client;
+ bool flag[IPA_HDR_L2_MAX];
+
+ if(m_support_inter_iface_offload)
+ {
+ memset(flag, 0, sizeof(flag));
+ for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++)
+ {
+ if(it_peer_info->peer->is_l2tp_iface())
+ {
+ peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
+ flag[peer_l2_hdr_type] = true;
+ }
+ }
+
+ for(i = 0; i < IPA_HDR_L2_MAX; i++)
+ {
+ if(flag[i] == true)
+ {
+ IPACMDBG_H("Add rt rule for peer l2 type %s\n", ipa_l2_hdr_type[i]);
+ for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
+ {
+ m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, it_client->mac_addr, &hdr_proc_ctx_for_l2tp,
+ &it_client->l2tp_rt_rule_hdl[i].num_rt_hdl[IPA_IP_v6],
+ it_client->l2tp_rt_rule_hdl[i].first_pass_rt_rule_hdl[IPA_IP_v6]);
+ }
+ }
+ }
+ }
+ return;
+}
+
+void IPACM_LanToLan_Iface::handle_l2tp_disable()
+{
+ int i;
+ ipa_hdr_l2_type peer_l2_hdr_type;
+ list<peer_iface_info>::iterator it_peer_info;
+ list<client_info>::iterator it_client;
+ bool flag[IPA_HDR_L2_MAX];
+
+ if(m_support_inter_iface_offload)
+ {
+ memset(flag, 0, sizeof(flag));
+ for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++)
+ {
+ peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
+ flag[peer_l2_hdr_type] = true;
+ }
+
+ for(i = 0; i < IPA_HDR_L2_MAX; i++)
+ {
+ if(flag[i] == true)
+ {
+ IPACMDBG_H("Delete rt rule for peer l2 type %s\n", ipa_l2_hdr_type[i]);
+ for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
+ {
+ m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, it_client->l2tp_rt_rule_hdl[i].num_rt_hdl[IPA_IP_v6],
+ it_client->l2tp_rt_rule_hdl[i].first_pass_rt_rule_hdl[IPA_IP_v6]);
+ }
+ }
+ }
+ }
+ return;
+}
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 16ec73a..6bd0cbd 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -232,6 +232,8 @@
ipacm_event_data_wlan_ex *data_ex;
ipa_get_data_stats_resp_msg_v01 *data_tethering_stats = NULL;
ipa_get_apn_data_stats_resp_msg_v01 *data_network_stats = NULL;
+ ipa_ioc_vlan_iface_info *vlan_info = NULL;
+ ipa_ioc_l2tp_vlan_mapping_info *mapping = NULL;
ipacm_cmd_q_data new_neigh_evt;
ipacm_event_data_all* new_neigh_data;
@@ -677,6 +679,7 @@
evt_data.event = IPA_NETWORK_STATS_UPDATE_EVENT;
evt_data.evt_data = data_network_stats;
break;
+
#ifdef FEATURE_IPACM_HAL
case IPA_QUOTA_REACH:
IPACMDBG_H("Received IPA_QUOTA_REACH\n");
@@ -706,6 +709,55 @@
}
break;
#endif
+#ifdef FEATURE_L2TP
+ case ADD_VLAN_IFACE:
+ vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info));
+ if(vlan_info == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return NULL;
+ }
+ memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info));
+ evt_data.event = IPA_ADD_VLAN_IFACE;
+ evt_data.evt_data = vlan_info;
+ break;
+
+ case DEL_VLAN_IFACE:
+ vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info));
+ if(vlan_info == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return NULL;
+ }
+ memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info));
+ evt_data.event = IPA_DEL_VLAN_IFACE;
+ evt_data.evt_data = vlan_info;
+ break;
+
+ case ADD_L2TP_VLAN_MAPPING:
+ mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping));
+ if(mapping == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return NULL;
+ }
+ memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping));
+ evt_data.event = IPA_ADD_L2TP_VLAN_MAPPING;
+ evt_data.evt_data = mapping;
+ break;
+
+ case DEL_L2TP_VLAN_MAPPING:
+ mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping));
+ if(mapping == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return NULL;
+ }
+ memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping));
+ evt_data.event = IPA_DEL_L2TP_VLAN_MAPPING;
+ evt_data.evt_data = mapping;
+ break;
+#endif
default:
IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type);
continue;
@@ -782,7 +834,7 @@
#endif
#ifdef FEATURE_ETH_BRIDGE_LE
- IPACM_LanToLan* lan2lan = new IPACM_LanToLan();
+ IPACM_LanToLan* lan2lan = IPACM_LanToLan::get_instance();
#endif
CtList = new IPACM_ConntrackListener();
diff --git a/ipacm/src/IPACM_Neighbor.cpp b/ipacm/src/IPACM_Neighbor.cpp
index 7f73bbd..8d5a16f 100644
--- a/ipacm/src/IPACM_Neighbor.cpp
+++ b/ipacm/src/IPACM_Neighbor.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -133,6 +133,10 @@
memcpy(data_all->mac_addr,
neighbor_client[i].mac_addr,
sizeof(data_all->mac_addr));
+#ifdef FEATURE_L2TP
+ memcpy(data_all->iface_name, neighbor_client[i].iface_name,
+ sizeof(data_all->iface_name));
+#endif
evt_data.evt_data = (void *)data_all;
IPACM_EvtDispatcher::PostEvt(&evt_data);
/* ask for replaced iface name*/
@@ -143,7 +147,7 @@
} else {
IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n",
evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+ data_all->iface_name);
}
}
}
@@ -166,11 +170,13 @@
ipacm_event_data_all *data = (ipacm_event_data_all *)param;
ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
+#ifndef FEATURE_L2TP
/* check for failure return */
if (IPACM_FAILURE == ipa_interface_index) {
IPACMERR("not supported iface id: %d\n", data->if_index);
break;
}
+#endif
if (data->iptype == IPA_IP_v4)
{
if (data->ipv4_addr != 0) /* not 0.0.0.0 */
@@ -183,7 +189,7 @@
return;
}
/* check if iface is bridge interface*/
- if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0)
+ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0)
{
/* searh if seen this client or not*/
for (i = 0; i < num_neighbor_client_temp; i++)
@@ -191,6 +197,7 @@
if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
{
data->if_index = neighbor_client[i].iface_index;
+ strlcpy(data->iface_name, neighbor_client[i].iface_name, sizeof(data->iface_name));
neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
if (event == IPA_NEW_NEIGH_EVENT)
@@ -217,7 +224,7 @@
IPACMDBG_H("Posted event %d,\
with %s for ipv4\n",
evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+ data->iface_name);
}
break;
}
@@ -240,10 +247,9 @@
neighbor_client[i].iface_index = data->if_index;
neighbor_client[i].ipa_if_num = ipa_interface_index;
neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
+ strlcpy(neighbor_client[i].iface_name, data->iface_name, sizeof(neighbor_client[i].iface_name));
IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n",
- i,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,
- data->ipv4_addr);
+ i, data->iface_name, data->ipv4_addr);
break;
}
}
@@ -259,6 +265,8 @@
/* cache the network interface client associated */
neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index;
neighbor_client[num_neighbor_client_temp].v4_addr = data->ipv4_addr;
+ strlcpy(neighbor_client[num_neighbor_client_temp].iface_name,
+ data->iface_name, sizeof(neighbor_client[num_neighbor_client_temp].iface_name));
num_neighbor_client++;
IPACMDBG_H("Cache client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
neighbor_client[num_neighbor_client_temp].mac_addr[0],
@@ -280,6 +288,8 @@
/* cache the network interface client associated */
neighbor_client[circular_index].ipa_if_num = ipa_interface_index;
neighbor_client[circular_index].v4_addr = 0;
+ strlcpy(neighbor_client[circular_index].iface_name,
+ data->iface_name, sizeof(neighbor_client[circular_index].iface_name));
IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n",
neighbor_client[circular_index].mac_addr[0],
neighbor_client[circular_index].mac_addr[1],
@@ -316,6 +326,7 @@
neighbor_client[i].iface_index = 0;
neighbor_client[i].v4_addr = 0;
neighbor_client[i].ipa_if_num = 0;
+ memset(neighbor_client[i].iface_name, 0, sizeof(neighbor_client[i].iface_name));
for (; i < num_neighbor_client_temp - 1; i++)
{
memcpy(neighbor_client[i].mac_addr,
@@ -324,6 +335,8 @@
neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
+ strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name,
+ sizeof(neighbor_client[i].iface_name));
}
num_neighbor_client--;
IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client);
@@ -343,8 +356,7 @@
evt_data.evt_data = (void *)data_all;
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG_H("Posted event %d with %s for ipv4\n",
- evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+ evt_data.event, data->iface_name);
}
}
}
@@ -355,7 +367,7 @@
{
IPACMDBG("Got New_Neighbor event with ipv6 address \n");
/* check if iface is bridge interface*/
- if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0)
+ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0)
{
/* searh if seen this client or not*/
for (i = 0; i < num_neighbor_client_temp; i++)
@@ -363,6 +375,7 @@
if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
{
data->if_index = neighbor_client[i].iface_index;
+ strlcpy(data->iface_name, neighbor_client[i].iface_name, sizeof(data->iface_name));
/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
@@ -384,7 +397,7 @@
IPACMDBG_H("Posted event %d,\
with %s for ipv6\n",
evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+ data->iface_name);
}
break;
};
@@ -407,8 +420,7 @@
evt_data.evt_data = (void *)data_all;
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG_H("Posted event %d with %s for ipv6\n",
- evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+ evt_data.event, data->iface_name);
}
}
else
@@ -430,13 +442,14 @@
neighbor_client[i].mac_addr[5],
num_neighbor_client);
/* check if iface is not bridge interface*/
- if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
+ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) != 0)
{
/* use previous ipv4 first */
if(data->if_index != neighbor_client[i].iface_index)
{
IPACMDBG_H("update new kernel iface index \n");
neighbor_client[i].iface_index = data->if_index;
+ strlcpy(neighbor_client[i].iface_name, data->iface_name, sizeof(neighbor_client[i].iface_name));
}
/* check if client associated with previous network interface */
@@ -461,22 +474,13 @@
data_all->iptype = IPA_IP_v4;
data_all->if_index = neighbor_client[i].iface_index;
data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address
- memcpy(data_all->mac_addr,
- neighbor_client[i].mac_addr,
- sizeof(data_all->mac_addr));
+ memcpy(data_all->mac_addr, neighbor_client[i].mac_addr,
+ sizeof(data_all->mac_addr));
+ strlcpy(data_all->iface_name, neighbor_client[i].iface_name, sizeof(data_all->iface_name));
evt_data.evt_data = (void *)data_all;
IPACM_EvtDispatcher::PostEvt(&evt_data);
- /* ask for replaced iface name*/
- ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
- /* check for failure return */
- if (IPACM_FAILURE == ipa_interface_index) {
- IPACMERR("not supported iface id: %d\n", data_all->if_index);
- } else {
- IPACMDBG_H("Posted event %d,\
- with %s for ipv4 client re-connect\n",
- evt_data.event,
- IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
- }
+ IPACMDBG_H("Posted event %d with %s for ipv4\n",
+ evt_data.event, data_all->iface_name);
}
}
/* delete cache neighbor entry */
@@ -496,6 +500,7 @@
neighbor_client[i].iface_index = 0;
neighbor_client[i].v4_addr = 0;
neighbor_client[i].ipa_if_num = 0;
+ memset(neighbor_client[i].iface_name, 0, sizeof(neighbor_client[i].iface_name));
for (; i < num_neighbor_client_temp - 1; i++)
{
memcpy(neighbor_client[i].mac_addr,
@@ -504,6 +509,8 @@
neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
+ strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name,
+ sizeof(neighbor_client[i].iface_name));
}
num_neighbor_client--;
IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client);
@@ -515,7 +522,7 @@
if ((i == num_neighbor_client_temp) && (event == IPA_NEW_NEIGH_EVENT))
{
/* check if iface is not bridge interface*/
- if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
+ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) != 0)
{
if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS)
{
@@ -526,6 +533,8 @@
/* cache the network interface client associated */
neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index;
neighbor_client[num_neighbor_client_temp].v4_addr = 0;
+ strlcpy(neighbor_client[num_neighbor_client_temp].iface_name, data->iface_name,
+ sizeof(neighbor_client[num_neighbor_client_temp].iface_name));
num_neighbor_client++;
IPACMDBG_H("Copy client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
neighbor_client[num_neighbor_client_temp].mac_addr[0],
@@ -547,6 +556,8 @@
/* cache the network interface client associated */
neighbor_client[circular_index].ipa_if_num = ipa_interface_index;
neighbor_client[circular_index].v4_addr = 0;
+ strlcpy(neighbor_client[circular_index].iface_name, data->iface_name,
+ sizeof(neighbor_client[circular_index].iface_name));
IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n",
neighbor_client[circular_index].mac_addr[0],
neighbor_client[circular_index].mac_addr[1],
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index 186e196..b5fadcb 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -849,6 +849,9 @@
evt_data.event = IPA_ADDR_ADD_EVENT;
data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index;
+#ifdef FEATURE_L2TP
+ strlcpy(data_addr->iface_name, dev_name, sizeof(data_addr->iface_name));
+#endif
if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family)
{
IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
@@ -1421,6 +1424,9 @@
msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data,
sizeof(data_all->mac_addr));
data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
+#ifdef FEATURE_L2TP
+ strlcpy(data_all->iface_name, dev_name, sizeof(data_all->iface_name));
+#endif
/* Add support to replace src-mac as bridge0 mac */
if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) &&
(msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT))
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index b47c5ef..54a2e66 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2017, 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
@@ -683,7 +683,7 @@
{
if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR)
{
- eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr, NULL, NULL);
break;
}
}
@@ -700,7 +700,7 @@
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG_H("Received IPA_WLAN_CLIENT_DEL_EVENT\n");
- eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, NULL);
handle_wlan_client_down_evt(data->mac_addr);
}
}
@@ -802,7 +802,7 @@
{
handle_SCC_MCC_switch(ip_type);
}
- eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL);
break;
case IPA_WLAN_SWITCH_TO_MCC:
@@ -816,7 +816,7 @@
{
handle_SCC_MCC_switch(ip_type);
}
- eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL);
break;
case IPA_CRADLE_WAN_MODE_SWITCH:
@@ -1804,7 +1804,7 @@
}
IPACMDBG_H("finished deleting default RT rules\n ");
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
/* free the wlan clients cache */
IPACMDBG_H("Free wlan clients cache\n");
@@ -2163,23 +2163,23 @@
/* ====== post events to mimic WLAN interface goes down/up when AP mode is changing ====== */
/* first post IFACE_DOWN event */
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
/* then post IFACE_UP event */
if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
{
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL);
}
if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
{
- eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL);
+ eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL);
}
/* at last post CLIENT_ADD event */
for(i = 0; i < num_wifi_client; i++)
{
eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX,
- get_client_memptr(wlan_client, i)->mac);
+ get_client_memptr(wlan_client, i)->mac, NULL, NULL);
}
return;
diff --git a/ipacm/src/Makefile.am b/ipacm/src/Makefile.am
index 7a62a75..92ea904 100644
--- a/ipacm/src/Makefile.am
+++ b/ipacm/src/Makefile.am
@@ -2,7 +2,7 @@
-I$(top_srcdir)/ipanat/inc \
${LIBXML_CFLAGS}
AM_CPPFLAGS += -Wall -Wundef -Wno-trigraphs
-AM_CPPFLAGS += -DDEBUG -g -DFEATURE_ETH_BRIDGE_LE
+AM_CPPFLAGS += -DDEBUG -g -DFEATURE_ETH_BRIDGE_LE -DFEATURE_L2TP
AM_CPPFLAGS += -DFEATURE_IPA_V3
ipacm_SOURCES = IPACM_Main.cpp \