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_Filtering.cpp
32
33 @brief
34 This file implements the IPACM filtering functionality.
35
36 @Author
37 Skylar Chang
38
39 */
40 #include <unistd.h>
41 #include <sys/ioctl.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #include "IPACM_Filtering.h"
47 #include <IPACM_Log.h>
48 #include "IPACM_Defs.h"
49 #include "IPACM_Iface.h"
50
51
52 const char *IPACM_Filtering::DEVICE_NAME = "/dev/ipa";
53
IPACM_Filtering()54 IPACM_Filtering::IPACM_Filtering()
55 {
56 fd = open(DEVICE_NAME, O_RDWR);
57 if (fd < 0)
58 {
59 IPACMERR("Failed opening %s.\n", DEVICE_NAME);
60 }
61 total_num_offload_rules = 0;
62 pcie_modem_rule_id = 0;
63 memset(pcie_modem_rule_id_in_use, 0, sizeof(pcie_modem_rule_id_in_use));
64 }
65
~IPACM_Filtering()66 IPACM_Filtering::~IPACM_Filtering()
67 {
68 close(fd);
69 }
70
DeviceNodeIsOpened()71 bool IPACM_Filtering::DeviceNodeIsOpened()
72 {
73 return fd;
74 }
75
AddFilteringRule(struct ipa_ioc_add_flt_rule const * ruleTable)76 bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable)
77 {
78 int retval = 0;
79
80 IPACMDBG("Printing filter add attributes\n");
81 IPACMDBG("ip type: %d\n", ruleTable->ip);
82 IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
83 IPACMDBG("End point: %d and global value: %d\n", ruleTable->ep, ruleTable->global);
84 IPACMDBG("commit value: %d\n", ruleTable->commit);
85 for (int cnt=0; cnt<ruleTable->num_rules; cnt++)
86 {
87 IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
88 ruleTable->rules[cnt].rule.attrib.attrib_mask);
89 }
90
91 retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable);
92 if (retval != 0)
93 {
94 IPACMERR("Failed adding Filtering rule %pK\n", ruleTable);
95 PERROR("unable to add filter rule:");
96
97 for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
98 {
99 if (ruleTable->rules[cnt].status != 0)
100 {
101 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
102 cnt, ruleTable->rules[cnt].status);
103 }
104 }
105 return false;
106 }
107
108 for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
109 {
110 if(ruleTable->rules[cnt].status != 0)
111 {
112 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
113 cnt, ruleTable->rules[cnt].status);
114 }
115 }
116
117 IPACMDBG("Added Filtering rule %pK\n", ruleTable);
118 return true;
119 }
120
121 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
AddFilteringRule_hw_index(struct ipa_ioc_add_flt_rule * ruleTable,int hw_counter_index)122 bool IPACM_Filtering::AddFilteringRule_hw_index(struct ipa_ioc_add_flt_rule *ruleTable, int hw_counter_index)
123 {
124 int retval=0, cnt = 0, len = 0;
125 struct ipa_ioc_add_flt_rule_v2 *ruleTable_v2;
126 struct ipa_flt_rule_add_v2 flt_rule_entry;
127 bool ret = true;
128
129 IPACMDBG("Printing filter add attributes\n");
130 IPACMDBG("ip type: %d\n", ruleTable->ip);
131 IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
132 IPACMDBG("End point: %d and global value: %d\n", ruleTable->ep, ruleTable->global);
133 IPACMDBG("commit value: %d\n", ruleTable->commit);
134
135 /* change to v2 format*/
136 len = sizeof(struct ipa_ioc_add_flt_rule_v2);
137 ruleTable_v2 = (struct ipa_ioc_add_flt_rule_v2*)malloc(len);
138 if (ruleTable_v2 == NULL)
139 {
140 IPACMERR("Error Locate ipa_ioc_add_flt_rule_v2 memory...\n");
141 return false;
142 }
143 memset(ruleTable_v2, 0, len);
144 ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2));
145 if (!ruleTable_v2->rules) {
146 IPACMERR("Failed to allocate memory for filtering rules\n");
147 ret = false;
148 goto fail_tbl;
149 }
150
151 ruleTable_v2->commit = ruleTable->commit;
152 ruleTable_v2->ep = ruleTable->ep;
153 ruleTable_v2->global = ruleTable->global;
154 ruleTable_v2->ip = ruleTable->ip;
155 ruleTable_v2->num_rules = ruleTable->num_rules;
156 ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2);
157
158 for (cnt=0; cnt < ruleTable->num_rules; cnt++)
159 {
160 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2));
161 flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear;
162 flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr;
163 flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc;
164 flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action;
165 flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl;
166 flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx;
167 flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type;
168 flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio;
169 flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable;
170 flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id;
171 flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata;
172 flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx;
173 memcpy(&flt_rule_entry.rule.eq_attrib,
174 &ruleTable->rules[cnt].rule.eq_attrib,
175 sizeof(flt_rule_entry.rule.eq_attrib));
176 memcpy(&flt_rule_entry.rule.attrib,
177 &ruleTable->rules[cnt].rule.attrib,
178 sizeof(flt_rule_entry.rule.attrib));
179 IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
180 ruleTable->rules[cnt].rule.attrib.attrib_mask);
181 /* 0 means disable hw-counter-sats */
182 if (hw_counter_index != 0)
183 {
184 flt_rule_entry.rule.enable_stats = 1;
185 flt_rule_entry.rule.cnt_idx = hw_counter_index;
186 }
187
188 /* copy to v2 table*/
189 memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))),
190 &flt_rule_entry, sizeof(flt_rule_entry));
191 }
192
193 retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_V2, ruleTable_v2);
194 if (retval != 0)
195 {
196 IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2);
197 PERROR("unable to add filter rule:");
198
199 for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++)
200 {
201 if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
202 {
203 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
204 cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status);
205 }
206 }
207 ret = false;
208 goto fail_rule;
209 }
210
211 /* copy results from v2 to v1 format */
212 for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
213 {
214 /* copy status to v1 format */
215 ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status;
216 ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl;
217
218 if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
219 {
220 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
221 cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status);
222 }
223 }
224
225 IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2);
226
227 fail_rule:
228 if((void *)ruleTable_v2->rules != NULL)
229 free((void *)ruleTable_v2->rules);
230 fail_tbl:
231 if (ruleTable_v2 != NULL)
232 free(ruleTable_v2);
233 return ret;
234 }
235
AddFilteringRuleAfter_hw_index(struct ipa_ioc_add_flt_rule_after * ruleTable,int hw_counter_index)236 bool IPACM_Filtering::AddFilteringRuleAfter_hw_index(struct ipa_ioc_add_flt_rule_after *ruleTable, int hw_counter_index)
237 {
238 bool ret = true;
239 int retval=0, cnt = 0, len = 0;
240 struct ipa_ioc_add_flt_rule_after_v2 *ruleTable_v2;
241 struct ipa_flt_rule_add_v2 flt_rule_entry;
242
243 if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
244 {
245 IPACMDBG("Printing filter add attributes\n");
246 IPACMDBG("ep: %d\n", ruleTable->ep);
247 IPACMDBG("ip type: %d\n", ruleTable->ip);
248 IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
249 IPACMDBG("add_after_hdl: %d\n", ruleTable->add_after_hdl);
250 IPACMDBG("commit value: %d\n", ruleTable->commit);
251
252 /* change to v2 format*/
253 len = sizeof(struct ipa_ioc_add_flt_rule_after_v2);
254 ruleTable_v2 = (struct ipa_ioc_add_flt_rule_after_v2*)malloc(len);
255 if (ruleTable_v2 == NULL)
256 {
257 IPACMERR("Error Locate ipa_ioc_add_flt_rule_after_v2 memory...\n");
258 return false;
259 }
260 memset(ruleTable_v2, 0, len);
261 ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2));
262 if (!ruleTable_v2->rules) {
263 IPACMERR("Failed to allocate memory for filtering rules\n");
264 ret = false;
265 goto fail_tbl;
266 }
267
268 ruleTable_v2->commit = ruleTable->commit;
269 ruleTable_v2->ep = ruleTable->ep;
270 ruleTable_v2->ip = ruleTable->ip;
271 ruleTable_v2->num_rules = ruleTable->num_rules;
272 ruleTable_v2->add_after_hdl = ruleTable->add_after_hdl;
273 ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2);
274
275 for (cnt=0; cnt < ruleTable->num_rules; cnt++)
276 {
277 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2));
278 flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear;
279 flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr;
280 flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc;
281 flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action;
282 flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl;
283 flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx;
284 flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type;
285 flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio;
286 flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable;
287 flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id;
288 flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata;
289 flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx;
290 memcpy(&flt_rule_entry.rule.eq_attrib,
291 &ruleTable->rules[cnt].rule.eq_attrib,
292 sizeof(flt_rule_entry.rule.eq_attrib));
293 memcpy(&flt_rule_entry.rule.attrib,
294 &ruleTable->rules[cnt].rule.attrib,
295 sizeof(flt_rule_entry.rule.attrib));
296 IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
297 ruleTable->rules[cnt].rule.attrib.attrib_mask);
298 /* 0 means disable hw-counter-sats */
299 if (hw_counter_index != 0)
300 {
301 flt_rule_entry.rule.enable_stats = 1;
302 flt_rule_entry.rule.cnt_idx = hw_counter_index;
303 }
304
305 /* copy to v2 table*/
306 memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))),
307 &flt_rule_entry, sizeof(flt_rule_entry));
308 }
309
310 retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER_V2, ruleTable_v2);
311 if (retval != 0)
312 {
313 IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2);
314 PERROR("unable to add filter rule:");
315
316 for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++)
317 {
318 if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
319 {
320 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
321 cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status);
322 }
323 }
324 ret = false;
325 goto fail_rule;
326 }
327
328 /* copy results from v2 to v1 format */
329 for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
330 {
331 /* copy status to v1 format */
332 ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status;
333 ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl;
334
335 if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
336 {
337 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
338 cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status);
339 }
340 }
341
342 IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2);
343
344 fail_rule:
345 if((void *)ruleTable_v2->rules != NULL)
346 free((void *)ruleTable_v2->rules);
347 fail_tbl:
348 if (ruleTable_v2 != NULL)
349 free(ruleTable_v2);
350 }
351 else
352 {
353 if (ruleTable)
354 IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
355 }
356 return ret;
357 }
358 #endif //IPA_IOCTL_SET_FNR_COUNTER_INFO
359
AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const * ruleTable)360 bool IPACM_Filtering::AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable)
361 {
362 int retval = 0;
363
364 if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
365 {
366 IPACMDBG("Printing filter add attributes\n");
367 IPACMDBG("ip type: %d\n", ruleTable->ip);
368 IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
369 IPACMDBG("End point: %d\n", ruleTable->ep);
370 IPACMDBG("commit value: %d\n", ruleTable->commit);
371
372 retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER, ruleTable);
373
374 for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
375 {
376 if(ruleTable->rules[cnt].status != 0)
377 {
378 IPACMERR("Adding Filter rule:%d failed with status:%d\n",
379 cnt, ruleTable->rules[cnt].status);
380 }
381 }
382
383 if (retval != 0)
384 {
385 IPACMERR("Failed adding Filtering rule %pK\n", ruleTable);
386 return false;
387 }
388 IPACMDBG("Added Filtering rule %pK\n", ruleTable);
389 }
390 else
391 {
392 if (ruleTable)
393 IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
394 }
395 return true;
396 }
397
DeleteFilteringRule(struct ipa_ioc_del_flt_rule * ruleTable)398 bool IPACM_Filtering::DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable)
399 {
400 int retval = 0;
401
402 retval = ioctl(fd, IPA_IOC_DEL_FLT_RULE, ruleTable);
403 if (retval != 0)
404 {
405 IPACMERR("Failed deleting Filtering rule %pK\n", ruleTable);
406 return false;
407 }
408
409 IPACMDBG("Deleted Filtering rule %pK\n", ruleTable);
410 return true;
411 }
412
Commit(enum ipa_ip_type ip)413 bool IPACM_Filtering::Commit(enum ipa_ip_type ip)
414 {
415 int retval = 0;
416
417 retval = ioctl(fd, IPA_IOC_COMMIT_FLT, ip);
418 if (retval != 0)
419 {
420 IPACMERR("failed committing Filtering rules.\n");
421 return false;
422 }
423
424 IPACMDBG("Committed Filtering rules to IPA HW.\n");
425 return true;
426 }
427
Reset(enum ipa_ip_type ip)428 bool IPACM_Filtering::Reset(enum ipa_ip_type ip)
429 {
430 int retval = 0;
431
432 retval = ioctl(fd, IPA_IOC_RESET_FLT, ip);
433 retval |= ioctl(fd, IPA_IOC_COMMIT_FLT, ip);
434 if (retval)
435 {
436 IPACMERR("failed resetting Filtering block.\n");
437 return false;
438 }
439
440 IPACMDBG("Reset command issued to IPA Filtering block.\n");
441 return true;
442 }
443
DeleteFilteringHdls(uint32_t * flt_rule_hdls,ipa_ip_type ip,uint8_t num_rules)444 bool IPACM_Filtering::DeleteFilteringHdls
445 (
446 uint32_t *flt_rule_hdls,
447 ipa_ip_type ip,
448 uint8_t num_rules
449 )
450 {
451 struct ipa_ioc_del_flt_rule *flt_rule;
452 bool res = true;
453 int len = 0, cnt = 0;
454 const uint8_t UNIT_RULES = 1;
455
456 len = (sizeof(struct ipa_ioc_del_flt_rule)) + (UNIT_RULES * sizeof(struct ipa_flt_rule_del));
457 flt_rule = (struct ipa_ioc_del_flt_rule *)malloc(len);
458 if (flt_rule == NULL)
459 {
460 IPACMERR("unable to allocate memory for del filter rule\n");
461 return false;
462 }
463
464 for (cnt = 0; cnt < num_rules; cnt++)
465 {
466 memset(flt_rule, 0, len);
467 flt_rule->commit = 1;
468 flt_rule->num_hdls = UNIT_RULES;
469 flt_rule->ip = ip;
470
471 if (flt_rule_hdls[cnt] == 0)
472 {
473 IPACMERR("invalid filter handle passed, ignoring it: %d\n", cnt)
474 }
475 else
476 {
477
478 flt_rule->hdl[0].status = -1;
479 flt_rule->hdl[0].hdl = flt_rule_hdls[cnt];
480 IPACMDBG("Deleting filter hdl:(0x%x) with ip type: %d\n", flt_rule_hdls[cnt], ip);
481
482 if (DeleteFilteringRule(flt_rule) == false)
483 {
484 PERROR("Filter rule deletion failed!\n");
485 res = false;
486 goto fail;
487 }
488 else
489 {
490
491 if (flt_rule->hdl[0].status != 0)
492 {
493 IPACMERR("Filter rule hdl 0x%x deletion failed with error:%d\n",
494 flt_rule->hdl[0].hdl, flt_rule->hdl[0].status);
495 res = false;
496 goto fail;
497 }
498 }
499 }
500 }
501
502 fail:
503 free(flt_rule);
504
505 return res;
506 }
507
AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const * rule_table_v4,struct ipa_ioc_add_flt_rule const * rule_table_v6,uint8_t mux_id)508 bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id)
509 {
510 int ret = 0, cnt, num_rules = 0, pos = 0;
511 ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg;
512 ipa_install_fltr_rule_req_ex_msg_v01 qmi_rule_ex_msg;
513
514 memset(&qmi_rule_msg, 0, sizeof(qmi_rule_msg));
515 int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
516 if(fd_wwan_ioctl < 0)
517 {
518 IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
519 return false;
520 }
521
522 if(rule_table_v4 != NULL)
523 {
524 num_rules += rule_table_v4->num_rules;
525 IPACMDBG_H("Get %d WAN DL IPv4 filtering rules.\n", rule_table_v4->num_rules);
526 }
527 if(rule_table_v6 != NULL)
528 {
529 num_rules += rule_table_v6->num_rules;
530 IPACMDBG_H("Get %d WAN DL IPv6 filtering rules.\n", rule_table_v6->num_rules);
531 }
532
533 /* if it is not IPA v3, use old QMI format */
534 if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
535 {
536 if(num_rules > QMI_IPA_MAX_FILTERS_V01)
537 {
538 IPACMERR("The number of filtering rules exceed limit.\n");
539 close(fd_wwan_ioctl);
540 return false;
541 }
542 else
543 {
544 if (num_rules > 0)
545 {
546 qmi_rule_msg.filter_spec_list_valid = true;
547 }
548 else
549 {
550 qmi_rule_msg.filter_spec_list_valid = false;
551 }
552
553 qmi_rule_msg.filter_spec_list_len = num_rules;
554 qmi_rule_msg.source_pipe_index_valid = 0;
555
556 IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
557
558 if(rule_table_v4 != NULL)
559 {
560 for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
561 {
562 if (pos < QMI_IPA_MAX_FILTERS_V01)
563 {
564 qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
565 qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
566 qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
567 qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
568 qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
569 qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
570 qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
571 memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
572 &rule_table_v4->rules[cnt].rule.eq_attrib,
573 sizeof(struct ipa_filter_rule_type_v01));
574 pos++;
575 }
576 else
577 {
578 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
579 }
580 }
581 }
582
583 if(rule_table_v6 != NULL)
584 {
585 for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
586 {
587 if (pos < QMI_IPA_MAX_FILTERS_V01)
588 {
589 qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
590 qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
591 qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
592 qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
593 qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
594 qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
595 qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
596 memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
597 &rule_table_v6->rules[cnt].rule.eq_attrib,
598 sizeof(struct ipa_filter_rule_type_v01));
599 pos++;
600 }
601 else
602 {
603 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
604 }
605 }
606 }
607
608 ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg);
609 if (ret != 0)
610 {
611 IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret);
612 close(fd_wwan_ioctl);
613 return false;
614 }
615 }
616 /* if it is IPA v3, use new QMI format */
617 }
618 else
619 {
620 if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01)
621 {
622 IPACMERR("The number of filtering rules exceed limit.\n");
623 close(fd_wwan_ioctl);
624 return false;
625 }
626 else
627 {
628 memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg));
629
630 if (num_rules > 0)
631 {
632 qmi_rule_ex_msg.filter_spec_ex_list_valid = true;
633 }
634 else
635 {
636 qmi_rule_ex_msg.filter_spec_ex_list_valid = false;
637 }
638 qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules;
639 qmi_rule_ex_msg.source_pipe_index_valid = 0;
640
641 IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
642
643 if(rule_table_v4 != NULL)
644 {
645 for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
646 {
647 if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
648 {
649 qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
650 qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
651 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
652 qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
653 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
654 qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
655 qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
656 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
657 memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
658 &rule_table_v4->rules[cnt].rule.eq_attrib,
659 sizeof(struct ipa_filter_rule_type_v01));
660
661 pos++;
662 }
663 else
664 {
665 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
666 }
667 }
668 }
669
670 if(rule_table_v6 != NULL)
671 {
672 for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
673 {
674 if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
675 {
676 qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
677 qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
678 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
679 qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
680 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
681 qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
682 qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
683 qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
684 memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
685 &rule_table_v6->rules[cnt].rule.eq_attrib,
686 sizeof(struct ipa_filter_rule_type_v01));
687
688 pos++;
689 }
690 else
691 {
692 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
693 }
694 }
695 }
696
697 ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg);
698 if (ret != 0)
699 {
700 IPACMERR("Failed adding Filtering rule %pK with ret %d\n ", &qmi_rule_ex_msg, ret);
701 close(fd_wwan_ioctl);
702 return false;
703 }
704 }
705 }
706
707 close(fd_wwan_ioctl);
708 return true;
709 }
710
AddOffloadFilteringRule(struct ipa_ioc_add_flt_rule * flt_rule_tbl,uint8_t mux_id,uint8_t default_path)711 bool IPACM_Filtering::AddOffloadFilteringRule(struct ipa_ioc_add_flt_rule *flt_rule_tbl, uint8_t mux_id, uint8_t default_path)
712 {
713 #ifdef WAN_IOCTL_ADD_OFFLOAD_CONNECTION
714 int ret = 0, cnt, pos = 0, i;
715 ipa_add_offload_connection_req_msg_v01 qmi_add_msg;
716 int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
717 if(fd_wwan_ioctl < 0)
718 {
719 IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
720 return false;
721 }
722
723 if(flt_rule_tbl == NULL)
724 {
725 if(mux_id ==0)
726 {
727 IPACMERR("Invalid add_offload_req muxd: (%d)\n", mux_id);
728 close(fd_wwan_ioctl);
729 return false;
730 }
731 #ifdef QMI_IPA_MAX_FILTERS_EX2_V01
732 /* used for sending mux_id info to modem for UL sky*/
733 IPACMDBG_H("sending mux_id info (%d) to modem for UL\n", mux_id);
734 memset(&qmi_add_msg, 0, sizeof(qmi_add_msg));
735 qmi_add_msg.embedded_call_mux_id_valid = true;
736 qmi_add_msg.embedded_call_mux_id = mux_id;
737 ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_OFFLOAD_CONNECTION, &qmi_add_msg);
738 if (ret != 0)
739 {
740 IPACMERR("Failed sending WAN_IOC_ADD_OFFLOAD_CONNECTION with ret %d\n ", ret);
741 close(fd_wwan_ioctl);
742 return false;
743 }
744 #endif
745 close(fd_wwan_ioctl);
746 return true;
747 }
748 /* check Max offload connections */
749 if (total_num_offload_rules + flt_rule_tbl->num_rules > QMI_IPA_MAX_FILTERS_V01)
750 {
751 IPACMERR("(%d) add_offload req with curent(%d), exceed max (%d).\n",
752 flt_rule_tbl->num_rules, total_num_offload_rules,
753 QMI_IPA_MAX_FILTERS_V01);
754 close(fd_wwan_ioctl);
755 return false;
756 }
757 else
758 {
759 memset(&qmi_add_msg, 0, sizeof(qmi_add_msg));
760
761 if (flt_rule_tbl->num_rules > 0)
762 {
763 qmi_add_msg.filter_spec_ex2_list_valid = true;
764 }
765 else
766 {
767 IPACMDBG_H("Get %d offload-req\n", flt_rule_tbl->num_rules);
768 close(fd_wwan_ioctl);
769 return true;
770 }
771 qmi_add_msg.filter_spec_ex2_list_len = flt_rule_tbl->num_rules;
772
773 /* check if we want to take default MHI path */
774 if (default_path)
775 {
776 qmi_add_msg.default_mhi_path_valid = true;
777 qmi_add_msg.default_mhi_path = true;
778 }
779
780 IPACMDBG_H("passing %d offload req to modem. default %d\n", flt_rule_tbl->num_rules, qmi_add_msg.default_mhi_path);
781
782 if(flt_rule_tbl != NULL)
783 {
784 for(cnt = flt_rule_tbl->num_rules - 1; cnt >= 0; cnt--)
785 {
786 if (pos < QMI_IPA_MAX_FILTERS_V01)
787 {
788 if (flt_rule_tbl->ip == IPA_IP_v4)
789 {
790 qmi_add_msg.filter_spec_ex2_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
791 } else if (flt_rule_tbl->ip == IPA_IP_v6) {
792 qmi_add_msg.filter_spec_ex2_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
793 } else {
794 IPACMDBG_H("invalid ip-type %d\n", flt_rule_tbl->ip);
795 close(fd_wwan_ioctl);
796 return true;
797 }
798
799 qmi_add_msg.filter_spec_ex2_list[pos].filter_action = GetQmiFilterAction(flt_rule_tbl->rules[cnt].rule.action);
800 qmi_add_msg.filter_spec_ex2_list[pos].is_mux_id_valid = 1;
801 qmi_add_msg.filter_spec_ex2_list[pos].mux_id = mux_id;
802 /* assign the rule-id */
803 flt_rule_tbl->rules[cnt].flt_rule_hdl = IPA_PCIE_MODEM_RULE_ID_START + pcie_modem_rule_id;
804 qmi_add_msg.filter_spec_ex2_list[pos].rule_id = flt_rule_tbl->rules[cnt].flt_rule_hdl;
805 qmi_add_msg.filter_spec_ex2_list[pos].is_rule_hashable = flt_rule_tbl->rules[cnt].rule.hashable;
806 memcpy(&qmi_add_msg.filter_spec_ex2_list[pos].filter_rule,
807 &flt_rule_tbl->rules[cnt].rule.eq_attrib,
808 sizeof(struct ipa_filter_rule_type_v01));
809 IPACMDBG_H("mux-id %d, hashable %d\n", qmi_add_msg.filter_spec_ex2_list[pos].mux_id, qmi_add_msg.filter_spec_ex2_list[pos].is_rule_hashable);
810 pos++;
811 pcie_modem_rule_id_in_use[pcie_modem_rule_id] = true;
812 for(i = 0; i < IPA_PCIE_MODEM_RULE_ID_MAX; i++)
813 {
814 pcie_modem_rule_id = (pcie_modem_rule_id + 1)%IPA_PCIE_MODEM_RULE_ID_MAX;
815 if(!pcie_modem_rule_id_in_use[pcie_modem_rule_id])
816 break;
817 }
818
819 if(i == IPA_PCIE_MODEM_RULE_ID_MAX)
820 {
821 IPACMERR("all handles are in use, max = %d\n", i);
822 return false;
823 }
824 else
825 {
826 IPACMDBG("next free pcie_modem_rule_id: %d\n", pcie_modem_rule_id);
827 }
828 }
829 else
830 {
831 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
832 }
833 }
834 }
835
836 ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_OFFLOAD_CONNECTION, &qmi_add_msg);
837 if (ret != 0)
838 {
839 IPACMERR("Failed sending WAN_IOC_ADD_OFFLOAD_CONNECTION with ret %d\n ", ret);
840 close(fd_wwan_ioctl);
841 return false;
842 }
843 }
844 /* update total_num_offload_rules */
845 total_num_offload_rules += flt_rule_tbl->num_rules;
846 IPACMDBG_H("total_num_offload_rules %d \n", total_num_offload_rules);
847 close(fd_wwan_ioctl);
848 return true;
849 #else
850 if(flt_rule_tbl != NULL)
851 {
852 IPACMERR("Not support (%d) AddOffloadFilteringRule with mux-id (%d) and default path = %d\n", flt_rule_tbl->num_rules, mux_id, default_path);
853 }
854 return false;
855 #endif
856 }
857
DelOffloadFilteringRule(struct ipa_ioc_del_flt_rule const * flt_rule_tbl)858 bool IPACM_Filtering::DelOffloadFilteringRule(struct ipa_ioc_del_flt_rule const *flt_rule_tbl)
859 {
860 #ifdef WAN_IOCTL_ADD_OFFLOAD_CONNECTION
861 bool result = true;
862 int ret = 0, cnt, pos = 0;
863 ipa_remove_offload_connection_req_msg_v01 qmi_del_msg;
864 int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
865
866 if(fd_wwan_ioctl < 0)
867 {
868 IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
869 return false;
870 }
871
872 if(flt_rule_tbl == NULL)
873 {
874 IPACMERR("Invalid add_offload_req\n");
875 result = false;
876 goto fail;
877 }
878
879 /* check # of offload connections */
880 if (flt_rule_tbl->num_hdls > total_num_offload_rules) {
881 IPACMERR("(%d) del_offload req , exceed curent(%d)\n",
882 flt_rule_tbl->num_hdls, total_num_offload_rules);
883 result = false;
884 goto fail;
885 }
886 else
887 {
888 memset(&qmi_del_msg, 0, sizeof(qmi_del_msg));
889
890 if (flt_rule_tbl->num_hdls > 0)
891 {
892 qmi_del_msg.filter_handle_list_valid = true;
893 }
894 else
895 {
896 IPACMERR("Get %d offload-req\n", flt_rule_tbl->num_hdls);
897 goto fail;
898 }
899 qmi_del_msg.filter_handle_list_len = flt_rule_tbl->num_hdls;
900
901 IPACMDBG_H("passing %d offload req to modem.\n", flt_rule_tbl->num_hdls);
902
903 if(flt_rule_tbl != NULL)
904 {
905 for(cnt = flt_rule_tbl->num_hdls - 1; cnt >= 0; cnt--)
906 {
907 if (pos < QMI_IPA_MAX_FILTERS_V01)
908 {
909 /* passing rule-id to wan-driver */
910 qmi_del_msg.filter_handle_list[pos].filter_spec_identifier = flt_rule_tbl->hdl[cnt].hdl;
911 pos++;
912
913 /* set in use to false for future rule additions (need to subtract offset and mod max index) */
914 pcie_modem_rule_id_in_use[(IPA_PCIE_MODEM_RULE_ID_MAX + flt_rule_tbl->hdl[cnt].hdl - IPA_PCIE_MODEM_RULE_ID_START)
915 % IPA_PCIE_MODEM_RULE_ID_MAX] = false;
916 IPACMDBG("freeing pcie_modem_rule_id: %d\n", (IPA_PCIE_MODEM_RULE_ID_MAX + flt_rule_tbl->hdl[cnt].hdl -IPA_PCIE_MODEM_RULE_ID_START)
917 % IPA_PCIE_MODEM_RULE_ID_MAX);
918 }
919 else
920 {
921 IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
922 result = false;
923 goto fail;
924 }
925 }
926 }
927
928 ret = ioctl(fd_wwan_ioctl, WAN_IOC_RMV_OFFLOAD_CONNECTION, &qmi_del_msg);
929 if (ret != 0)
930 {
931 IPACMERR("Failed deleting Filtering rule %pK with ret %d\n ", &qmi_del_msg, ret);
932 result = false;
933 goto fail;
934 }
935 }
936 /* update total_num_offload_rules */
937 total_num_offload_rules -= flt_rule_tbl->num_hdls;
938 IPACMDBG_H("total_num_offload_rules %d \n", total_num_offload_rules);
939
940 fail:
941 close(fd_wwan_ioctl);
942 return result;
943 #else
944 if(flt_rule_tbl != NULL)
945 {
946 IPACMERR("Not support (%d) DelOffloadFilteringRule\n", flt_rule_tbl->num_hdls);
947 }
948 return false;
949 #endif
950 }
951
SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01 * table)952 bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table)
953 {
954 int ret = 0;
955 int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
956 if(fd_wwan_ioctl < 0)
957 {
958 IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
959 return false;
960 }
961
962 ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_INDEX, table);
963 if (ret != 0)
964 {
965 IPACMERR("Failed adding filtering rule index %pK with ret %d\n", table, ret);
966 close(fd_wwan_ioctl);
967 return false;
968 }
969
970 IPACMDBG("Added Filtering rule index %pK\n", table);
971 close(fd_wwan_ioctl);
972 return true;
973 }
974
GetQmiFilterAction(ipa_flt_action action)975 ipa_filter_action_enum_v01 IPACM_Filtering::GetQmiFilterAction(ipa_flt_action action)
976 {
977 switch(action)
978 {
979 case IPA_PASS_TO_ROUTING:
980 return QMI_IPA_FILTER_ACTION_ROUTING_V01;
981
982 case IPA_PASS_TO_SRC_NAT:
983 return QMI_IPA_FILTER_ACTION_SRC_NAT_V01;
984
985 case IPA_PASS_TO_DST_NAT:
986 return QMI_IPA_FILTER_ACTION_DST_NAT_V01;
987
988 case IPA_PASS_TO_EXCEPTION:
989 return QMI_IPA_FILTER_ACTION_EXCEPTION_V01;
990
991 default:
992 return IPA_FILTER_ACTION_ENUM_MAX_ENUM_VAL_V01;
993 }
994 }
995
ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule * ruleTable)996 bool IPACM_Filtering::ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable)
997 {
998 int i, ret = 0;
999
1000 IPACMDBG("Printing filtering add attributes\n");
1001 IPACMDBG("IP type: %d Number of rules: %d commit value: %d\n", ruleTable->ip, ruleTable->num_rules, ruleTable->commit);
1002
1003 for (i=0; i<ruleTable->num_rules; i++)
1004 {
1005 IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", i, ruleTable->rules[i].rule.attrib.attrib_mask);
1006 }
1007
1008 ret = ioctl(fd, IPA_IOC_MDFY_FLT_RULE, ruleTable);
1009
1010 for (i = 0; i < ruleTable->num_rules; i++)
1011 {
1012 if (ruleTable->rules[i].status != 0)
1013 {
1014 IPACMERR("Modifying filter rule %d failed\n", i);
1015 }
1016 }
1017
1018 if (ret != 0)
1019 {
1020 IPACMERR("Failed modifying filtering rule IOCTL for %pK\n", ruleTable);
1021 return false;
1022 }
1023
1024 IPACMDBG("Modified filtering rule %p\n", ruleTable);
1025 return true;
1026 }
1027
1028