IPACM: Use Metadata replacement feature

Enable Metadata replacement bit in modem uplink filtering rules.
NAT block will replace the metadata of the packets to metadata
that contains the appropriate MUX ID according to the PDN being used.
This Mechanism overrides the MUX ID which is set with
IPA_IOC_WRITE_QMAPID.

Change-Id: If67f21d3e8cc51a7ff11b9e4192e522d2a16c90d
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 926ed5e..a9524f6 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -252,7 +252,7 @@
 
 	int DelExtProp(ipa_ip_type ip_type);
 
-	enum ipa_hw_type GetIPAVer();
+	enum ipa_hw_type GetIPAVer(bool get = false);
 
 	int Init(void);
 
diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h
index e50b316..c3749e1 100644
--- a/ipacm/inc/IPACM_Conntrack_NATApp.h
+++ b/ipacm/inc/IPACM_Conntrack_NATApp.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
@@ -102,11 +102,12 @@
 	bool isAlgPort(uint8_t, uint16_t);
 	void Reset();
 	bool isPwrSaveIf(uint32_t);
+	uint32_t GenerateMetdata(uint8_t mux_id);
 
 public:
 	static NatApp* GetInstance();
 
-	int AddTable(uint32_t);
+	int AddTable(uint32_t, uint8_t mux_id);
 	uint32_t GetTableHdl(uint32_t);
 	int DeleteTable(uint32_t);
 
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index fe252c9..2031fc5 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -341,6 +341,7 @@
 	uint32_t ipv6_prefix[2];
 	bool is_sta;
 	uint8_t xlat_mux_id;
+	uint8_t mux_id;
 }ipacm_event_iface_up;
 
 typedef struct _ipacm_event_iface_up_tether
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 7e747f0..92f4880 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -157,7 +157,7 @@
 	memset(flt_rule_count_v4, 0, IPA_CLIENT_MAX*sizeof(int));
 	memset(flt_rule_count_v6, 0, IPA_CLIENT_MAX*sizeof(int));
 	memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t));
-	ver = IPA_HW_None;
+	ver = GetIPAVer(true);
 
 	IPACMDBG_H(" create IPACM_Config constructor\n");
 	return;
@@ -849,17 +849,18 @@
 	return ipacm_event_name[event_id];
 }
 
-enum ipa_hw_type IPACM_Config::GetIPAVer()
+enum ipa_hw_type IPACM_Config::GetIPAVer(bool get)
 {
 	int ret;
 
-	if(ver != IPA_HW_None)
+	if(!get)
 		return ver;
 
 	ret = ioctl(m_fd, IPA_IOC_GET_HW_VERSION, &ver);
 	if(ret != 0)
 	{
 		IPACMERR("Failed to get IPA version with error %d.\n", ret);
+		ver = IPA_HW_None;
 		return IPA_HW_None;
 	}
 	IPACMDBG_H("IPA version is %d.\n", ver);
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index 4f83b3d..e02ca10 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.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
@@ -373,7 +373,7 @@
 
 	 if(nat_inst != NULL)
 	 {
-		 nat_inst->AddTable(wanup_data->ipv4_addr);
+		 nat_inst->AddTable(wanup_data->ipv4_addr, wanup_data->mux_id);
 	 }
 
 	 IPACMDBG("creating nat threads\n");
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index c13c48e..27bf95a 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.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
@@ -31,9 +31,13 @@
 #ifdef FEATURE_IPACM_HAL
 #include "IPACM_OffloadManager.h"
 #endif
+#include "IPACM_Iface.h"
 
 #define INVALID_IP_ADDR 0x0
 
+#define HDR_METADATA_MUX_ID_BMASK 0x00FF0000
+#define HDR_METADATA_MUX_ID_SHFT 0x10
+
 /* NatApp class Implementation */
 NatApp *NatApp::pInstance = NULL;
 NatApp::NatApp()
@@ -127,9 +131,14 @@
 	return pInstance;
 }
 
+uint32_t NatApp::GenerateMetdata(uint8_t mux_id)
+{
+	return (mux_id << HDR_METADATA_MUX_ID_SHFT) & HDR_METADATA_MUX_ID_BMASK;
+}
+
 /* NAT APP related object function definitions */
 
-int NatApp::AddTable(uint32_t pub_ip)
+int NatApp::AddTable(uint32_t pub_ip, uint8_t mux_id)
 {
 	int ret;
 	int cnt = 0;
@@ -151,6 +160,19 @@
 		IPACMERR("unable to create nat table Error:%d\n", ret);
 		return ret;
 	}
+	if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_v4_0) {
+		/* modify PDN 0 so it will hold the mux ID in the src metadata field */
+		ipa_nat_pdn_entry entry;
+
+		entry.dst_metadata = 0;
+		entry.src_metadata = GenerateMetdata(mux_id);
+		entry.public_ip = pub_ip;
+		ret = ipa_nat_modify_pdn(nat_table_hdl, 0, &entry);
+		if(ret)
+		{
+			IPACMERR("unable to modify PDN 0 entry Error:%d INIT_HDR_METADATA register values will be used!\n", ret);
+		}
+	}
 
 	/* Add back the cached NAT-entry */
 	if (pub_ip == pub_ip_addr_pre)
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index d574616..2f18f38 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1687,9 +1687,10 @@
 	IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg;
 	struct ipa_ioc_write_qmapid mux;
 
-	if(rx_prop != NULL)
+	/* not  needed for newer versions since it will be overridden by NAT metadata replacement for IPAv4 and up */
+	if((IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0) && (rx_prop != NULL))
 	{
-		/* give mud ID to IPA-driver for WLAN/LAN pkts */
+		/* give mux ID of the default PDN to IPA-driver for WLAN/LAN pkts */
 		fd = open(IPA_DEVICE_NAME, O_RDWR);
 		if (0 == fd)
 		{
@@ -3197,6 +3198,10 @@
 		else
 		{
 			flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT;
+
+			/* NAT block will set the proper MUX ID in the metadata according to the relevant PDN */
+			if (IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_v4_0)
+				flt_rule_entry.rule.set_metadata = true;
 		}
 	}
 	else if(iptype == IPA_IP_v6)
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 79f88cd..6d57c39 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.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
@@ -1604,6 +1604,7 @@
 		{
 			IPACM_Wan::xlat_mux_id = 0;
 			wanup_data->xlat_mux_id = 0;
+			wanup_data->mux_id = ext_prop->ext[0].mux_id;
 			IPACMDBG_H("No xlat configuratio:\n");
 		}
 		evt_data.event = IPA_HANDLE_WAN_UP;