Merge "IPACM: change src mac to bridge0"
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 54a4423..665b844 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -126,6 +126,12 @@
 	/* Store SW-enable or not */
 	bool ipa_sw_rt_enable;
 
+	/* Store bridge mode or not */
+	bool ipa_bridge_enable;
+
+	/* Store bridge netdev mac */
+	uint8_t bridge_mac[IPA_MAC_ADDR_SIZE];
+
 	/* Store the flt rule count for each producer client*/
 	int flt_rule_count_v4[IPA_CLIENT_CONS - IPA_CLIENT_PROD];
 	int flt_rule_count_v6[IPA_CLIENT_CONS - IPA_CLIENT_PROD];
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index f0eff09..677b122 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -195,6 +195,7 @@
 	IPA_HANDLE_WAN_DOWN_TETHER,               /* 57 ipacm_event_iface_up_tehter */
 	IPA_HANDLE_WAN_UP_V6_TETHER,		  /* 58 ipacm_event_iface_up_tehter */
 	IPA_HANDLE_WAN_DOWN_V6_TETHER,		  /* 59 ipacm_event_iface_up_tehter */
+	IPA_BRIDGE_LINK_UP_EVENT,                 /* 60 ipacm_event_data_all */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
 
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index f7d764a..c718603 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -64,6 +64,7 @@
 	ipa_nat_max_entries = 0;
 	ipa_nat_iface_entries = 0;
 	ipa_sw_rt_enable = false;
+	ipa_bridge_enable = false;
 	isMCC_Mode = false;
 	ipa_max_valid_rm_entry = 0;
 
@@ -88,6 +89,7 @@
 
 	memset(flt_rule_count_v4, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int));
 	memset(flt_rule_count_v6, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int));
+	memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t));
 
 	IPACMDBG_H(" create IPACM_Config constructor\n");
 	return;
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 3024ce6..59884ab 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -58,8 +58,10 @@
 	IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this);  // register for wlan AP-iface
 #ifndef FEATURE_IPA_ANDROID
 	IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface
+	/* only MDM targets support device on bridge mode */
+	IPACM_EvtDispatcher::registr(IPA_BRIDGE_LINK_UP_EVENT, this); 	// register for IPA_BRIDGE_LINK_UP_EVENT event
 #endif /* not defined(FEATURE_IPA_ANDROID)*/
-	IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for wlan STA-iface
+	IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for USB-iface
 	IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this);  // register for wan eMBMS-iface
 	return;
 }
@@ -69,6 +71,7 @@
 	int ipa_interface_index;
 	ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param;
 	ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param;
+	ipacm_event_data_all *data_all = (ipacm_event_data_all *)param;
 	ipacm_ifacemgr_data ifmgr_data = {0};
 
 	switch(event)
@@ -77,6 +80,21 @@
 				IPACMDBG_H(" RESET IPACM_cfg \n");
 				IPACM_Iface::ipacmcfg->Init();
 			break;
+		case IPA_BRIDGE_LINK_UP_EVENT:
+			IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n");
+			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
+			/* 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)
+			{
+				IPACM_Iface::ipacmcfg->ipa_bridge_enable = true;
+				memcpy(IPACM_Iface::ipacmcfg->bridge_mac,
+								data_all->mac_addr,
+								sizeof(IPACM_Iface::ipacmcfg->bridge_mac));
+				IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+						 IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2],
+						 IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]);
+			}
+			break;
 		case IPA_LINK_UP_EVENT:
 			IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index);
 			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index);
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index b69ebec..0878d29 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1849,6 +1849,14 @@
 											 mac_addr,
 											 IPA_MAC_ADDR_SIZE);
 								}
+								/* replace src mac to bridge mac_addr if any  */
+								if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+								{
+									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+											IPACM_Iface::ipacmcfg->bridge_mac,
+											IPA_MAC_ADDR_SIZE);
+									IPACMDBG_H("device is in bridge mode \n");
+								}
 
 								pHeaderDescriptor->commit = true;
 								pHeaderDescriptor->num_hdrs = 1;
@@ -1941,6 +1949,15 @@
 						mac_addr,
 						IPA_MAC_ADDR_SIZE);
 				}
