279727efe2e1ca473d92cb7890fcef35db72d229
[samplevnf.git] / common / VIL / acl / lib_acl.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "lib_acl.h"
17 #include "vnf_common.h"
18 #include <rte_port.h>
19 #define ACL_LIB_DEBUG 0
20 static struct rte_acl_field_def field_format_ipv4[] = {
21         /* Protocol */
22         [0] = {
23                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
24                                  .size = sizeof(uint8_t),
25                                  .field_index = 0,
26                                  .input_index = 0,
27                                  .offset = sizeof(struct ether_hdr) +
28                                  offsetof(struct ipv4_hdr, next_proto_id),
29                                  },
30
31         /* Source IP address (IPv4) */
32         [1] = {
33                                  .type = RTE_ACL_FIELD_TYPE_MASK,
34                                  .size = sizeof(uint32_t),
35                                  .field_index = 1,
36                                  .input_index = 1,
37                                  .offset = sizeof(struct ether_hdr) +
38                                  offsetof(struct ipv4_hdr, src_addr),
39                                  },
40
41         /* Destination IP address (IPv4) */
42         [2] = {
43                                  .type = RTE_ACL_FIELD_TYPE_MASK,
44                                  .size = sizeof(uint32_t),
45                                  .field_index = 2,
46                                  .input_index = 2,
47                                  .offset = sizeof(struct ether_hdr) +
48                                  offsetof(struct ipv4_hdr, dst_addr),
49                                  },
50
51         /* Source Port */
52         [3] = {
53                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
54                                  .size = sizeof(uint16_t),
55                                  .field_index = 3,
56                                  .input_index = 3,
57                                  .offset = sizeof(struct ether_hdr) +
58                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
59                                  },
60
61         /* Destination Port */
62         [4] = {
63                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
64                                  .size = sizeof(uint16_t),
65                                  .field_index = 4,
66                                  .input_index = 3,
67                                  .offset = sizeof(struct ether_hdr) +
68                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
69                                  },
70 };
71
72 #define SIZEOF_VLAN_HDR                          4
73
74 static struct rte_acl_field_def field_format_vlan_ipv4[] = {
75         /* Protocol */
76         [0] = {
77                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
78                                  .size = sizeof(uint8_t),
79                                  .field_index = 0,
80                                  .input_index = 0,
81                                  .offset = sizeof(struct ether_hdr) +
82                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, next_proto_id),
83                                  },
84
85         /* Source IP address (IPv4) */
86         [1] = {
87                                  .type = RTE_ACL_FIELD_TYPE_MASK,
88                                  .size = sizeof(uint32_t),
89                                  .field_index = 1,
90                                  .input_index = 1,
91                                  .offset = sizeof(struct ether_hdr) +
92                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, src_addr),
93                                  },
94
95         /* Destination IP address (IPv4) */
96         [2] = {
97                                  .type = RTE_ACL_FIELD_TYPE_MASK,
98                                  .size = sizeof(uint32_t),
99                                  .field_index = 2,
100                                  .input_index = 2,
101                                  .offset = sizeof(struct ether_hdr) +
102                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, dst_addr),
103                                  },
104
105         /* Source Port */
106         [3] = {
107                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
108                                  .size = sizeof(uint16_t),
109                                  .field_index = 3,
110                                  .input_index = 3,
111                                  .offset = sizeof(struct ether_hdr) +
112                                  SIZEOF_VLAN_HDR +
113                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
114                                  },
115
116         /* Destination Port */
117         [4] = {
118                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
119                                  .size = sizeof(uint16_t),
120                                  .field_index = 4,
121                                  .input_index = 4,
122                                  .offset = sizeof(struct ether_hdr) +
123                                  SIZEOF_VLAN_HDR +
124                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
125                                  },
126 };
127
128 #define SIZEOF_QINQ_HEADER                       8
129
130 static struct rte_acl_field_def field_format_qinq_ipv4[] = {
131         /* Protocol */
132         [0] = {
133                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
134                                  .size = sizeof(uint8_t),
135                                  .field_index = 0,
136                                  .input_index = 0,
137                                  .offset = sizeof(struct ether_hdr) +
138                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, next_proto_id),
139                                  },
140
141         /* Source IP address (IPv4) */
142         [1] = {
143                                  .type = RTE_ACL_FIELD_TYPE_MASK,
144                                  .size = sizeof(uint32_t),
145                                  .field_index = 1,
146                                  .input_index = 1,
147                                  .offset = sizeof(struct ether_hdr) +
148                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, src_addr),
149                                  },
150
151         /* Destination IP address (IPv4) */
152         [2] = {
153                                  .type = RTE_ACL_FIELD_TYPE_MASK,
154                                  .size = sizeof(uint32_t),
155                                  .field_index = 2,
156                                  .input_index = 2,
157                                  .offset = sizeof(struct ether_hdr) +
158                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, dst_addr),
159                                  },
160
161         /* Source Port */
162         [3] = {
163                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
164                                  .size = sizeof(uint16_t),
165                                  .field_index = 3,
166                                  .input_index = 3,
167                                  .offset = sizeof(struct ether_hdr) +
168                                  SIZEOF_QINQ_HEADER +
169                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
170                                  },
171
172         /* Destination Port */
173         [4] = {
174                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
175                                  .size = sizeof(uint16_t),
176                                  .field_index = 4,
177                                  .input_index = 4,
178                                  .offset = sizeof(struct ether_hdr) +
179                                  SIZEOF_QINQ_HEADER +
180                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
181                                  },
182 };
183
184 static struct rte_acl_field_def field_format_ipv6[] = {
185         /* Protocol */
186         [0] = {
187                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
188                                  .size = sizeof(uint8_t),
189                                  .field_index = 0,
190                                  .input_index = 0,
191                                  .offset = sizeof(struct ether_hdr) +
192                                  offsetof(struct ipv6_hdr, proto),
193                                  },
194
195         /* Source IP address (IPv6) */
196         [1] = {
197                                  .type = RTE_ACL_FIELD_TYPE_MASK,
198                                  .size = sizeof(uint32_t),
199                                  .field_index = 1,
200                                  .input_index = 1,
201                                  .offset = sizeof(struct ether_hdr) +
202                                  offsetof(struct ipv6_hdr, src_addr),
203                                  },
204
205         [2] = {
206                                  .type = RTE_ACL_FIELD_TYPE_MASK,
207                                  .size = sizeof(uint32_t),
208                                  .field_index = 2,
209                                  .input_index = 2,
210                                  .offset = sizeof(struct ether_hdr) +
211                                  offsetof(struct ipv6_hdr, src_addr) + sizeof(uint32_t),
212                                  },
213
214         [3] = {
215                                  .type = RTE_ACL_FIELD_TYPE_MASK,
216                                  .size = sizeof(uint32_t),
217                                  .field_index = 3,
218                                  .input_index = 3,
219                                  .offset = sizeof(struct ether_hdr) +
220                                  offsetof(struct ipv6_hdr, src_addr) + 2 * sizeof(uint32_t),
221                                  },
222
223         [4] = {
224                                  .type = RTE_ACL_FIELD_TYPE_MASK,
225                                  .size = sizeof(uint32_t),
226                                  .field_index = 4,
227                                  .input_index = 4,
228                                  .offset = sizeof(struct ether_hdr) +
229                                  offsetof(struct ipv6_hdr, src_addr) + 3 * sizeof(uint32_t),
230                                  },
231
232         /* Destination IP address (IPv6) */
233         [5] = {
234                                  .type = RTE_ACL_FIELD_TYPE_MASK,
235                                  .size = sizeof(uint32_t),
236                                  .field_index = 5,
237                                  .input_index = 5,
238                                  .offset = sizeof(struct ether_hdr) +
239                                  offsetof(struct ipv6_hdr, dst_addr),
240                                  },
241
242         [6] = {
243                                  .type = RTE_ACL_FIELD_TYPE_MASK,
244                                  .size = sizeof(uint32_t),
245                                  .field_index = 6,
246                                  .input_index = 6,
247                                  .offset = sizeof(struct ether_hdr) +
248                                  offsetof(struct ipv6_hdr, dst_addr) + sizeof(uint32_t),
249                                  },
250
251         [7] = {
252                                  .type = RTE_ACL_FIELD_TYPE_MASK,
253                                  .size = sizeof(uint32_t),
254                                  .field_index = 7,
255                                  .input_index = 7,
256                                  .offset = sizeof(struct ether_hdr) +
257                                  offsetof(struct ipv6_hdr, dst_addr) + 2 * sizeof(uint32_t),
258                                  },
259
260         [8] = {
261                                  .type = RTE_ACL_FIELD_TYPE_MASK,
262                                  .size = sizeof(uint32_t),
263                                  .field_index = 8,
264                                  .input_index = 8,
265                                  .offset = sizeof(struct ether_hdr) +
266                                  offsetof(struct ipv6_hdr, dst_addr) + 3 * sizeof(uint32_t),
267                                  },
268
269         /* Source Port */
270         [9] = {
271                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
272                                  .size = sizeof(uint16_t),
273                                  .field_index = 9,
274                                  .input_index = 9,
275                                  .offset = sizeof(struct ether_hdr) +
276                                  sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, src_port),
277                                  },
278
279         /* Destination Port */
280         [10] = {
281                 .type = RTE_ACL_FIELD_TYPE_RANGE,
282                 .size = sizeof(uint16_t),
283                 .field_index = 10,
284                 .input_index = 9,
285                 .offset = sizeof(struct ether_hdr) +
286                 sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, dst_port),
287                 },
288 };
289
290 void *lib_acl_create_active_standby_table_ipv4(uint8_t table_num,
291                 uint32_t *libacl_n_rules)
292 {
293         printf("Create LIBACL active IPV4 Tables rte_socket_id(): %i\n",
294                         rte_socket_id());
295
296         /* Create IPV4 LIBACL Rule Tables */
297         struct rte_table_acl_params common_ipv4_table_libacl_params = {
298                 .name = "LIBACLIPV4A",
299                 .n_rules = *libacl_n_rules,
300                 .n_rule_fields = RTE_DIM(field_format_ipv4),
301         };
302
303         memcpy(common_ipv4_table_libacl_params.field_format,
304                         field_format_ipv4, sizeof(field_format_ipv4));
305
306         uint32_t ipv4_entry_size = sizeof(struct lib_acl_table_entry);
307         /* Create second IPV4 Table */
308         if (table_num == 2)
309                 common_ipv4_table_libacl_params.name = "LIBACLIPV4B";
310         return  rte_table_acl_ops.f_create(&common_ipv4_table_libacl_params,
311                         rte_socket_id(),
312                         ipv4_entry_size);
313
314
315 }
316
317 void *lib_acl_create_active_standby_table_ipv6(uint8_t table_num,
318                 uint32_t *libacl_n_rules)
319 {
320         printf("Create LIBACL active IPV6 Tables rte_socket_id(): %i\n",
321                         rte_socket_id());
322         /* Create IPV6 LIBACL Rule Tables */
323         struct rte_table_acl_params common_ipv6_table_libacl_params = {
324                 .name = "LIBACLIPV6A",
325                 .n_rules = *libacl_n_rules,
326                 .n_rule_fields = RTE_DIM(field_format_ipv6),
327         };
328
329         memcpy(common_ipv6_table_libacl_params.field_format,
330                         field_format_ipv6, sizeof(field_format_ipv6));
331
332         uint32_t ipv6_entry_size = sizeof(struct lib_acl_table_entry);
333         /* Create second IPV6 table */
334         if (table_num == 2)
335                 common_ipv6_table_libacl_params.name = "LIBACLIPV6B";
336         return  rte_table_acl_ops.f_create(&common_ipv6_table_libacl_params,
337                         rte_socket_id(),
338                         ipv6_entry_size);
339
340
341 }
342 int lib_acl_parse_config(struct lib_acl *plib_acl,
343                 char *arg_name, char *arg_value,
344                 uint32_t *libacl_n_rules)
345 {
346         uint32_t n_rules_present = 0;
347         uint32_t pkt_type_present = 0;
348         /* defaults */
349         plib_acl->n_rules = DEFULT_NUM_RULE;
350         *libacl_n_rules = DEFULT_NUM_RULE;
351         plib_acl->n_rule_fields = RTE_DIM(field_format_ipv4);
352         plib_acl->field_format = field_format_ipv4;
353         plib_acl->field_format_size = sizeof(field_format_ipv4);
354         if (strcmp(arg_name, "n_rules") == 0) {
355                 if (n_rules_present) {
356                         printf("n_rules_present");
357                         return -1;
358                 }
359                 n_rules_present = 1;
360
361                 plib_acl->n_rules = atoi(arg_value);
362                 *libacl_n_rules = atoi(arg_value);
363                 return 0;
364         }
365         if (strcmp(arg_name, "pkt_type") == 0) {
366                 if (pkt_type_present) {
367                         printf("pkt_type");
368                         return -1;
369                 }
370                 pkt_type_present = 1;
371
372                 /* ipv4 */
373                 if (strcmp(arg_value, "ipv4") == 0) {
374                         plib_acl->n_rule_fields =
375                                 RTE_DIM(field_format_ipv4);
376                         plib_acl->field_format = field_format_ipv4;
377                         plib_acl->field_format_size =
378                                 sizeof(field_format_ipv4);
379                         return 0;
380                 }
381
382                 /* vlan_ipv4 */
383                 if (strcmp(arg_value, "vlan_ipv4") == 0) {
384                         plib_acl->n_rule_fields =
385                                 RTE_DIM(field_format_vlan_ipv4);
386                         plib_acl->field_format =
387                                 field_format_vlan_ipv4;
388                         plib_acl->field_format_size =
389                                 sizeof(field_format_vlan_ipv4);
390                         return 0;
391                 }
392
393                 /* qinq_ipv4 */
394                 if (strcmp(arg_value, "qinq_ipv4") == 0) {
395                         plib_acl->n_rule_fields =
396                                 RTE_DIM(field_format_qinq_ipv4);
397                         plib_acl->field_format =
398                                 field_format_qinq_ipv4;
399                         plib_acl->field_format_size =
400                                 sizeof(field_format_qinq_ipv4);
401                         return 0;
402                 }
403
404                 /* ipv6 */
405                 if (strcmp(arg_value, "ipv6") == 0) {
406                         plib_acl->n_rule_fields =
407                                 RTE_DIM(field_format_ipv6);
408                         plib_acl->field_format = field_format_ipv6;
409                         plib_acl->field_format_size =
410                                 sizeof(field_format_ipv6);
411                         return 0;
412                 }
413                 /* other */
414                 printf("other");
415                 return -1;
416         }
417         /* Parameter not processed in this parse function */
418         return 1;
419 }
420 /**
421  * Main packet processing function.
422  * 64 packet bit mask are used to identify which packets to forward.
423  * Performs the following:
424  *  - Burst lookup packets in the IPv4 ACL Rule Table.
425  *  - Burst lookup packets in the IPv6 ACL Rule Table.
426  *  - Lookup Action Table, perform actions.
427  *  - Burst lookup Connection Tracking, if enabled.
428  *  - Lookup MAC address.
429  *  - Set bit mask.
430  *  - Packets with bit mask set are forwarded
431  *
432  * @param p
433  *  A pointer to the pipeline.
434  * @param pkts
435  *  A pointer to a burst of packets.
436  * @param n_pkts
437  *  Number of packets to process.
438  * @param arg
439  *  A pointer to pipeline specific data.
440  *
441  * @return
442  *  0 on success, negative on error.
443  */
444         uint64_t
445 lib_acl_pkt_work_key(struct lib_acl *plib_acl,
446         struct rte_mbuf **pkts, uint64_t pkts_mask,
447         uint64_t *pkts_drop_without_rule,
448         void *plib_acl_rule_table_ipv4_active,
449         void *plib_acl_rule_table_ipv6_active,
450         struct pipeline_action_key *action_array_active,
451         struct action_counter_block (*p_action_counter_table)[action_array_max],
452         uint64_t *conntrack_mask,
453         uint64_t *connexist_mask,
454         int lib_acl_ipv4_enabled, int lib_acl_ipv6_enabled)
455 {
456
457         uint64_t lookup_hit_mask = 0;
458         uint64_t lookup_hit_mask_ipv4 = 0;
459         uint64_t lookup_hit_mask_ipv6 = 0;
460         uint64_t lookup_miss_mask = 0;
461         int status;
462
463
464         if (lib_acl_ipv4_enabled) {
465                 if (ACL_LIB_DEBUG)
466                         printf("ACL IPV4 Lookup Mask Before = 0x%"PRIx64"\n",
467                                         pkts_mask);
468                 status = rte_table_acl_ops.f_lookup(
469                                 plib_acl_rule_table_ipv4_active,
470                                 pkts, pkts_mask, &lookup_hit_mask_ipv4,
471                                 (void **) plib_acl->plib_acl_entries_ipv4);
472                 if (status < 0)
473                         printf("Lookup failed\n");
474                 if (ACL_LIB_DEBUG)
475                         printf("ACL IPV4 Lookup Mask After = 0x%"PRIx64"\n",
476                                         lookup_hit_mask_ipv4);
477         }
478
479         if (lib_acl_ipv6_enabled) {
480                 if (ACL_LIB_DEBUG)
481                         printf("ACL IPV6 Lookup Mask Before = 0x%"PRIx64"\n",
482                                         pkts_mask);
483                 status = rte_table_acl_ops.f_lookup(
484                                 plib_acl_rule_table_ipv6_active,
485                                 pkts, pkts_mask, &lookup_hit_mask_ipv6,
486                                 (void **) plib_acl->plib_acl_entries_ipv6);
487                 if (status < 0)
488                         printf("Lookup Failed\n");
489                 if (ACL_LIB_DEBUG)
490                         printf("ACL IPV6 Lookup Mask After = 0x%"PRIx64"\n",
491                                         lookup_hit_mask_ipv6);
492         }
493
494         /* Merge lookup results since we process both IPv4 and IPv6 below */
495         lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
496         if (ACL_LIB_DEBUG)
497                 printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
498                                 lookup_hit_mask);
499
500         lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
501         pkts_mask = lookup_hit_mask;
502         *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask);
503         if (ACL_LIB_DEBUG)
504                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
505                                 *pkts_drop_without_rule,
506                                 __builtin_popcountll(lookup_miss_mask));
507         /* bitmap of packets left to process for ARP */
508         uint64_t pkts_to_process = lookup_hit_mask;
509
510         for (; pkts_to_process;) {
511                 uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
512                 /* bitmask representing only this packet */
513                 uint64_t pkt_mask = 1LLU << pos;
514                 /* remove this packet from remaining list */
515                 pkts_to_process &= ~pkt_mask;
516                 struct rte_mbuf *pkt = pkts[pos];
517
518                 uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, IP_START);
519
520                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
521
522                 if (hdr_chk == IPv4_HDR_VERSION) {
523
524                         struct lib_acl_table_entry *entry =
525                                 (struct lib_acl_table_entry *)
526                                 plib_acl->plib_acl_entries_ipv4[pos];
527                         uint16_t phy_port = entry->head.port_id;
528                         uint32_t action_id = entry->action_id;
529
530                         if (ACL_LIB_DEBUG)
531                                 printf("action_id = %u\n", action_id);
532
533                         uint32_t dscp_offset = IP_START + IP_HDR_DSCP_OFST;
534
535                         if (action_array_active[action_id].action_bitmap &
536                                         lib_acl_action_count) {
537                                 p_action_counter_table
538                                         [plib_acl->action_counter_index]
539                                         [action_id].packetCount++;
540                                 p_action_counter_table
541                                         [plib_acl->action_counter_index]
542                                         [action_id].byteCount +=
543                                         rte_pktmbuf_pkt_len(pkt);
544                                 if (ACL_LIB_DEBUG)
545                                         printf("Action Count   Packet Count: %"
546                                                 PRIu64 "  Byte Count: %"
547                                                 PRIu64 "\n"
548                                                 , p_action_counter_table
549                                                 [plib_acl->action_counter_index]
550                                                 [action_id].packetCount,
551                                                 p_action_counter_table
552                                                 [plib_acl->action_counter_index]
553                                                 [action_id].byteCount);
554                         }
555
556                         if (action_array_active[action_id].action_bitmap &
557                                         lib_acl_action_packet_drop) {
558
559                                 /* Drop packet by changing the mask */
560                                 if (ACL_LIB_DEBUG)
561                                         printf("ACL before drop pkt_mask %"
562                                                         PRIx64", pkt_num %d\n",
563                                                         pkts_mask, pos);
564                                 pkts_mask &= ~(1LLU << pos);
565                                 (*pkts_drop_without_rule)++;
566                                 if (ACL_LIB_DEBUG)
567                                         printf("ACL after drop pkt_mask %"PRIx64
568                                                 ", pkt_num %d, packet_drop%"
569                                                 PRIu64"\n", pkts_mask, pos,
570                                                 *pkts_drop_without_rule);
571                         }
572
573                         if (action_array_active[action_id].action_bitmap &
574                                         lib_acl_action_fwd) {
575                                 phy_port = action_array_active[action_id].
576                                         fwd_port;
577                                 entry->head.port_id = phy_port;
578                                 if (ACL_LIB_DEBUG)
579                                         printf("Action FWD  Port ID: %"
580                                                         PRIu16"\n", phy_port);
581                         }
582
583                         if (action_array_active[action_id].action_bitmap &
584                                         lib_acl_action_nat) {
585                                 phy_port = action_array_active[action_id].
586                                         nat_port;
587                                 entry->head.port_id = phy_port;
588                                 if (ACL_LIB_DEBUG)
589                                         printf("Action NAT  Port ID: %"
590                                                         PRIu16"\n", phy_port);
591                         }
592
593                         if (action_array_active[action_id].action_bitmap &
594                                         lib_acl_action_dscp) {
595
596                                 /* Set DSCP priority */
597                                 uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
598                                                 dscp_offset);
599                                 *dscp = action_array_active[action_id].
600                                         dscp_priority << 2;
601                                 if (ACL_LIB_DEBUG)
602                                         printf("Action DSCP   DSCP Priority: %"
603                                                         PRIu16 "\n", *dscp);
604                         }
605
606                         if (action_array_active[action_id].action_bitmap &
607                                         lib_acl_action_packet_accept) {
608                                 if (ACL_LIB_DEBUG)
609                                         printf("Action Accept\n");
610
611                                 if (action_array_active[action_id].action_bitmap
612                                                 & lib_acl_action_conntrack) {
613
614                                         /* Set conntrack bit for this pkt */
615                                         *conntrack_mask |= pkt_mask;
616                                         if (ACL_LIB_DEBUG)
617                                                 printf("ACL CT enabled: 0x%"
618                                                         PRIx64"  pkt_mask: 0x%"
619                                                         PRIx64"\n",
620                                                         *conntrack_mask,
621                                                         pkt_mask);
622                         }
623
624                                 if (action_array_active[action_id].action_bitmap
625                                                 & lib_acl_action_connexist) {
626
627                                         /* Set conntrack bit for this pkt */
628                                         *conntrack_mask |= pkt_mask;
629
630                                         /* Set connexist bit for this pkt for
631                                          * public -> private */
632                                         /* Private -> public packet will open
633                                          * the connection */
634                                         if (action_array_active[action_id].
635                                                         private_public ==
636                                                         lib_acl_public_private)
637                                                 *connexist_mask |= pkt_mask;
638
639                                         if (ACL_LIB_DEBUG)
640                                                 printf("Connexist ENB CT:0x%"
641                                                         PRIx64"  connexist: 0x%"
642                                                         PRIx64"  pkt_mask: 0x%"
643                                                         PRIx64"\n",
644                                                         *conntrack_mask,
645                                                         *connexist_mask,
646                                                         pkt_mask);
647                                 }
648                         }
649                 }
650
651                 if (hdr_chk == IPv6_HDR_VERSION) {
652
653                         struct lib_acl_table_entry *entry =
654                                 (struct lib_acl_table_entry *)
655                                 plib_acl->plib_acl_entries_ipv6[pos];
656                         uint16_t phy_port = entry->head.port_id;
657                         uint32_t action_id = entry->action_id;
658
659                         if (ACL_LIB_DEBUG)
660                                 printf("action_id = %u\n", action_id);
661
662                         if (action_array_active[action_id].action_bitmap &
663                                         lib_acl_action_count) {
664                                 p_action_counter_table
665                                         [plib_acl->action_counter_index]
666                                         [action_id].packetCount++;
667                                 p_action_counter_table
668                                         [plib_acl->action_counter_index]
669                                         [action_id].byteCount +=
670                                         rte_pktmbuf_pkt_len(pkt);
671                                 if (ACL_LIB_DEBUG)
672                                         printf("Action Count   Packet Count: %"
673                                                 PRIu64 "  Byte Count: %"
674                                                 PRIu64 "\n",
675                                                 p_action_counter_table
676                                                 [plib_acl->action_counter_index]
677                                                 [action_id].packetCount,
678                                                 p_action_counter_table
679                                                 [plib_acl->action_counter_index]
680                                                 [action_id].byteCount);
681                         }
682
683                         if (action_array_active[action_id].action_bitmap &
684                                         lib_acl_action_packet_drop) {
685                                 /* Drop packet by changing the mask */
686                                 if (ACL_LIB_DEBUG)
687                                         printf("ACL before drop pkt_mask %"
688                                                         PRIx64", pkt_num %d\n",
689                                                         pkts_mask, pos);
690                                 pkts_mask &= ~(1LLU << pos);
691                                 (*pkts_drop_without_rule)++;
692                                 if (ACL_LIB_DEBUG)
693                                         printf("ACL after drop pkt_mask %"PRIx64
694                                                 ", pkt_num %d, packet_drop %"
695                                                 PRIu64 "\n", pkts_mask, pos,
696                                                 *pkts_drop_without_rule);
697
698                         }
699
700                         if (action_array_active[action_id].action_bitmap &
701                                         lib_acl_action_fwd) {
702                                 phy_port = action_array_active[action_id].
703                                         fwd_port;
704                                 entry->head.port_id = phy_port;
705                                 if (ACL_LIB_DEBUG)
706                                         printf("Action FWD  Port ID: %"
707                                                         PRIu16"\n", phy_port);
708                         }
709
710                         if (action_array_active[action_id].action_bitmap &
711                                         lib_acl_action_nat) {
712                                 phy_port = action_array_active[action_id].
713                                         nat_port;
714                                 entry->head.port_id = phy_port;
715                                 if (ACL_LIB_DEBUG)
716                                         printf("Action NAT  Port ID: %"
717                                                         PRIu16"\n", phy_port);
718                         }
719
720                         if (action_array_active[action_id].action_bitmap &
721                                         lib_acl_action_dscp) {
722
723                                 /* Set DSCP priority */
724                                 uint32_t dscp_offset = IP_START +
725                                         IP_HDR_DSCP_OFST_IPV6;
726                                 uint16_t *dscp = RTE_MBUF_METADATA_UINT16_PTR(
727                                                 pkt, dscp_offset);
728                                 uint16_t temp = *dscp;
729                                 uint16_t dscp_value = (rte_bswap16(temp) &
730                                                 0XF00F);
731                                 uint8_t dscp_store =
732                                         action_array_active
733                                         [action_id].dscp_priority << 2;
734                                 uint16_t dscp_temp = dscp_store;
735
736                                 dscp_temp = dscp_temp << 4;
737                                 *dscp = rte_bswap16(dscp_temp | dscp_value);
738                                 if (ACL_LIB_DEBUG)
739                                         printf("Action DSCP   DSCP Priority: %"
740                                                         PRIu16"\n", *dscp);
741                         }
742
743                         if (action_array_active[action_id].action_bitmap
744                                         & lib_acl_action_packet_accept) {
745                                 if (ACL_LIB_DEBUG)
746                                         printf("Action Accept\n");
747
748                                 if (action_array_active[action_id].action_bitmap
749                                                 & lib_acl_action_conntrack) {
750
751                                         /* Set conntrack bit for this pkt */
752                                         *conntrack_mask |= pkt_mask;
753                                         if (ACL_LIB_DEBUG)
754                                                 printf("ACL CT enabled: 0x%"
755                                                         PRIx64" pkt_mask: 0x%"
756                                                         PRIx64"\n",
757                                                         *conntrack_mask,
758                                                         pkt_mask);
759                                 }
760
761                                 if (action_array_active[action_id].action_bitmap
762                                                 & lib_acl_action_connexist) {
763
764                                         /* Set conntrack bit for this pkt */
765                                         *conntrack_mask |= pkt_mask;
766
767                                         /* Set connexist bit for this pkt for
768                                          * public -> private */
769                                         /* Private -> public packet will open
770                                          * the connection */
771                                         if (action_array_active[action_id].
772                                                         private_public ==
773                                                         lib_acl_public_private)
774                                                 *connexist_mask |= pkt_mask;
775
776                                         if (ACL_LIB_DEBUG)
777                                                 printf("Connexist ENB CT:0x%"
778                                                         PRIx64"  connexist: 0x%"
779                                                         PRIx64"  pkt_mask: 0x%"
780                                                         PRIx64"\n",
781                                                         *conntrack_mask,
782                                                         *connexist_mask,
783                                                         pkt_mask);
784                                 }
785                         }
786                 }
787         }
788         return pkts_mask;
789 }
790 /**
791  * Main packet processing function.
792  * 64 packet bit mask are used to identify which packets to forward.
793  * Performs the following:
794  *  - Burst lookup packets in the IPv4 ACL Rule Table.
795  *  - Lookup Action Table, perform actions.
796  *  - Burst lookup Connection Tracking, if enabled.
797  *  - Lookup MAC address.
798  *  - Set bit mask.
799  *  - Packets with bit mask set are forwarded
800  *
801  * @param p
802  *  A pointer to the pipeline.
803  * @param pkts
804  *  A pointer to a burst of packets.
805  * @param n_pkts
806  *  Number of packets to process.
807  * @param arg
808  *  A pointer to pipeline specific data.
809  *
810  * @return
811  *  0 on success, negative on error.
812  */
813         uint64_t
814 lib_acl_ipv4_pkt_work_key(struct lib_acl *plib_acl,
815         struct rte_mbuf **pkts, uint64_t pkts_mask,
816         uint64_t *pkts_drop_without_rule,
817         void *plib_acl_rule_table_ipv4_active,
818         struct pipeline_action_key *action_array_active,
819         struct action_counter_block (*p_action_counter_table)[action_array_max],
820         uint64_t *conntrack_mask,
821         uint64_t *connexist_mask)
822 {
823
824         uint64_t lookup_hit_mask_ipv4 = 0;
825         uint64_t lookup_miss_mask_ipv4 = 0;
826         int status;
827
828         if (ACL_LIB_DEBUG)
829                 printf("ACL IPV4 Lookup Mask Before = 0x%"PRIx64"\n",
830                                 pkts_mask);
831         status = rte_table_acl_ops.f_lookup(
832                         plib_acl_rule_table_ipv4_active,
833                         pkts, pkts_mask, &lookup_hit_mask_ipv4,
834                         (void **) plib_acl->plib_acl_entries_ipv4);
835         if (status < 0)
836                 printf("Lookup Failed\n");
837         if (ACL_LIB_DEBUG)
838                 printf("ACL IPV4 Lookup Mask After = 0x%"PRIx64"\n",
839                                 lookup_hit_mask_ipv4);
840         if (ACL_LIB_DEBUG)
841                 printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
842                                 lookup_hit_mask_ipv4);
843
844         lookup_miss_mask_ipv4 = pkts_mask & (~lookup_hit_mask_ipv4);
845         pkts_mask = lookup_hit_mask_ipv4;
846         *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv4);
847         if (ACL_LIB_DEBUG)
848                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
849                                 *pkts_drop_without_rule,
850                                 __builtin_popcountll(lookup_miss_mask_ipv4));
851         /* bitmap of packets left to process for ARP */
852         uint64_t pkts_to_process = lookup_hit_mask_ipv4;
853
854         for (; pkts_to_process;) {
855                 uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
856                 /* bitmask representing only this packet */
857                 uint64_t pkt_mask = 1LLU << pos;
858                 /* remove this packet from remaining list */
859                 pkts_to_process &= ~pkt_mask;
860                 struct rte_mbuf *pkt = pkts[pos];
861
862
863
864                 struct lib_acl_table_entry *entry =
865                         (struct lib_acl_table_entry *)
866                         plib_acl->plib_acl_entries_ipv4[pos];
867                 uint16_t phy_port = entry->head.port_id;
868                 uint32_t action_id = entry->action_id;
869
870                 if (ACL_LIB_DEBUG)
871                         printf("action_id = %u\n", action_id);
872
873                 uint32_t dscp_offset = IP_START + IP_HDR_DSCP_OFST;
874
875                 if (action_array_active[action_id].action_bitmap &
876                                 lib_acl_action_count) {
877                         p_action_counter_table
878                                 [plib_acl->action_counter_index]
879                                 [action_id].packetCount++;
880                         p_action_counter_table
881                                 [plib_acl->action_counter_index]
882                                 [action_id].byteCount +=
883                                 rte_pktmbuf_pkt_len(pkt);
884                         if (ACL_LIB_DEBUG)
885                                 printf("Action Count   Packet Count: %"
886                                                 PRIu64 "  Byte Count: %"
887                                                 PRIu64 "\n"
888                                                 , p_action_counter_table
889                                                 [plib_acl->action_counter_index]
890                                                 [action_id].packetCount,
891                                                 p_action_counter_table
892                                                 [plib_acl->action_counter_index]
893                                                 [action_id].byteCount);
894                 }
895
896                 if (action_array_active[action_id].action_bitmap &
897                                 lib_acl_action_packet_drop) {
898
899                         /* Drop packet by changing the mask */
900                         if (ACL_LIB_DEBUG)
901                                 printf("ACL before drop pkt_mask %"
902                                                 PRIx64", pkt_num %d\n",
903                                                 pkts_mask, pos);
904                         pkts_mask &= ~(1LLU << pos);
905                         (*pkts_drop_without_rule)++;
906                         if (ACL_LIB_DEBUG)
907                                 printf("ACL after drop pkt_mask %" PRIx64
908                                         ", pkt_num %d, action_packet_drop %"
909                                         PRIu64 "\n", pkts_mask, pos,
910                                         *pkts_drop_without_rule);
911                 }
912
913                 if (action_array_active[action_id].action_bitmap &
914                                 lib_acl_action_fwd) {
915                         phy_port = action_array_active[action_id].
916                                 fwd_port;
917                         entry->head.port_id = phy_port;
918                         if (ACL_LIB_DEBUG)
919                                 printf("Action FWD  Port ID: %"
920                                                 PRIu16"\n", phy_port);
921                 }
922
923                 if (action_array_active[action_id].action_bitmap &
924                                 lib_acl_action_nat) {
925                         phy_port = action_array_active[action_id].
926                                 nat_port;
927                         entry->head.port_id = phy_port;
928                         if (ACL_LIB_DEBUG)
929                                 printf("Action NAT  Port ID: %"
930                                                 PRIu16"\n", phy_port);
931                 }
932
933                 if (action_array_active[action_id].action_bitmap &
934                                 lib_acl_action_dscp) {
935
936                         /* Set DSCP priority */
937                         uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
938                                         dscp_offset);
939                         *dscp = action_array_active[action_id].
940                                 dscp_priority << 2;
941                         if (ACL_LIB_DEBUG)
942                                 printf("Action DSCP   DSCP Priority: %"
943                                                 PRIu16 "\n", *dscp);
944                 }
945
946                 if (action_array_active[action_id].action_bitmap &
947                                 lib_acl_action_packet_accept) {
948                         if (ACL_LIB_DEBUG)
949                                 printf("Action Accept\n");
950
951                         if (action_array_active[action_id].action_bitmap
952                                         & lib_acl_action_conntrack) {
953
954                                 /* Set conntrack bit for this pkt */
955                                 *conntrack_mask |= pkt_mask;
956                                 if (ACL_LIB_DEBUG)
957                                         printf("ACL CT enabled: 0x%"
958                                                         PRIx64"  pkt_mask: 0x%"
959                                                         PRIx64"\n",
960                                                         *conntrack_mask,
961                                                         pkt_mask);
962                         }
963
964                         if (action_array_active[action_id].action_bitmap
965                                         & lib_acl_action_connexist) {
966
967                                 /* Set conntrack bit for this pkt */
968                                 *conntrack_mask |= pkt_mask;
969
970                                 /* Set connexist bit for this pkt for
971                                  * public -> private */
972                                 /* Private -> public packet will open
973                                  * the connection */
974                                 if (action_array_active[action_id].
975                                                 private_public ==
976                                                 lib_acl_public_private)
977                                         *connexist_mask |= pkt_mask;
978
979                                 if (ACL_LIB_DEBUG)
980                                         printf("ACL Connexist ENB CT:0x%"
981                                                         PRIx64"  connexist: 0x%"
982                                                         PRIx64"  pkt_mask: 0x%"
983                                                         PRIx64"\n",
984                                                         *conntrack_mask,
985                                                         *connexist_mask,
986                                                         pkt_mask);
987                         }
988                 }
989
990         }
991         return pkts_mask;
992 }
993 /**
994  * Main packet processing function.
995  * 64 packet bit mask are used to identify which packets to forward.
996  * Performs the following:
997  *  - Burst lookup packets in the IPv6 ACL Rule Table.
998  *  - Lookup Action Table, perform actions.
999  *  - Burst lookup Connection Tracking, if enabled.
1000  *  - Lookup MAC address.
1001  *  - Set bit mask.
1002  *  - Packets with bit mask set are forwarded
1003  *
1004  * @param p
1005  *  A pointer to the pipeline.
1006  * @param pkts
1007  *  A pointer to a burst of packets.
1008  * @param n_pkts
1009  *  Number of packets to process.
1010  * @param arg
1011  *  A pointer to pipeline specific data.
1012  *
1013  * @return
1014  *  0 on success, negative on error.
1015  */
1016         uint64_t
1017 lib_acl_ipv6_pkt_work_key(struct lib_acl *plib_acl,
1018         struct rte_mbuf **pkts, uint64_t pkts_mask,
1019         uint64_t *pkts_drop_without_rule,
1020         void *plib_acl_rule_table_ipv6_active,
1021         struct pipeline_action_key *action_array_active,
1022         struct action_counter_block (*p_action_counter_table)[action_array_max],
1023         uint64_t *conntrack_mask,
1024         uint64_t *connexist_mask)
1025 {
1026
1027         uint64_t lookup_hit_mask_ipv6 = 0;
1028         uint64_t lookup_miss_mask_ipv6 = 0;
1029         int status;
1030
1031
1032         if (ACL_LIB_DEBUG)
1033                 printf("ACL IPV6 Lookup Mask Before = 0x%"PRIx64"\n",
1034                                 pkts_mask);
1035         status = rte_table_acl_ops.f_lookup(
1036                         plib_acl_rule_table_ipv6_active,
1037                         pkts, pkts_mask, &lookup_hit_mask_ipv6,
1038                         (void **) plib_acl->plib_acl_entries_ipv6);
1039         if (status < 0)
1040                 printf("Lookup Failed\n");
1041         if (ACL_LIB_DEBUG)
1042                 printf("ACL IPV6 Lookup Mask After = 0x%"PRIx64"\n",
1043                                 lookup_hit_mask_ipv6);
1044
1045         if (ACL_LIB_DEBUG)
1046                 printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
1047                                 lookup_hit_mask_ipv6);
1048
1049         lookup_miss_mask_ipv6 = pkts_mask & (~lookup_hit_mask_ipv6);
1050         pkts_mask = lookup_hit_mask_ipv6;
1051         *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv6);
1052         if (ACL_LIB_DEBUG)
1053                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
1054                                 *pkts_drop_without_rule,
1055                                 __builtin_popcountll(lookup_miss_mask_ipv6));
1056         /* bitmap of packets left to process for ARP */
1057         uint64_t pkts_to_process = lookup_hit_mask_ipv6;
1058
1059         for (; pkts_to_process;) {
1060                 uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
1061                 /* bitmask representing only this packet */
1062                 uint64_t pkt_mask = 1LLU << pos;
1063                 /* remove this packet from remaining list */
1064                 pkts_to_process &= ~pkt_mask;
1065                 struct rte_mbuf *pkt = pkts[pos];
1066
1067
1068                 struct lib_acl_table_entry *entry =
1069                         (struct lib_acl_table_entry *)
1070                         plib_acl->plib_acl_entries_ipv6[pos];
1071                 uint16_t phy_port = entry->head.port_id;
1072                 uint32_t action_id = entry->action_id;
1073
1074                 if (ACL_LIB_DEBUG)
1075                         printf("action_id = %u\n", action_id);
1076
1077                 if (action_array_active[action_id].action_bitmap &
1078                                 lib_acl_action_count) {
1079                         p_action_counter_table
1080                                 [plib_acl->action_counter_index]
1081                                 [action_id].packetCount++;
1082                         p_action_counter_table
1083                                 [plib_acl->action_counter_index]
1084                                 [action_id].byteCount +=
1085                                 rte_pktmbuf_pkt_len(pkt);
1086                         if (ACL_LIB_DEBUG)
1087                                 printf("Action Count   Packet Count: %"
1088                                                 PRIu64 "  Byte Count: %"
1089                                                 PRIu64 "\n",
1090                                                 p_action_counter_table
1091                                                 [plib_acl->action_counter_index]
1092                                                 [action_id].packetCount,
1093                                                 p_action_counter_table
1094                                                 [plib_acl->action_counter_index]
1095                                                 [action_id].byteCount);
1096                 }
1097
1098                 if (action_array_active[action_id].action_bitmap &
1099                                 lib_acl_action_packet_drop) {
1100                         /* Drop packet by changing the mask */
1101                         if (ACL_LIB_DEBUG)
1102                                 printf("ACL before drop pkt_mask %"
1103                                                 PRIx64", pkt_num %d\n",
1104                                                 pkts_mask, pos);
1105                         pkts_mask &= ~(1LLU << pos);
1106                         (*pkts_drop_without_rule)++;
1107                         if (ACL_LIB_DEBUG)
1108                                 printf("ACL after drop pkt_mask %" PRIx64
1109                                         ", pkt_num %d, action_packet_drop %"
1110                                         PRIu64 "\n", pkts_mask, pos,
1111                                         *pkts_drop_without_rule);
1112
1113                 }
1114
1115                 if (action_array_active[action_id].action_bitmap &
1116                                 lib_acl_action_fwd) {
1117                         phy_port = action_array_active[action_id].
1118                                 fwd_port;
1119                         entry->head.port_id = phy_port;
1120                         if (ACL_LIB_DEBUG)
1121                                 printf("Action FWD  Port ID: %"
1122                                                 PRIu16"\n", phy_port);
1123                 }
1124
1125                 if (action_array_active[action_id].action_bitmap &
1126                                 lib_acl_action_nat) {
1127                         phy_port = action_array_active[action_id].
1128                                 nat_port;
1129                         entry->head.port_id = phy_port;
1130                         if (ACL_LIB_DEBUG)
1131                                 printf("Action NAT  Port ID: %"
1132                                                 PRIu16"\n", phy_port);
1133                 }
1134
1135                 if (action_array_active[action_id].action_bitmap &
1136                                 lib_acl_action_dscp) {
1137
1138                         /* Set DSCP priority */
1139                         uint32_t dscp_offset = IP_START +
1140                                 IP_HDR_DSCP_OFST_IPV6;
1141                         uint16_t *dscp = RTE_MBUF_METADATA_UINT16_PTR(
1142                                         pkt, dscp_offset);
1143                         uint16_t temp = *dscp;
1144                         uint16_t dscp_value = (rte_bswap16(temp) &
1145                                         0XF00F);
1146                         uint8_t dscp_store =
1147                                 action_array_active
1148                                 [action_id].dscp_priority << 2;
1149                         uint16_t dscp_temp = dscp_store;
1150
1151                         dscp_temp = dscp_temp << 4;
1152                         *dscp = rte_bswap16(dscp_temp | dscp_value);
1153                         if (ACL_LIB_DEBUG)
1154                                 printf("Action DSCP   DSCP Priority: %"
1155                                                 PRIu16"\n", *dscp);
1156                 }
1157
1158                 if (action_array_active[action_id].action_bitmap
1159                                 & lib_acl_action_packet_accept) {
1160                         if (ACL_LIB_DEBUG)
1161                                 printf("Action Accept\n");
1162
1163                         if (action_array_active[action_id].action_bitmap
1164                                         & lib_acl_action_conntrack) {
1165
1166                                 /* Set conntrack bit for this pkt */
1167                                 *conntrack_mask |= pkt_mask;
1168                                 if (ACL_LIB_DEBUG)
1169                                         printf("ACL CT enabled: 0x%"
1170                                                         PRIx64" pkt_mask: 0x%"
1171                                                         PRIx64"\n",
1172                                                         *conntrack_mask,
1173                                                         pkt_mask);
1174                         }
1175
1176                         if (action_array_active[action_id].action_bitmap
1177                                         & lib_acl_action_connexist) {
1178
1179                                 /* Set conntrack bit for this pkt */
1180                                 *conntrack_mask |= pkt_mask;
1181
1182                                 /* Set connexist bit for this pkt for
1183                                  * public -> private */
1184                                 /* Private -> public packet will open
1185                                  * the connection */
1186                                 if (action_array_active[action_id].
1187                                                 private_public ==
1188                                                 lib_acl_public_private)
1189                                         *connexist_mask |= pkt_mask;
1190
1191                                 if (ACL_LIB_DEBUG)
1192                                         printf("ACL Connexist ENB CT:0x%"
1193                                                         PRIx64"  connexist: 0x%"
1194                                                         PRIx64"  pkt_mask: 0x%"
1195                                                         PRIx64"\n",
1196                                                         *conntrack_mask,
1197                                                         *connexist_mask,
1198                                                         pkt_mask);
1199                         }
1200                 }
1201         }
1202         return pkts_mask;
1203 }