IPACM: move NAT table on request from modem

On request from modem move NAT table to DDR only
or back to hybrid mode. send QMI indication when
transition has finished.

Change-Id: Ib2c0529a477d97155fc011f3618d3857832090c2
diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h
index 2977af7..217761b 100644
--- a/ipacm/inc/IPACM_ConntrackListener.h
+++ b/ipacm/inc/IPACM_ConntrackListener.h
@@ -103,6 +103,7 @@
 	void CheckSTAClient(const nat_table_entry *, bool *);
 	int CheckNatIface(ipacm_event_data_all *, bool *);
 	void HandleNonNatIPAddr(void *, bool);
+	void HandleNatTableMove(void *in_param);
 
 #ifdef CT_OPT
 	void ProcessCTV6Message(void *);
diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h
index 95dcdfe..9490aa6 100644
--- a/ipacm/inc/IPACM_Conntrack_NATApp.h
+++ b/ipacm/inc/IPACM_Conntrack_NATApp.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -119,6 +119,7 @@
 	int AddTable(uint32_t, uint8_t mux_id);
 	uint32_t GetTableHdl(uint32_t);
 	int DeleteTable(uint32_t);
+	int MoveTable(bool to_ddr);
 
 	int AddEntry(const nat_table_entry *);
 	int DeleteEntry(const nat_table_entry *);
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 1c41dfa..0d2a257 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -44,6 +44,7 @@
 #include <fcntl.h>
 #include <linux/msm_ipa.h>
 #include "IPACM_Log.h"
+#include "linux/ipa_qmi_service_v01.h"
 
 #ifdef USE_GLIB
 #include <glib.h>
@@ -213,6 +214,7 @@
 	IPA_LAN_DELETE_SELF,                      /* ipacm_event_data_fid */
 	IPA_WIGIG_CLIENT_ADD_EVENT,               /* ipacm_event_data_mac_ep */
 	IPA_WIGIG_FST_SWITCH,                     /* ipacm_event_data_fst */
+	IPA_MOVE_NAT_TBL_EVENT,                   /* ipacm_event_move_nat */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
 
@@ -394,6 +396,10 @@
 	uint8_t xlat_mux_id;
 }ipacm_event_iface_up_tehter;
 
+typedef struct
+{
+	ipa_move_nat_type_enum_v01 nat_move_direction;
+}ipacm_event_move_nat;
 
 typedef struct _ipacm_ifacemgr_data
 {
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 369c7d4..41b920d 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -125,7 +125,8 @@
 	__stringify(IPA_LAN_DELETE_SELF),                      /* ipacm_event_data_fid */
 	__stringify(IPA_WIGIG_CLIENT_ADD_EVENT),               /* ipacm_event_data_mac_ep */
 	__stringify(IPA_WIGIG_FST_SWITCH),                     /* ipacm_event_data_fst */
-	__stringify(IPACM_EVENT_MAX),
+	__stringify(IPA_MOVE_NAT_TBL_EVENT),                   /* ipacm_event_move_nat */
+	__stringify(IPACM_EVENT_MAX)
 };
 
 IPACM_Config::IPACM_Config()
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index b991324..f0abb84 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -65,6 +65,7 @@
 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
+	 IPACM_EvtDispatcher::registr(IPA_MOVE_NAT_TBL_EVENT, this);
 
 #ifdef CT_OPT
 	 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
@@ -144,7 +145,10 @@
 		 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
 		 HandleNonNatIPAddr(data, false);
 		 break;
-
+	 case IPA_MOVE_NAT_TBL_EVENT:
+		 IPACMDBG_H("Received IPA_MOVE_NAT_TBL_EVENT event\n");
+		 HandleNatTableMove(data);
+		 break;
 	 default:
 			IPACMDBG("Ignore cmd %d\n", evt);
 			break;
@@ -1501,3 +1505,37 @@
 	IPACMDBG("Exit:\n");
 }
 
+void IPACM_ConntrackListener::HandleNatTableMove(void *in_param)
+{
+	int ret;
+	int fd_wwan_ioctl;
+	ipacm_event_move_nat *data_nat = (ipacm_event_move_nat *)in_param;
+
+	IPACMDBG_H("handling nat table move request\n");
+
+	fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
+	if(fd_wwan_ioctl < 0)
+	{
+		IPACMERR("Failed to open %s.\n", WWAN_QMI_IOCTL_DEVICE_NAME);
+		return;
+	}
+
+	if(data_nat->nat_move_direction == QMI_IPA_MOVE_NAT_TO_DDR_V01) {
+		ret = nat_inst->MoveTable(true);
+	}
+	else {
+		ret = nat_inst->MoveTable(false);
+	}
+
+	IPACMDBG_H("sending indication to Q6 about transition %s\n",
+		ret ? "failure" : "success");
+
+	ret = ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_NAT_MOVE_RES, ret);
+	if(ret != 0)
+	{
+		IPACMERR("Failed sending NAT TABLR MOVE indication with ret %d\n ", ret);
+	}
+
+	close(fd_wwan_ioctl);
+}
+
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index 111733a..5b72cba 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -318,6 +318,21 @@
 	return 0;
 }
 
+int NatApp::MoveTable(bool to_ddr)
+{
+	int ret;
+
+	if (to_ddr) {
+		IPACMDBG_H("direction TO_DDR - move and lock table at DDR\n");
+		ret = ipa_nat_switch_to(IPA_NAT_MEM_IN_DDR, true);
+	} else {
+		IPACMDBG_H("direction TO_SRAM - allow table transition to SRAM\n");
+		ret = ipa_nat_switch_to(IPA_NAT_MEM_IN_DDR, false);
+	}
+
+	return ret;
+}
+
 /* Check for duplicate entries */
 bool NatApp::ChkForDup(const nat_table_entry *rule)
 {
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 8166329..2e41389 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -305,6 +305,9 @@
 #endif
 
 	param = NULL;
+	struct ipa_move_nat_req_msg_v01 *move_nat;
+	ipacm_event_move_nat *move_nat_data;
+
 	fd = open(IPA_DRIVER, O_RDWR);
 	if (fd < 0)
 	{
@@ -945,6 +948,23 @@
 			break;
 #endif
 
+		case IPA_MOVE_NAT_TABLE:
+			move_nat = (struct ipa_move_nat_req_msg_v01 *)(buffer + sizeof(struct ipa_msg_meta));
+			IPACMDBG_H("received IPA_MOVE_NAT_TABLE direction %s\n",
+				move_nat->nat_move_direction == QMI_IPA_MOVE_NAT_TO_DDR_V01 ? "TO_DDR" : "TO_SRAM");
+			move_nat_data = (ipacm_event_move_nat *)malloc(sizeof(ipacm_event_move_nat));
+			if(move_nat_data == NULL)
+			{
+				IPACMERR("unable to allocate memory for move_nat_tbl_evnt\n");
+				return NULL;
+			}
+
+			move_nat_data->nat_move_direction = move_nat->nat_move_direction;
+
+			evt_data.event = IPA_MOVE_NAT_TBL_EVENT;
+			evt_data.evt_data = move_nat_data;
+			break;
+
 		default:
 			IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type);
 			continue;