+				/* replace src mac to bridge mac_addr if any  */
+				if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+				{
+					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+							IPACM_Iface::ipacmcfg->bridge_mac,
+							IPA_MAC_ADDR_SIZE);
+					IPACMDBG_H("device is in bridge mode \n");
+				}
+
 				pHeaderDescriptor->commit = true;
 				pHeaderDescriptor->num_hdrs = 1;
 
@@ -2360,7 +2377,14 @@
 											 mac_addr,
 											 IPA_MAC_ADDR_SIZE);
 								}
-
+								/* replace src mac to bridge mac_addr if any  */
+								if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+								{
+									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+											IPACM_Iface::ipacmcfg->bridge_mac,
+											IPA_MAC_ADDR_SIZE);
+									IPACMDBG_H("device is in bridge mode \n");
+								}
 
 								pHeaderDescriptor->commit = true;
 								pHeaderDescriptor->num_hdrs = 1;
@@ -2432,6 +2456,14 @@
 					 mac_addr,
 					 IPA_MAC_ADDR_SIZE);
 				}
+				/* replace src mac to bridge mac_addr if any  */
+				if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+				{
+					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+							IPACM_Iface::ipacmcfg->bridge_mac,
+							IPA_MAC_ADDR_SIZE);
+					IPACMDBG_H("device is in bridge mode \n");
+				}
 
 				pHeaderDescriptor->commit = true;
 				pHeaderDescriptor->num_hdrs = 1;
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index a343e24..30295b1 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -1376,13 +1376,13 @@
 				IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
 			}
 
-					/* insert to command queue */
+			/* insert to command queue */
 		    data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
 		    if(data_all == NULL)
-					{
+			{
 		    	IPACMERR("unable to allocate memory for event data_all\n");
 						return IPACM_FAILURE;
-					}
+			}
 
 		    memset(data_all, 0, sizeof(ipacm_event_data_all));
 		    if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6)
@@ -1390,11 +1390,11 @@
 				IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
 				IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
 
-                      data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]);
-                      data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]);
-                      data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]);
-                      data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]);
-		    	data_all->iptype = IPA_IP_v6;
+				data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]);
+				data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]);
+				data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]);
+				data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]);
+				data_all->iptype = IPA_IP_v6;
 		    }
 		    else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET)
 		    {
@@ -1420,13 +1420,26 @@
 		    memcpy(data_all->mac_addr,
 		    			 msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data,
 		    			 sizeof(data_all->mac_addr));
-		    evt_data.event = IPA_NEW_NEIGH_EVENT;
-		    data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
-
-		    IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
+			data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
+			/* 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))
+		    {
+				/* Posting IPA_BRIDGE_LINK_UP_EVENT event */
+				evt_data.event = IPA_BRIDGE_LINK_UP_EVENT;
+				IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n",
+                                 dev_name,
+ 		                    data_all->if_index);
+			}
+			else
+		    {
+				/* Posting new_neigh events for all LAN/WAN clients */
+				evt_data.event = IPA_NEW_NEIGH_EVENT;
+				IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
                                  dev_name,
  		                    data_all->if_index,
 		    				 msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
+			}
 		    evt_data.evt_data = data_all;
 					IPACM_EvtDispatcher::PostEvt(&evt_data);
 					/* finish command queue */
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index e8dccdf..bb70724 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1784,6 +1784,15 @@
 						memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset],
 									 get_client_memptr(wlan_client, num_wifi_client)->mac,
 									 IPA_MAC_ADDR_SIZE);
+						/* replace src mac to bridge mac_addr if any  */
+						if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+						{
+							memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE],
+									 IPACM_Iface::ipacmcfg->bridge_mac,
+									 IPA_MAC_ADDR_SIZE);
+							IPACMDBG_H("device is in bridge mode \n");
+						}
+
 					}
 					else if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID)
 					{
@@ -1890,6 +1899,15 @@
 						memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset],
 								get_client_memptr(wlan_client, num_wifi_client)->mac,
 								IPA_MAC_ADDR_SIZE);
+
+						/* replace src mac to bridge mac_addr if any  */
+						if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+						{
+							memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE],
+									 IPACM_Iface::ipacmcfg->bridge_mac,
+									 IPA_MAC_ADDR_SIZE);
+							IPACMDBG_H("device is in bridge mode \n");
+						}
 					}
 					else if (data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID)
 					{