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