1 /*
2 Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 	@file
31 	IPACM_Config.h
32 
33 	@brief
34 	This file implements the IPACM Configuration from XML file
35 
36 	@Author
37 	Skylar Chang
38 
39 */
40 #ifndef IPACM_CONFIG_H
41 #define IPACM_CONFIG_H
42 
43 #include "IPACM_Defs.h"
44 #include "IPACM_Xml.h"
45 #include "IPACM_EvtDispatcher.h"
46 
47 typedef struct
48 {
49   char iface_name[IPA_IFACE_NAME_LEN];
50   bool v4_up;
51   bool v6_up;
52 }NatIfaces;
53 
54 /* for IPACM rm dependency use*/
55 typedef struct _ipa_rm_client
56 {
57     ipa_rm_resource_name producer_rm1;
58     ipa_rm_resource_name consumer_rm1;
59     ipa_rm_resource_name producer_rm2;
60     ipa_rm_resource_name consumer_rm2;
61     bool producer1_up;            /* only monitor producer_rm1, not monitor producer_rm2 */
62     bool consumer1_up;            /* only monitor consumer_rm1, not monitor consumer_rm2 */
63     bool rm_set;                  /* once producer1_up and consumer1_up, will add bi-directional dependency */
64     bool rx_bypass_ipa;          /* support WLAN may not register RX-property, should not add dependency */
65 }ipa_rm_client;
66 
67 #define MAX_NUM_EXT_PROPS 25
68 
69 /* used to hold extended properties */
70 typedef struct
71 {
72 	uint8_t num_ext_props;
73 	ipa_ioc_ext_intf_prop prop[MAX_NUM_EXT_PROPS];
74 } ipacm_ext_prop;
75 
76 /* iface */
77 class IPACM_Config
78 {
79 public:
80 
81 	/* IPACM ipa_client map to rm_resource*/
82 	ipa_rm_resource_name ipa_client_rm_map_tbl[IPA_CLIENT_MAX];
83 
84 	/* IPACM monitored rm_depency table */
85 	ipa_rm_client ipa_rm_tbl[IPA_MAX_RM_ENTRY];
86 
87 	/* IPACM rm_depency a2 endpoint check*/
88 	int ipa_rm_a2_check;
89 
90 	/* Store interested interface and their configuration from XML file */
91 	ipa_ifi_dev_name_t *iface_table;
92 
93 	/* Store interested ALG port from XML file */
94 	ipacm_alg *alg_table;
95 
96 	/* Store private subnet configuration from XML file */
97 	ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
98 
99 	/* Store the non nat iface names */
100 	NatIfaces *pNatIfaces;
101 
102 	/* Store the bridge iface name */
103 	char ipa_virtual_iface_name[IPA_IFACE_NAME_LEN];
104 
105 	/* Store the number of interface IPACM read from XML file */
106 	int ipa_num_ipa_interfaces;
107 
108 	int ipa_num_private_subnet;
109 
110 	int ipa_num_alg_ports;
111 
112 	int ipa_nat_max_entries;
113 
114 	bool ipacm_odu_router_mode;
115 
116 	bool ipacm_odu_enable;
117 
118 	bool ipacm_odu_embms_enable;
119 
120 	bool ipacm_ip_passthrough_mode;
121 
122 	int ipa_nat_iface_entries;
123 
124 	/* Store the total number of wlan guest ap configured */
125 	int ipa_num_wlan_guest_ap;
126 
127 	/* Max valid rm entry */
128 	int ipa_max_valid_rm_entry;
129 
130 	/* Store SW-enable or not */
131 	bool ipa_sw_rt_enable;
132 
133 	/* Store bridge mode or not */
134 	bool ipa_bridge_enable;
135 
136 	/* Store bridge netdev mac */
137 	uint8_t bridge_mac[IPA_MAC_ADDR_SIZE];
138 
139 	/* Store the flt rule count for each producer client*/
140 	int flt_rule_count_v4[IPA_CLIENT_MAX];
141 	int flt_rule_count_v6[IPA_CLIENT_MAX];
142 
143 	/* IPACM routing table name for v4/v6 */
144 	struct ipa_ioc_get_rt_tbl rt_tbl_lan_v4, rt_tbl_wan_v4, rt_tbl_default_v4, rt_tbl_v6, rt_tbl_wan_v6;
145 	struct ipa_ioc_get_rt_tbl rt_tbl_wan_dl;
146 	struct ipa_ioc_get_rt_tbl rt_tbl_odu_v4, rt_tbl_odu_v6;
147 
148 	bool isMCC_Mode;
149 
150 	/* IPA_HW_FNR_STATS */
151 	bool hw_fnr_stats_support;
152 	int hw_counter_offset;
153 	int sw_counter_offset;
154 
155 	/* To return the instance */
156 	static IPACM_Config* GetInstance();
157 
158 	const char* getEventName(ipa_cm_event_id event_id);
159 
increaseFltRuleCount(int index,ipa_ip_type iptype,int increment)160 	inline void increaseFltRuleCount(int index, ipa_ip_type iptype, int increment)
161 	{
162 		if((index >= IPA_CLIENT_MAX) || (index < 0))
163 		{
164 			IPACMERR("Index is out of range: %d.\n", index);
165 			return;
166 		}
167 		if(iptype == IPA_IP_v4)
168 		{
169 			flt_rule_count_v4[index] += increment;
170 			IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]);
171 		}
172 		else
173 		{
174 			flt_rule_count_v6[index] += increment;
175 			IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]);
176 		}
177 		return;
178 	}
179 
decreaseFltRuleCount(int index,ipa_ip_type iptype,int decrement)180 	inline void decreaseFltRuleCount(int index, ipa_ip_type iptype, int decrement)
181 	{
182 		if((index >= IPA_CLIENT_MAX) || (index < 0))
183 		{
184 			IPACMERR("Index is out of range: %d.\n", index);
185 			return;
186 		}
187 		if(iptype == IPA_IP_v4)
188 		{
189 			flt_rule_count_v4[index] -= decrement;
190 			IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]);
191 		}
192 		else
193 		{
194 			flt_rule_count_v6[index] -= decrement;
195 			IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]);
196 		}
197 		return;
198 	}
199 
getFltRuleCount(int index,ipa_ip_type iptype)200 	inline int getFltRuleCount(int index, ipa_ip_type iptype)
201 	{
202 		if((index >= IPA_CLIENT_MAX) || (index < 0))
203 		{
204 			IPACMERR("Index is out of range: %d.\n", index);
205 			return -1;
206 		}
207 		if(iptype == IPA_IP_v4)
208 		{
209 			return flt_rule_count_v4[index];
210 		}
211 		else
212 		{
213 			return flt_rule_count_v6[index];
214 		}
215 	}
216 
GetAlgPortCnt()217 	inline int GetAlgPortCnt()
218 	{
219 		return ipa_num_alg_ports;
220 	}
221 
222 	int GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts);
223 
GetNatMaxEntries(void)224 	inline int GetNatMaxEntries(void)
225 	{
226 		return ipa_nat_max_entries;
227 	}
228 
GetNatIfacesCnt()229 	inline int GetNatIfacesCnt()
230 	{
231 		return ipa_nat_iface_entries;
232 	}
233 	int GetNatIfaces(int nPorts, NatIfaces *ifaces);
234 
235 	/* for IPACM resource manager dependency usage */
236 	void AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa);
237 
238 	void DelRmDepend(ipa_rm_resource_name rm1);
239 
240 	int AddNatIfaces(char *dev_name, ipa_ip_type ip_type);
241 
242 	int DelNatIfaces(char *dev_name);
243 
244 	int CheckNatIfaces(const char *dev_name, ipa_ip_type ip_type);
245 
SetQmapId(uint8_t id)246 	inline void SetQmapId(uint8_t id)
247 	{
248 		qmap_id = id;
249 	}
250 
GetQmapId()251 	inline uint8_t GetQmapId()
252 	{
253 		return qmap_id;
254 	}
255 
256 	int SetExtProp(ipa_ioc_query_intf_ext_props *prop);
257 
258 	ipacm_ext_prop* GetExtProp(ipa_ip_type ip_type);
259 
260 	int DelExtProp(ipa_ip_type ip_type);
261 
262 	enum ipa_hw_type GetIPAVer(bool get = false);
263 
264 	bool isEthBridgingSupported();
265 
266 	bool isIPAv3Supported();
267 
268 	int Init(void);
269 
isPrivateSubnet(uint32_t ip_addr)270 	inline bool isPrivateSubnet(uint32_t ip_addr)
271 	{
272 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
273 		{
274 			if(private_subnet_table[cnt].subnet_addr ==
275 				 (private_subnet_table[cnt].subnet_mask & ip_addr))
276 			{
277 				return true;
278 			}
279 		}
280 
281 		return false;
282 	}
283 #ifdef FEATURE_IPA_ANDROID
AddPrivateSubnet(uint32_t ip_addr,int ipa_if_index)284 	inline bool AddPrivateSubnet(uint32_t ip_addr, int ipa_if_index)
285 	{
286 		ipacm_cmd_q_data evt_data;
287 		ipacm_event_data_fid *data_fid;
288 		uint32_t subnet_mask = ~0;
289 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
290 		{
291 			if(private_subnet_table[cnt].subnet_addr == ip_addr)
292 			{
293 				IPACMDBG("Already has private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, cnt);
294 				return true;
295 			}
296 		}
297 
298 		if(ipa_num_private_subnet < IPA_MAX_PRIVATE_SUBNET_ENTRIES)
299 		{
300 			IPACMDBG("Add IPACM private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, ipa_num_private_subnet);
301 			private_subnet_table[ipa_num_private_subnet].subnet_addr = ip_addr;
302 			private_subnet_table[ipa_num_private_subnet].subnet_mask = (subnet_mask >> 8) << 8;
303 			ipa_num_private_subnet++;
304 
305 			/* IPACM private subnet set changes */
306 			data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
307 			if(data_fid == NULL)
308 			{
309 				IPACMERR("unable to allocate memory for event data_fid\n");
310 				return IPACM_FAILURE;
311 			}
312 			data_fid->if_index = ipa_if_index; // already ipa index, not fid index
313 			evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT;
314 			evt_data.evt_data = data_fid;
315 
316 			/* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */
317 			IPACM_EvtDispatcher::PostEvt(&evt_data);
318 			return true;
319 		}
320 		IPACMERR("IPACM private subnet_addr overflow, total entry(%d)\n", ipa_num_private_subnet);
321 		return false;
322 	}
323 
DelPrivateSubnet(uint32_t ip_addr,int ipa_if_index)324 	inline bool DelPrivateSubnet(uint32_t ip_addr, int ipa_if_index)
325 	{
326 		ipacm_cmd_q_data evt_data;
327 		ipacm_event_data_fid *data_fid;
328 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
329 		{
330 			if(private_subnet_table[cnt].subnet_addr == ip_addr)
331 			{
332 				IPACMDBG("Found private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, cnt);
333 				for (; cnt < ipa_num_private_subnet - 1; cnt++)
334 				{
335 					private_subnet_table[cnt].subnet_addr = private_subnet_table[cnt+1].subnet_addr;
336 				}
337 				ipa_num_private_subnet = ipa_num_private_subnet - 1;
338 
339 				/* IPACM private subnet set changes */
340 				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
341 				if(data_fid == NULL)
342 				{
343 					IPACMERR("unable to allocate memory for event data_fid\n");
344 					return IPACM_FAILURE;
345 				}
346 				data_fid->if_index = ipa_if_index; // already ipa index, not fid index
347 				evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT;
348 				evt_data.evt_data = data_fid;
349 
350 				/* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */
351 				IPACM_EvtDispatcher::PostEvt(&evt_data);
352 				return true;
353 			}
354 		}
355 		IPACMDBG("can't find private subnet_addr as: 0x%x \n", ip_addr);
356 		return false;
357 	}
358 #endif /* defined(FEATURE_IPA_ANDROID)*/
359 
360 	static const char *DEVICE_NAME_ODU;
361 
362 private:
363 	enum ipa_hw_type ver;
364 	static IPACM_Config *pInstance;
365 	static const char *DEVICE_NAME;
366 	IPACM_Config(void);
367 	int m_fd; /* File descriptor of the IPA device node /dev/ipa */
368 	uint8_t qmap_id;
369 	ipacm_ext_prop ext_prop_v4;
370 	ipacm_ext_prop ext_prop_v6;
371 };
372 
373 #endif /* IPACM_CONFIG */
374