ipacm: Handle WLAN FW rejuvenate events

Handle WLAN FW SSR event for FW rejuvenate
scenario.

Change-Id: Ieceaf20a05dd645e56e3fb3b87ffd7cb97453cb0
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 149c03a..051184d 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2018, 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
@@ -195,6 +195,7 @@
 	IPA_HANDLE_VLAN_CLIENT_INFO,              /* ipacm_event_data_all */
 	IPA_HANDLE_VLAN_IFACE_INFO,               /* ipacm_event_data_all */
 #endif
+	IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE,
 	IPA_LAN_DELETE_SELF,                      /* ipacm_event_data_fid */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
diff --git a/ipacm/inc/IPACM_OffloadManager.h b/ipacm/inc/IPACM_OffloadManager.h
index 4947a83..e5ab22f 100644
--- a/ipacm/inc/IPACM_OffloadManager.h
+++ b/ipacm/inc/IPACM_OffloadManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -94,6 +94,8 @@
 
 	bool search_framwork_cache(char * interface_name);
 
+	bool push_framework_event(const char * if_name, _ipacm_offload_prefix prefix);
+
 private:
 
 	std::list<std::string> valid_ifaces;
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index ad0cdd3..90d3647 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -106,6 +106,7 @@
 	__stringify(IPA_ETH_BRIDGE_CLIENT_ADD),                /* ipacm_event_eth_bridge*/
 	__stringify(IPA_ETH_BRIDGE_CLIENT_DEL),                /* ipacm_event_eth_bridge*/
 	__stringify(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH),       /* ipacm_event_eth_bridge*/
+	__stringify(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE),       /* ipacm_event_iface*/
 	__stringify(IPA_LAN_DELETE_SELF),                      /* ipacm_event_data_fid */
 #ifdef FEATURE_L2TP
 	__stringify(IPA_ADD_VLAN_IFACE),                       /* ipa_ioc_vlan_iface_info */
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index e7660b1..248bb78 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -417,6 +417,9 @@
 #else
 				IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, wl);
 #endif
+#ifdef FEATURE_IPACM_HAL
+				IPACM_EvtDispatcher::registr(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE, wl);
+#endif
 				/* IPA_LAN_DELETE_SELF should be always last */
 				IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl);
 				IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance open/registr ok\n", wl->dev_name, wl->ipa_if_num);
@@ -474,6 +477,7 @@
 						IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, w);
 #ifdef FEATURE_IPACM_HAL
 						IPACM_EvtDispatcher::registr(IPA_SSR_NOTICE, w);
+						IPACM_EvtDispatcher::registr(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE, w);
 #endif
 #endif
 					}
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 34b2dda..1292d04 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2018, 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
@@ -730,6 +730,13 @@
 				OffloadMng->elrInstance->onOffloadSupportAvailable();
 			}
 			continue;
+#ifdef IPA_WLAN_FW_SSR_EVENT_MAX
+		case WLAN_FWR_SSR_BEFORE_SHUTDOWN:
+                        IPACMDBG_H("Received WLAN_FWR_SSR_BEFORE_SHUTDOWN\n");
+                        evt_data.event = IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE;
+                        evt_data.evt_data = NULL;
+                        break;
+#endif
 #endif
 #ifdef FEATURE_L2TP
 		case ADD_VLAN_IFACE:
@@ -1073,4 +1080,4 @@
 	IPACMDBG_H("send IPA_IOC_CLEANUP \n");
 	close(fd);
 	return IPACM_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/ipacm/src/IPACM_OffloadManager.cpp b/ipacm/src/IPACM_OffloadManager.cpp
index 88e3761..d9a9f4b 100644
--- a/ipacm/src/IPACM_OffloadManager.cpp
+++ b/ipacm/src/IPACM_OffloadManager.cpp
@@ -366,16 +366,16 @@
 	if(upstream_name == NULL)
 	{
 		if (default_gw_index == INVALID_IFACE) {
+			result = FAIL_INPUT_CHECK;
 			for (index = 0; index < MAX_EVENT_CACHE; index++) {
 				if (event_cache[index].valid == true &&
 					event_cache[index ].event == IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT) {
 					event_cache[index].valid = false;
-					memset(event_cache, 0, MAX_EVENT_CACHE*sizeof(framework_event_cache));
-					return SUCCESS;
+					result = SUCCESS;
 				}
 			}
 			IPACMERR("no previous upstream set before\n");
-			return FAIL_INPUT_CHECK;
+			return result;
 		}
 		if (gw_addr_v4.fam == V4 && upstream_v4_up == true) {
 			IPACMDBG_H("clean upstream for ipv4-fam(%d) upstream_v4_up(%d)\n", gw_addr_v4.fam, upstream_v4_up);
@@ -876,3 +876,54 @@
 	return IPACM_SUCCESS;
 }
 
+bool IPACM_OffloadManager::push_framework_event(const char * if_name, _ipacm_offload_prefix prefix)
+{
+	bool ret =  false;
+
+	for(int i = 0; i < MAX_EVENT_CACHE ;i++)
+	{
+		if(event_cache[latest_cache_index].valid == false)
+		{
+			//do the copy
+			event_cache[latest_cache_index].valid = true;
+			event_cache[latest_cache_index].event = IPA_DOWNSTREAM_ADD;
+			memcpy(event_cache[latest_cache_index].dev_name, if_name,
+				sizeof(event_cache[latest_cache_index].dev_name));
+			memcpy(&event_cache[latest_cache_index].prefix_cache, &prefix,
+				sizeof(event_cache[latest_cache_index].prefix_cache));
+
+			if (prefix.iptype == IPA_IP_v4) {
+				IPACMDBG_H("cache event(%d) subnet info v4Addr (%x) v4Mask (%x) dev(%s) on entry (%d)\n",
+						event_cache[latest_cache_index].event,
+						event_cache[latest_cache_index].prefix_cache.v4Addr,
+						event_cache[latest_cache_index].prefix_cache.v4Mask,
+						event_cache[latest_cache_index].dev_name,
+						latest_cache_index);
+			} else {
+				IPACMDBG_H("cache event (%d) v6Addr: %08x:%08x:%08x:%08x \n",
+						event_cache[latest_cache_index].event,
+						event_cache[latest_cache_index].prefix_cache.v6Addr[0],
+						event_cache[latest_cache_index].prefix_cache.v6Addr[1],
+						event_cache[latest_cache_index].prefix_cache.v6Addr[2],
+						event_cache[latest_cache_index].prefix_cache.v6Addr[3]);
+				IPACMDBG_H("subnet v6Mask: %08x:%08x:%08x:%08x dev(%s) on entry(%d),\n",
+						event_cache[latest_cache_index].prefix_cache.v6Mask[0],
+						event_cache[latest_cache_index].prefix_cache.v6Mask[1],
+						event_cache[latest_cache_index].prefix_cache.v6Mask[2],
+						event_cache[latest_cache_index].prefix_cache.v6Mask[3],
+						event_cache[latest_cache_index].dev_name,
+						latest_cache_index);
+			}
+			latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE;
+			ret = true;
+			break;
+		}
+		latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE;
+		if(i == MAX_EVENT_CACHE - 1)
+		{
+			IPACMDBG_H(" run out of event cache (%d)\n", i);
+			ret = false;
+		}
+	}
+	return ret;
+}
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 397a3c6..1a34388 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -1263,6 +1263,7 @@
 #ifdef FEATURE_IPACM_HAL
 		/* WA for WLAN to clean up NAT instance during SSR */
 		case IPA_SSR_NOTICE: //sky
+		case IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE:
 			IPACMDBG_H("Received IPA_SSR_NOTICE event.\n");
 			if(m_is_sta_mode == WLAN_WAN)
 			{
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index ef1fb1d..b787bad 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -49,7 +49,9 @@
 #include <IPACM_Lan.h>
 #include <IPACM_IfaceManager.h>
 #include <IPACM_ConntrackListener.h>
-
+#ifdef FEATURE_IPACM_HAL
+#include "IPACM_OffloadManager.h"
+#endif
 
 /* static member to store the number of total wifi clients within all APs*/
 int IPACM_Wlan::total_num_wifi_clients = 0;
@@ -149,6 +151,9 @@
 	int wlan_index;
 	ipacm_ext_prop* ext_prop;
 	ipacm_event_iface_up_tehter* data_wan_tether;
+#ifdef FEATURE_IPACM_HAL
+	IPACM_OffloadManager* OffloadMng;
+#endif
 
 	switch (event)
 	{
@@ -941,6 +946,28 @@
 		IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
 	}
 	break;
+	case IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE:
+        {
+                IPACMDBG_H("Received IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE.\n");
+
+                /* internal push add_downstream event in cache */
+                OffloadMng = IPACM_OffloadManager::GetInstance();
+                if (OffloadMng == NULL) {
+                        IPACMERR("failed to get IPACM_OffloadManager instance !\n");
+                } else {
+                        IPACMDBG_H("Update iface %s add_downstream cache events\n", dev_name);
+			if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+			{
+				OffloadMng->push_framework_event(dev_name, prefix[IPA_IP_v4]);
+			}
+			else if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+			{
+				OffloadMng->push_framework_event(dev_name, prefix[IPA_IP_v6]);
+			}
+                }
+                IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
+        }
+        break;
 #endif
 	default:
 		break;