FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
acl.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stddef.h>
17 
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <acl/acl.h>
21 
22 #include <vnet/l2/l2_classify.h>
24 #include <vpp/app/version.h>
25 
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28 #include <vlibsocket/api.h>
29 
30 /* define message IDs */
31 #include <acl/acl_msg_enum.h>
32 
33 /* define message structures */
34 #define vl_typedefs
35 #include <acl/acl_all_api_h.h>
36 #undef vl_typedefs
37 
38 /* define generated endian-swappers */
39 #define vl_endianfun
40 #include <acl/acl_all_api_h.h>
41 #undef vl_endianfun
42 
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <acl/acl_all_api_h.h>
47 #undef vl_printfun
48 
49 /* Get the API version number */
50 #define vl_api_version(n,v) static u32 api_version=(v);
51 #include <acl/acl_all_api_h.h>
52 #undef vl_api_version
53 
54 #include "fa_node.h"
55 #include "hash_lookup.h"
56 
58 
59 #define REPLY_MSG_ID_BASE am->msg_id_base
61 
62 /* List of message types that this plugin understands */
63 
64 #define foreach_acl_plugin_api_msg \
65 _(ACL_PLUGIN_GET_VERSION, acl_plugin_get_version) \
66 _(ACL_PLUGIN_CONTROL_PING, acl_plugin_control_ping) \
67 _(ACL_ADD_REPLACE, acl_add_replace) \
68 _(ACL_DEL, acl_del) \
69 _(ACL_INTERFACE_ADD_DEL, acl_interface_add_del) \
70 _(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list) \
71 _(ACL_DUMP, acl_dump) \
72 _(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump) \
73 _(MACIP_ACL_ADD, macip_acl_add) \
74 _(MACIP_ACL_DEL, macip_acl_del) \
75 _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
76 _(MACIP_ACL_DUMP, macip_acl_dump) \
77 _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get)
78 
79 /* *INDENT-OFF* */
81  .version = VPP_BUILD_VER,
82  .description = "Access Control Lists",
83 };
84 /* *INDENT-ON* */
85 
86 
87 static void *
89 {
90  if (0 == am->acl_mheap) {
91  am->acl_mheap = mheap_alloc (0 /* use VM */ , 2 << 29);
92  mheap_t *h = mheap_header (am->acl_mheap);
94  }
95  void *oldheap = clib_mem_set_heap(am->acl_mheap);
96  return oldheap;
97 }
98 
99 void
101 {
103  mheap_t *h = mheap_header (am->acl_mheap);
104  if (on) {
107  mheap_validate(h);
108  } else {
109  h->flags &= ~MHEAP_FLAG_VALIDATE;
111  }
112 }
113 
114 void
116 {
118  mheap_t *h = mheap_header (am->acl_mheap);
119  if (on) {
120  h->flags |= MHEAP_FLAG_TRACE;
121  } else {
122  h->flags &= ~MHEAP_FLAG_TRACE;
123  }
124 }
125 
126 static void
128 {
129  acl_main_t *am = &acl_main;
131  int msg_size = sizeof (*rmp);
133 
135  if (q == 0)
136  {
137  return;
138  }
139 
140  rmp = vl_msg_api_alloc (msg_size);
141  memset (rmp, 0, msg_size);
142  rmp->_vl_msg_id =
143  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
144  rmp->context = mp->context;
145  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
146  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
147 
148  vl_msg_api_send_shmem (q, (u8 *) & rmp);
149 }
150 
151 static void
153 {
155  acl_main_t *am = &acl_main;
156  int rv = 0;
157 
158  /* *INDENT-OFF* */
159  REPLY_MACRO2 (VL_API_ACL_PLUGIN_CONTROL_PING_REPLY,
160  ({
161  rmp->vpe_pid = ntohl (getpid ());
162  }));
163  /* *INDENT-ON* */
164 }
165 
166 static int
168  u32 * acl_list_index, u8 * tag)
169 {
170  acl_main_t *am = &acl_main;
171  acl_list_t *a;
172  acl_rule_t *r;
173  acl_rule_t *acl_new_rules = 0;
174  int i;
175 
176  if (*acl_list_index != ~0)
177  {
178  /* They supplied some number, let's see if this ACL exists */
179  if (pool_is_free_index (am->acls, *acl_list_index))
180  {
181  /* tried to replace a non-existent ACL, no point doing anything */
182  clib_warning("acl-plugin-error: Trying to replace nonexistent ACL %d (tag %s)", *acl_list_index, tag);
183  return -1;
184  }
185  }
186  if (0 == count) {
187  clib_warning("acl-plugin-warning: supplied no rules for ACL %d (tag %s)", *acl_list_index, tag);
188  }
189 
190  void *oldheap = acl_set_heap(am);
191 
192  /* Create and populate the rules */
193  if (count > 0)
194  vec_validate(acl_new_rules, count-1);
195 
196  for (i = 0; i < count; i++)
197  {
198  r = vec_elt_at_index(acl_new_rules, i);
199  memset(r, 0, sizeof(*r));
200  r->is_permit = rules[i].is_permit;
201  r->is_ipv6 = rules[i].is_ipv6;
202  if (r->is_ipv6)
203  {
204  memcpy (&r->src, rules[i].src_ip_addr, sizeof (r->src));
205  memcpy (&r->dst, rules[i].dst_ip_addr, sizeof (r->dst));
206  }
207  else
208  {
209  memcpy (&r->src.ip4, rules[i].src_ip_addr, sizeof (r->src.ip4));
210  memcpy (&r->dst.ip4, rules[i].dst_ip_addr, sizeof (r->dst.ip4));
211  }
212  r->src_prefixlen = rules[i].src_ip_prefix_len;
213  r->dst_prefixlen = rules[i].dst_ip_prefix_len;
214  r->proto = rules[i].proto;
215  r->src_port_or_type_first = ntohs ( rules[i].srcport_or_icmptype_first );
216  r->src_port_or_type_last = ntohs ( rules[i].srcport_or_icmptype_last );
217  r->dst_port_or_code_first = ntohs ( rules[i].dstport_or_icmpcode_first );
218  r->dst_port_or_code_last = ntohs ( rules[i].dstport_or_icmpcode_last );
219  r->tcp_flags_value = rules[i].tcp_flags_value;
220  r->tcp_flags_mask = rules[i].tcp_flags_mask;
221  }
222 
223  if (~0 == *acl_list_index)
224  {
225  /* Get ACL index */
227  memset (a, 0, sizeof (*a));
228  /* Will return the newly allocated ACL index */
229  *acl_list_index = a - am->acls;
230  }
231  else
232  {
233  a = am->acls + *acl_list_index;
234  hash_acl_delete(am, *acl_list_index);
235  /* Get rid of the old rules */
236  if (a->rules)
237  vec_free (a->rules);
238  }
239  a->rules = acl_new_rules;
240  a->count = count;
241  memcpy (a->tag, tag, sizeof (a->tag));
242  hash_acl_add(am, *acl_list_index);
243  clib_mem_set_heap (oldheap);
244  return 0;
245 }
246 
247 static int
248 acl_del_list (u32 acl_list_index)
249 {
250  acl_main_t *am = &acl_main;
251  acl_list_t *a;
252  int i, ii;
253  if (pool_is_free_index (am->acls, acl_list_index))
254  {
255  return -1;
256  }
257 
258  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
259  if (vec_len(am->input_sw_if_index_vec_by_acl[acl_list_index]) > 0) {
260  /* ACL is applied somewhere inbound. Refuse to delete */
261  return -1;
262  }
263  }
264  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
265  if (vec_len(am->output_sw_if_index_vec_by_acl[acl_list_index]) > 0) {
266  /* ACL is applied somewhere outbound. Refuse to delete */
267  return -1;
268  }
269  }
270 
271  void *oldheap = acl_set_heap(am);
272  /* delete any references to the ACL */
273  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index); i++)
274  {
275  for (ii = 0; ii < vec_len (am->output_acl_vec_by_sw_if_index[i]);
276  /* see body */ )
277  {
278  if (acl_list_index == am->output_acl_vec_by_sw_if_index[i][ii])
279  {
281  }
282  else
283  {
284  ii++;
285  }
286  }
287  }
288  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index); i++)
289  {
290  for (ii = 0; ii < vec_len (am->input_acl_vec_by_sw_if_index[i]);
291  /* see body */ )
292  {
293  if (acl_list_index == am->input_acl_vec_by_sw_if_index[i][ii])
294  {
296  }
297  else
298  {
299  ii++;
300  }
301  }
302  }
303  /* delete the hash table data */
304 
305  hash_acl_delete(am, acl_list_index);
306  /* now we can delete the ACL itself */
307  a = &am->acls[acl_list_index];
308  if (a->rules)
309  vec_free (a->rules);
310 
311  pool_put (am->acls, a);
312  clib_mem_set_heap (oldheap);
313  return 0;
314 }
315 
316 /* Some aids in ASCII graphing the content */
317 #define XX "\377"
318 #define __ "\000"
319 #define _(x)
320 #define v
321 
323 _(" dmac smac etype ")
324 _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
325  _(" v ihl totlen ")
326  _(0x0000)
327  __ __ __ __
328  _(" ident fl+fo ")
329  _(0x0004)
330  __ __ __ __
331  _(" ttl pr checksum ")
332  _(0x0008)
333  __ XX __ __
334  _(" src address ")
335  _(0x000C)
336  XX XX XX XX
337  _(" dst address ")
338  _(0x0010)
339  XX XX XX XX
340  _("L4 T/U sport dport ")
341  _(tcpudp)
342  XX XX XX XX
343  _(padpad)
344  __ __ __ __
345  _(padpad)
346  __ __ __ __
347  _(padeth)
348  __ __;
349 
351  _(" dmac smac etype ")
352  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
353  _(" v tc + flow ")
354  _(0x0000) __ __ __ __
355  _(" plen nh hl ")
356  _(0x0004) __ __ XX __
357  _(" src address ")
358  _(0x0008) XX XX XX XX
359  _(0x000C) XX XX XX XX
360  _(0x0010) XX XX XX XX
361  _(0x0014) XX XX XX XX
362  _(" dst address ")
363  _(0x0018) XX XX XX XX
364  _(0x001C) XX XX XX XX
365  _(0x0020) XX XX XX XX
366  _(0x0024) XX XX XX XX
367  _("L4T/U sport dport ")
368  _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
369 
370 #undef XX
371 #undef __
372 #undef _
373 #undef v
374 
375  static int count_skip (u8 * p, u32 size)
376 {
377  u64 *p64 = (u64 *) p;
378  /* Be tolerant to null pointer */
379  if (0 == p)
380  return 0;
381 
382  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
383  {
384  p64++;
385  }
386  return (p64 - (u64 *) p) / 2;
387 }
388 
389 static int
391  u32 mask_len, u32 next_table_index,
392  u32 miss_next_index, u32 * table_index,
393  int is_add)
394 {
395  u32 nbuckets = 1;
396  u32 memory_size = 2 << 13;
397  u32 skip = count_skip (mask, mask_len);
398  u32 match = (mask_len / 16) - skip;
399  u8 *skip_mask_ptr = mask + 16 * skip;
400  u32 current_data_flag = 0;
401  int current_data_offset = 0;
402 
403  if (0 == match)
404  match = 1;
405  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
406  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
407  memory_size, skip, match,
408  next_table_index, miss_next_index,
409  table_index, current_data_flag,
410  current_data_offset, is_add,
411  1 /* delete_chain */);
412  clib_mem_set_heap (oldheap);
413  return ret;
414 }
415 
416 static int
418  u32 mask_len, u32 next_table_index,
419  u32 miss_next_index, u32 * table_index,
420  int is_add)
421 {
422  u32 nbuckets = 32;
423  u32 memory_size = 2 << 20;
424  u32 skip = count_skip (mask, mask_len);
425  u32 match = (mask_len / 16) - skip;
426  u8 *skip_mask_ptr = mask + 16 * skip;
427  u32 current_data_flag = 0;
428  int current_data_offset = 0;
429 
430  if (0 == match)
431  match = 1;
432 
433  void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
434  int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
435  memory_size, skip, match,
436  next_table_index, miss_next_index,
437  table_index, current_data_flag,
438  current_data_offset, is_add,
439  1 /* delete_chain */);
440  clib_mem_set_heap (oldheap);
441  return ret;
442 }
443 
444 
445 static int
447 {
449  u32 ip4_table_index = ~0;
450  u32 ip6_table_index = ~0;
451  void *oldheap = acl_set_heap(am);
452 
454  sw_if_index, ~0);
456  sw_if_index, ~0);
457 
458  /* switch to global heap while calling vnet_* functions */
459  clib_mem_set_heap (cm->vlib_main->heap_base);
460  vnet_l2_input_classify_enable_disable (sw_if_index, 0);
461 
462  if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
463  {
464  ip4_table_index =
466  am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
467  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
468  sizeof (ip4_5tuple_mask) - 1, ~0,
470  &ip4_table_index, 0);
471  }
472  if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
473  {
474  ip6_table_index =
476  am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
478  sizeof (ip6_5tuple_mask) - 1, ~0,
480  &ip6_table_index, 0);
481  }
482  clib_mem_set_heap (oldheap);
483  return 0;
484 }
485 
486 static int
488 {
490  u32 ip4_table_index = ~0;
491  u32 ip6_table_index = ~0;
492  void *oldheap = acl_set_heap(am);
493 
495  sw_if_index, ~0);
497  sw_if_index, ~0);
498 
499  /* switch to global heap while calling vnet_* functions */
500  clib_mem_set_heap (cm->vlib_main->heap_base);
501 
503 
504  if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
505  {
506  ip4_table_index =
508  am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
509  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
510  sizeof (ip4_5tuple_mask) - 1, ~0,
512  &ip4_table_index, 0);
513  }
514  if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
515  {
516  ip6_table_index =
518  am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
520  sizeof (ip6_5tuple_mask) - 1, ~0,
522  &ip6_table_index, 0);
523  }
524  clib_mem_set_heap (oldheap);
525  return 0;
526 }
527 
528 static int
530 {
532  u32 ip4_table_index = ~0;
533  u32 ip6_table_index = ~0;
534  int rv;
535 
536  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
537 
538  /* in case there were previous tables attached */
539  acl_unhook_l2_input_classify (am, sw_if_index);
540  rv =
541  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
542  sizeof (ip4_5tuple_mask) - 1, ~0,
544  &ip4_table_index, 1);
545  if (rv)
546  goto done;
547  rv =
549  sizeof (ip6_5tuple_mask) - 1, ~0,
551  &ip6_table_index, 1);
552  if (rv)
553  {
554  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
555  sizeof (ip4_5tuple_mask) - 1, ~0,
557  &ip4_table_index, 0);
558  goto done;
559  }
560  rv =
561  vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
562  ip6_table_index, ~0);
564  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
565  sw_if_index, ip4_table_index, ip6_table_index);
566  if (rv)
567  {
569  sizeof (ip6_5tuple_mask) - 1, ~0,
571  &ip6_table_index, 0);
572  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
573  sizeof (ip4_5tuple_mask) - 1, ~0,
575  &ip4_table_index, 0);
576  goto done;
577  }
578 
580  ip4_table_index;
582  ip6_table_index;
583 
584  vnet_l2_input_classify_enable_disable (sw_if_index, 1);
585 done:
586  clib_mem_set_heap (prevheap);
587  return rv;
588 }
589 
590 static int
592 {
594  u32 ip4_table_index = ~0;
595  u32 ip6_table_index = ~0;
596  int rv;
597 
598  void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
599 
600  /* in case there were previous tables attached */
601  acl_unhook_l2_output_classify (am, sw_if_index);
602  rv =
603  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
604  sizeof (ip4_5tuple_mask) - 1, ~0,
606  &ip4_table_index, 1);
607  if (rv)
608  goto done;
609  rv =
611  sizeof (ip6_5tuple_mask) - 1, ~0,
613  &ip6_table_index, 1);
614  if (rv)
615  {
616  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
617  sizeof (ip4_5tuple_mask) - 1, ~0,
619  &ip4_table_index, 0);
620  goto done;
621  }
622  rv =
623  vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
624  ip6_table_index, ~0);
626  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
627  sw_if_index, ip4_table_index, ip6_table_index);
628  if (rv)
629  {
631  sizeof (ip6_5tuple_mask) - 1, ~0,
633  &ip6_table_index, 0);
634  acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
635  sizeof (ip4_5tuple_mask) - 1, ~0,
637  &ip4_table_index, 0);
638  goto done;
639  }
640 
642  ip4_table_index;
644  ip6_table_index;
645 
647 done:
648  clib_mem_set_heap (prevheap);
649  return rv;
650 }
651 
652 
653 
654 int
656  int enable_disable)
657 {
658  int rv;
659 
660  /* Utterly wrong? */
662  sw_if_index))
663  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
664 
665  acl_fa_enable_disable(sw_if_index, 1, enable_disable);
666 
667  if (enable_disable)
668  {
669  rv = acl_hook_l2_input_classify (am, sw_if_index);
670  }
671  else
672  {
673  rv = acl_unhook_l2_input_classify (am, sw_if_index);
674  }
675 
676  return rv;
677 }
678 
679 int
681  int enable_disable)
682 {
683  int rv;
684 
685  /* Utterly wrong? */
687  sw_if_index))
688  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
689 
690  acl_fa_enable_disable(sw_if_index, 0, enable_disable);
691 
692  if (enable_disable)
693  {
694  rv = acl_hook_l2_output_classify (am, sw_if_index);
695  }
696  else
697  {
698  rv = acl_unhook_l2_output_classify (am, sw_if_index);
699  }
700 
701  return rv;
702 }
703 
704 static int
705 acl_is_not_defined(acl_main_t *am, u32 acl_list_index)
706 {
707  return (pool_is_free_index (am->acls, acl_list_index));
708 }
709 
710 
711 static int
712 acl_interface_add_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
713 {
714  acl_main_t *am = &acl_main;
715  if (acl_is_not_defined(am, acl_list_index)) {
716  /* ACL is not defined. Can not apply */
717  return -1;
718  }
719  void *oldheap = acl_set_heap(am);
720 
721  if (is_input)
722  {
723  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
724 
725  u32 index = vec_search(am->input_acl_vec_by_sw_if_index[sw_if_index], acl_list_index);
726  if (index < vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index])) {
727  clib_warning("ACL %d is already applied inbound on sw_if_index %d (index %d)",
728  acl_list_index, sw_if_index, index);
729  /* the entry is already there */
730  clib_mem_set_heap (oldheap);
731  return -1;
732  }
733  /* if there was no ACL applied before, enable the ACL processing */
734  if (vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index]) == 0) {
735  acl_interface_in_enable_disable (am, sw_if_index, 1);
736  }
737  vec_add (am->input_acl_vec_by_sw_if_index[sw_if_index], &acl_list_index,
738  1);
739  vec_validate (am->input_sw_if_index_vec_by_acl, acl_list_index);
740  vec_add (am->input_sw_if_index_vec_by_acl[acl_list_index], &sw_if_index,
741  1);
742  }
743  else
744  {
745  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
746 
747  u32 index = vec_search(am->output_acl_vec_by_sw_if_index[sw_if_index], acl_list_index);
748  if (index < vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index])) {
749  clib_warning("ACL %d is already applied outbound on sw_if_index %d (index %d)",
750  acl_list_index, sw_if_index, index);
751  /* the entry is already there */
752  clib_mem_set_heap (oldheap);
753  return -1;
754  }
755  /* if there was no ACL applied before, enable the ACL processing */
756  if (vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index]) == 0) {
757  acl_interface_out_enable_disable (am, sw_if_index, 1);
758  }
759  vec_add (am->output_acl_vec_by_sw_if_index[sw_if_index],
760  &acl_list_index, 1);
761  vec_validate (am->output_sw_if_index_vec_by_acl, acl_list_index);
762  vec_add (am->output_sw_if_index_vec_by_acl[acl_list_index], &sw_if_index,
763  1);
764  }
765  clib_mem_set_heap (oldheap);
766  return 0;
767 }
768 
769 
770 static int
771 acl_interface_del_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
772 {
773  acl_main_t *am = &acl_main;
774  int i;
775  int rv = -1;
776  void *oldheap = acl_set_heap(am);
777  if (is_input)
778  {
779  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
780  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
781  i++)
782  {
783  if (acl_list_index ==
784  am->input_acl_vec_by_sw_if_index[sw_if_index][i])
785  {
786  vec_del1 (am->input_acl_vec_by_sw_if_index[sw_if_index], i);
787  rv = 0;
788  break;
789  }
790  }
791 
792  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
793  u32 index = vec_search(am->input_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
794  if (index < vec_len(am->input_sw_if_index_vec_by_acl[acl_list_index])) {
795  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
796  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index], index);
797  }
798  }
799 
800  /* If there is no more ACLs applied on an interface, disable ACL processing */
801  if (0 == vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
802  {
803  acl_interface_in_enable_disable (am, sw_if_index, 0);
804  }
805  }
806  else
807  {
808  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
809  for (i = 0;
810  i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]); i++)
811  {
812  if (acl_list_index ==
813  am->output_acl_vec_by_sw_if_index[sw_if_index][i])
814  {
815  vec_del1 (am->output_acl_vec_by_sw_if_index[sw_if_index], i);
816  rv = 0;
817  break;
818  }
819  }
820 
821  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
822  u32 index = vec_search(am->output_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
823  if (index < vec_len(am->output_sw_if_index_vec_by_acl[acl_list_index])) {
824  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
825  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index], index);
826  }
827  }
828 
829  /* If there is no more ACLs applied on an interface, disable ACL processing */
830  if (0 == vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
831  {
832  acl_interface_out_enable_disable (am, sw_if_index, 0);
833  }
834  }
835  clib_mem_set_heap (oldheap);
836  return rv;
837 }
838 
839 static void
840 acl_interface_reset_inout_acls (u32 sw_if_index, u8 is_input)
841 {
842  acl_main_t *am = &acl_main;
843  int i;
844  void *oldheap = acl_set_heap(am);
845  if (is_input)
846  {
847  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
848  if (vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0) {
849  acl_interface_in_enable_disable (am, sw_if_index, 0);
850  }
851 
852  for(i = vec_len(am->input_acl_vec_by_sw_if_index[sw_if_index])-1; i>=0; i--) {
853  u32 acl_list_index = am->input_acl_vec_by_sw_if_index[sw_if_index][i];
854  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
855  if (acl_list_index < vec_len(am->input_sw_if_index_vec_by_acl)) {
856  u32 index = vec_search(am->input_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
857  if (index < vec_len(am->input_sw_if_index_vec_by_acl[acl_list_index])) {
858  vec_del1 (am->input_sw_if_index_vec_by_acl[acl_list_index], index);
859  }
860  }
861  }
862 
864  }
865  else
866  {
867  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
868  if (vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0) {
869  acl_interface_out_enable_disable (am, sw_if_index, 0);
870  }
871 
872  for(i = vec_len(am->output_acl_vec_by_sw_if_index[sw_if_index])-1; i>=0; i--) {
873  u32 acl_list_index = am->output_acl_vec_by_sw_if_index[sw_if_index][i];
874  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
875  if (acl_list_index < vec_len(am->output_sw_if_index_vec_by_acl)) {
876  u32 index = vec_search(am->output_sw_if_index_vec_by_acl[acl_list_index], sw_if_index);
877  if (index < vec_len(am->output_sw_if_index_vec_by_acl[acl_list_index])) {
878  vec_del1 (am->output_sw_if_index_vec_by_acl[acl_list_index], index);
879  }
880  }
881  }
882 
884  }
885  clib_mem_set_heap (oldheap);
886 }
887 
888 static int
889 acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
890  u32 acl_list_index)
891 {
892  int rv = -1;
893  acl_main_t *am = &acl_main;
894  void *oldheap = acl_set_heap(am);
895  if (is_add)
896  {
897  rv =
898  acl_interface_add_inout_acl (sw_if_index, is_input, acl_list_index);
899  if (rv == 0)
900  {
901  hash_acl_apply(am, sw_if_index, is_input, acl_list_index);
902  }
903  }
904  else
905  {
906  hash_acl_unapply(am, sw_if_index, is_input, acl_list_index);
907  rv =
908  acl_interface_del_inout_acl (sw_if_index, is_input, acl_list_index);
909  }
910  clib_mem_set_heap (oldheap);
911  return rv;
912 }
913 
914 
915 typedef struct
916 {
918  u8 mac_mask[6];
924 
925 static u32
926 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
927  u8 is_ipv6)
928 {
929  u32 i;
930  if (mv)
931  {
932  for (i = 0; i < vec_len (mv); i++)
933  {
934  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
935  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
936  {
937  return i;
938  }
939  }
940  }
941  return ~0;
942 }
943 
944 
945 /* Get metric used to sort match types.
946  The more specific and the more often seen - the bigger the metric */
947 static int
949 {
950  /* FIXME: count the ones in the MAC mask as well, check how well this heuristic works in real life */
951  return m->prefix_len + m->is_ipv6 + 10 * m->count;
952 }
953 
954 static int
956 {
957  /* Ascending sort based on the metric values */
958  return match_type_metric (m1) - match_type_metric (m2);
959 }
960 
961 /* Get the offset of L3 source within ethernet packet */
962 static int
964 {
965  if(is6)
966  return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
967  else
968  return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
969 }
970 
971 static int
973 {
974  macip_match_type_t *mvec = NULL;
975  macip_match_type_t *mt;
976  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
977  int i;
978  u32 match_type_index;
979  u32 last_table;
980  u8 mask[5 * 16];
982 
983  /* Count the number of different types of rules */
984  for (i = 0; i < a->count; i++)
985  {
986  if (~0 ==
987  (match_type_index =
989  a->rules[i].src_prefixlen,
990  a->rules[i].is_ipv6)))
991  {
992  match_type_index = vec_len (mvec);
993  vec_validate (mvec, match_type_index);
994  memcpy (mvec[match_type_index].mac_mask,
995  a->rules[match_type_index].src_mac_mask, 6);
996  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
997  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
998  mvec[match_type_index].table_index = ~0;
999  }
1000  mvec[match_type_index].count++;
1001  }
1002  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1004  /* Create the classifier tables */
1005  last_table = ~0;
1006  /* First add ARP tables */
1007  vec_foreach (mt, mvec)
1008  {
1009  int mask_len;
1010  int is6 = mt->is_ipv6;
1011 
1012  mt->arp_table_index = ~0;
1013  if (!is6)
1014  {
1015  memset (mask, 0, sizeof (mask));
1016  memcpy (&mask[6], mt->mac_mask, 6);
1017  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1018  memcpy (&mask[14 + 8], mt->mac_mask, 6);
1019 
1020  for (i = 0; i < (mt->prefix_len / 8); i++)
1021  mask[14 + 14 + i] = 0xff;
1022  if (mt->prefix_len % 8)
1023  mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1024 
1025  mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
1026  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1027  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1028  (~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
1029  1);
1030  last_table = mt->arp_table_index;
1031  }
1032  }
1033  /* Now add IP[46] tables */
1034  vec_foreach (mt, mvec)
1035  {
1036  int mask_len;
1037  int is6 = mt->is_ipv6;
1038  int l3_src_offs = get_l3_src_offset(is6);
1039  memset (mask, 0, sizeof (mask));
1040  memcpy (&mask[6], mt->mac_mask, 6);
1041  for (i = 0; i < (mt->prefix_len / 8); i++)
1042  {
1043  mask[l3_src_offs + i] = 0xff;
1044  }
1045  if (mt->prefix_len % 8)
1046  {
1047  mask[l3_src_offs + (mt->prefix_len / 8)] =
1048  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1049  }
1050  /*
1051  * Round-up the number of bytes needed to store the prefix,
1052  * and round up the number of vectors too
1053  */
1054  mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
1055  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1056  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1057  (~0 == last_table) ? 0 : ~0, &mt->table_index,
1058  1);
1059  last_table = mt->table_index;
1060  }
1061  a->ip4_table_index = ~0;
1062  a->ip6_table_index = ~0;
1063  a->l2_table_index = last_table;
1064 
1065  /* Populate the classifier tables with rules from the MACIP ACL */
1066  for (i = 0; i < a->count; i++)
1067  {
1068  u32 action = 0;
1069  u32 metadata = 0;
1070  int is6 = a->rules[i].is_ipv6;
1071  int l3_src_offs = get_l3_src_offset(is6);
1072  memset (mask, 0, sizeof (mask));
1073  memcpy (&mask[6], a->rules[i].src_mac, 6);
1074  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1075  if (is6)
1076  {
1077  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1078  mask[12] = 0x86;
1079  mask[13] = 0xdd;
1080  }
1081  else
1082  {
1083  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1084  mask[12] = 0x08;
1085  mask[13] = 0x00;
1086  }
1087  match_type_index =
1089  a->rules[i].src_prefixlen,
1090  a->rules[i].is_ipv6);
1091  ASSERT(match_type_index != ~0);
1092  /* add session to table mvec[match_type_index].table_index; */
1093  vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
1094  mask, a->rules[i].is_permit ? ~0 : 0, i,
1095  0, action, metadata, 1);
1096  /* add ARP table entry too */
1097  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1098  {
1099  memset (mask, 0, sizeof (mask));
1100  memcpy (&mask[6], a->rules[i].src_mac, 6);
1101  mask[12] = 0x08;
1102  mask[13] = 0x06;
1103  memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
1104  memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
1105  vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
1106  mask, a->rules[i].is_permit ? ~0 : 0, i,
1107  0, action, metadata, 1);
1108  }
1109  }
1110  return 0;
1111 }
1112 
1113 static void
1115 {
1117  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
1118 
1119  if (a->ip4_table_index != ~0)
1120  {
1121  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip4_table_index, 0);
1122  a->ip4_table_index = ~0;
1123  }
1124  if (a->ip6_table_index != ~0)
1125  {
1126  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip6_table_index, 0);
1127  a->ip6_table_index = ~0;
1128  }
1129  if (a->l2_table_index != ~0)
1130  {
1131  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index, 0);
1132  a->l2_table_index = ~0;
1133  }
1134 }
1135 
1136 static int
1138  u32 * acl_list_index, u8 * tag)
1139 {
1140  acl_main_t *am = &acl_main;
1142  macip_acl_rule_t *r;
1143  macip_acl_rule_t *acl_new_rules = 0;
1144  int i;
1145  if (0 == count) {
1146  clib_warning("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)", tag);
1147  }
1148  void *oldheap = acl_set_heap(am);
1149  /* Create and populate the rules */
1150  if (count > 0)
1151  vec_validate(acl_new_rules, count-1);
1152 
1153  for (i = 0; i < count; i++)
1154  {
1155  r = &acl_new_rules[i];
1156  r->is_permit = rules[i].is_permit;
1157  r->is_ipv6 = rules[i].is_ipv6;
1158  memcpy (&r->src_mac, rules[i].src_mac, 6);
1159  memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
1160  if(rules[i].is_ipv6)
1161  memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
1162  else
1163  memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
1164  r->src_prefixlen = rules[i].src_ip_prefix_len;
1165  }
1166 
1167  /* Get ACL index */
1169  memset (a, 0, sizeof (*a));
1170  /* Will return the newly allocated ACL index */
1171  *acl_list_index = a - am->macip_acls;
1172 
1173  a->rules = acl_new_rules;
1174  a->count = count;
1175  memcpy (a->tag, tag, sizeof (a->tag));
1176 
1177  /* Create and populate the classifer tables */
1178  macip_create_classify_tables (am, *acl_list_index);
1179  clib_mem_set_heap (oldheap);
1180  return 0;
1181 }
1182 
1183 
1184 /* No check for validity of sw_if_index - the callers were supposed to validate */
1185 
1186 static int
1188 {
1189  int rv;
1190  u32 macip_acl_index;
1192  void *oldheap = acl_set_heap(am);
1193  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1194  clib_mem_set_heap (oldheap);
1195  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1196  /* No point in deleting MACIP ACL which is not applied */
1197  if (~0 == macip_acl_index)
1198  return -1;
1199  a = &am->macip_acls[macip_acl_index];
1200  /* remove the classifier tables off the interface L2 ACL */
1201  rv =
1202  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1203  a->ip6_table_index, a->l2_table_index, 0);
1204  /* Unset the MACIP ACL index */
1205  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
1206  return rv;
1207 }
1208 
1209 /* No check for validity of sw_if_index - the callers were supposed to validate */
1210 
1211 static int
1213  u32 macip_acl_index)
1214 {
1216  int rv;
1217  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1218  {
1219  return -1;
1220  }
1221  void *oldheap = acl_set_heap(am);
1222  a = &am->macip_acls[macip_acl_index];
1223  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1224  /* If there already a MACIP ACL applied, unapply it */
1225  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1226  macip_acl_interface_del_acl(am, sw_if_index);
1227  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1228  clib_mem_set_heap (oldheap);
1229 
1230  /* Apply the classifier tables for L2 ACLs */
1231  rv =
1232  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1233  a->ip6_table_index, a->l2_table_index, 1);
1234  return rv;
1235 }
1236 
1237 static int
1238 macip_acl_del_list (u32 acl_list_index)
1239 {
1240  acl_main_t *am = &acl_main;
1241  void *oldheap = acl_set_heap(am);
1243  int i;
1244  if (pool_is_free_index (am->macip_acls, acl_list_index))
1245  {
1246  return -1;
1247  }
1248 
1249  /* delete any references to the ACL */
1250  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1251  {
1252  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1253  {
1255  }
1256  }
1257 
1258  /* Now that classifier tables are detached, clean them up */
1259  macip_destroy_classify_tables (am, acl_list_index);
1260 
1261  /* now we can delete the ACL itself */
1262  a = &am->macip_acls[acl_list_index];
1263  if (a->rules)
1264  {
1265  vec_free (a->rules);
1266  }
1267  pool_put (am->macip_acls, a);
1268  clib_mem_set_heap (oldheap);
1269  return 0;
1270 }
1271 
1272 
1273 static int
1275  u32 acl_list_index)
1276 {
1277  acl_main_t *am = &acl_main;
1278  void *oldheap = acl_set_heap(am);
1279  int rv = -1;
1280  if (is_add)
1281  {
1282  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1283  }
1284  else
1285  {
1286  rv = macip_acl_interface_del_acl (am, sw_if_index);
1287  }
1288  clib_mem_set_heap (oldheap);
1289  return rv;
1290 }
1291 
1292 /*
1293  * If the client does not allocate enough memory for a variable-length
1294  * message, and then proceed to use it as if the full memory allocated,
1295  * absent the check we happily consume that on the VPP side, and go
1296  * along as if nothing happened. However, the resulting
1297  * effects range from just garbage in the API decode
1298  * (because the decoder snoops too far), to potential memory
1299  * corruptions.
1300  *
1301  * This verifies that the actual length of the message is
1302  * at least expected_len, and complains loudly if it is not.
1303  *
1304  * A failing check here is 100% a software bug on the API user side,
1305  * so we might as well yell.
1306  *
1307  */
1308 static int verify_message_len(void *mp, u32 expected_len, char *where)
1309 {
1310  u32 supplied_len = vl_msg_api_get_msg_length (mp);
1311  if (supplied_len < expected_len) {
1312  clib_warning("%s: Supplied message length %d is less than expected %d",
1313  where, supplied_len, expected_len);
1314  return 0;
1315  } else {
1316  return 1;
1317  }
1318 }
1319 
1320 /* API message handler */
1321 static void
1323 {
1325  acl_main_t *am = &acl_main;
1326  int rv;
1327  u32 acl_list_index = ntohl (mp->acl_index);
1328  u32 acl_count = ntohl (mp->count);
1329  u32 expected_len = sizeof(*mp) + acl_count*sizeof(mp->r[0]);
1330 
1331  if (verify_message_len(mp, expected_len, "acl_add_replace")) {
1332  rv = acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1333  } else {
1334  rv = VNET_API_ERROR_INVALID_VALUE;
1335  }
1336 
1337  /* *INDENT-OFF* */
1338  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1339  ({
1340  rmp->acl_index = htonl(acl_list_index);
1341  }));
1342  /* *INDENT-ON* */
1343 }
1344 
1345 static void
1347 {
1348  acl_main_t *am = &acl_main;
1349  vl_api_acl_del_reply_t *rmp;
1350  int rv;
1351 
1352  rv = acl_del_list (ntohl (mp->acl_index));
1353 
1354  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1355 }
1356 
1357 static void
1359 {
1360  acl_main_t *am = &acl_main;
1362  u32 sw_if_index = ntohl (mp->sw_if_index);
1363  vl_api_acl_interface_add_del_reply_t *rmp;
1364  int rv = -1;
1365 
1366  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1367  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1368  else
1369  rv =
1370  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1371  mp->is_input, ntohl (mp->acl_index));
1372 
1373  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1374 }
1375 
1376 static void
1379 {
1380  acl_main_t *am = &acl_main;
1381  vl_api_acl_interface_set_acl_list_reply_t *rmp;
1382  int rv = 0;
1383  int i;
1385  u32 sw_if_index = ntohl (mp->sw_if_index);
1386 
1387  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1388  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1389  else
1390  {
1391  acl_interface_reset_inout_acls (sw_if_index, 0);
1392  acl_interface_reset_inout_acls (sw_if_index, 1);
1393 
1394  for (i = 0; i < mp->count; i++)
1395  {
1396  if(acl_is_not_defined(am, ntohl (mp->acls[i]))) {
1397  /* ACL does not exist, so we can not apply it */
1398  rv = -1;
1399  }
1400  }
1401  if (0 == rv) {
1402  for (i = 0; i < mp->count; i++)
1403  {
1404  acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
1405  ntohl (mp->acls[i]));
1406  }
1407  }
1408  }
1409 
1410  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1411 }
1412 
1413 static void
1415 {
1416  api_rule->is_permit = r->is_permit;
1417  api_rule->is_ipv6 = r->is_ipv6;
1418  if(r->is_ipv6)
1419  {
1420  memcpy (api_rule->src_ip_addr, &r->src, sizeof (r->src));
1421  memcpy (api_rule->dst_ip_addr, &r->dst, sizeof (r->dst));
1422  }
1423  else
1424  {
1425  memcpy (api_rule->src_ip_addr, &r->src.ip4, sizeof (r->src.ip4));
1426  memcpy (api_rule->dst_ip_addr, &r->dst.ip4, sizeof (r->dst.ip4));
1427  }
1428  api_rule->src_ip_prefix_len = r->src_prefixlen;
1429  api_rule->dst_ip_prefix_len = r->dst_prefixlen;
1430  api_rule->proto = r->proto;
1431  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1432  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1433  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1434  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1435  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1436  api_rule->tcp_flags_value = r->tcp_flags_value;
1437 }
1438 
1439 static void
1441  acl_list_t * acl, u32 context)
1442 {
1444  vl_api_acl_rule_t *rules;
1445  int i;
1446  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * acl->count;
1447  void *oldheap = acl_set_heap(am);
1448 
1449  mp = vl_msg_api_alloc (msg_size);
1450  memset (mp, 0, msg_size);
1451  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
1452 
1453  /* fill in the message */
1454  mp->context = context;
1455  mp->count = htonl (acl->count);
1456  mp->acl_index = htonl (acl - am->acls);
1457  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1458  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
1459  rules = mp->r;
1460  for (i = 0; i < acl->count; i++)
1461  {
1462  copy_acl_rule_to_api_rule (&rules[i], &acl->rules[i]);
1463  }
1464 
1465  clib_warning("Sending acl details for ACL index %d", ntohl(mp->acl_index));
1466  clib_mem_set_heap (oldheap);
1467  vl_msg_api_send_shmem (q, (u8 *) & mp);
1468 }
1469 
1470 
1471 static void
1473 {
1474  acl_main_t *am = &acl_main;
1475  u32 acl_index;
1476  acl_list_t *acl;
1477 
1478  int rv = -1;
1480 
1482  if (q == 0)
1483  {
1484  return;
1485  }
1486 
1487  if (mp->acl_index == ~0)
1488  {
1489  /* *INDENT-OFF* */
1490  /* Just dump all ACLs */
1491  pool_foreach (acl, am->acls,
1492  ({
1493  send_acl_details(am, q, acl, mp->context);
1494  }));
1495  /* *INDENT-ON* */
1496  }
1497  else
1498  {
1499  acl_index = ntohl (mp->acl_index);
1500  if (!pool_is_free_index (am->acls, acl_index))
1501  {
1502  acl = &am->acls[acl_index];
1503  send_acl_details (am, q, acl, mp->context);
1504  }
1505  }
1506 
1507  if (rv == -1)
1508  {
1509  /* FIXME API: should we signal an error here at all ? */
1510  return;
1511  }
1512 }
1513 
1514 static void
1517  u32 sw_if_index, u32 context)
1518 {
1520  int msg_size;
1521  int n_input;
1522  int n_output;
1523  int count;
1524  int i = 0;
1525  void *oldheap = acl_set_heap(am);
1526 
1527  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1528  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1529 
1530  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1531  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1532  count = n_input + n_output;
1533 
1534  msg_size = sizeof (*mp);
1535  msg_size += sizeof (mp->acls[0]) * count;
1536 
1537  mp = vl_msg_api_alloc (msg_size);
1538  memset (mp, 0, msg_size);
1539  mp->_vl_msg_id =
1540  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1541 
1542  /* fill in the message */
1543  mp->context = context;
1544  mp->sw_if_index = htonl (sw_if_index);
1545  mp->count = count;
1546  mp->n_input = n_input;
1547  for (i = 0; i < n_input; i++)
1548  {
1549  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
1550  }
1551  for (i = 0; i < n_output; i++)
1552  {
1553  mp->acls[n_input + i] =
1554  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
1555  }
1556  clib_mem_set_heap (oldheap);
1557  vl_msg_api_send_shmem (q, (u8 *) & mp);
1558 }
1559 
1560 static void
1562  mp)
1563 {
1564  acl_main_t *am = &acl_main;
1565  vnet_sw_interface_t *swif;
1567 
1568  u32 sw_if_index;
1570 
1572  if (q == 0)
1573  {
1574  return;
1575  }
1576 
1577  if (mp->sw_if_index == ~0)
1578  {
1579  /* *INDENT-OFF* */
1580  pool_foreach (swif, im->sw_interfaces,
1581  ({
1582  send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
1583  }));
1584  /* *INDENT-ON* */
1585  }
1586  else
1587  {
1588  sw_if_index = ntohl (mp->sw_if_index);
1589  if (!pool_is_free_index(im->sw_interfaces, sw_if_index))
1590  send_acl_interface_list_details (am, q, sw_if_index, mp->context);
1591  }
1592 }
1593 
1594 /* MACIP ACL API handlers */
1595 
1596 static void
1598 {
1600  acl_main_t *am = &acl_main;
1601  int rv;
1602  u32 acl_list_index = ~0;
1603  u32 acl_count = ntohl (mp->count);
1604  u32 expected_len = sizeof(*mp) + acl_count*sizeof(mp->r[0]);
1605 
1606  if (verify_message_len(mp, expected_len, "macip_acl_add")) {
1607  rv = macip_acl_add_list (acl_count, mp->r, &acl_list_index, mp->tag);
1608  } else {
1609  rv = VNET_API_ERROR_INVALID_VALUE;
1610  }
1611 
1612  /* *INDENT-OFF* */
1613  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
1614  ({
1615  rmp->acl_index = htonl(acl_list_index);
1616  }));
1617  /* *INDENT-ON* */
1618 }
1619 
1620 static void
1622 {
1623  acl_main_t *am = &acl_main;
1624  vl_api_macip_acl_del_reply_t *rmp;
1625  int rv;
1626 
1627  rv = macip_acl_del_list (ntohl (mp->acl_index));
1628 
1629  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
1630 }
1631 
1632 static void
1635 {
1636  acl_main_t *am = &acl_main;
1637  vl_api_macip_acl_interface_add_del_reply_t *rmp;
1638  int rv = -1;
1640  u32 sw_if_index = ntohl (mp->sw_if_index);
1641 
1642  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1643  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1644  else
1645  rv =
1647  ntohl (mp->acl_index));
1648 
1649  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
1650 }
1651 
1652 static void
1654  macip_acl_list_t * acl, u32 context)
1655 {
1657  vl_api_macip_acl_rule_t *rules;
1658  macip_acl_rule_t *r;
1659  int i;
1660  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
1661 
1662  mp = vl_msg_api_alloc (msg_size);
1663  memset (mp, 0, msg_size);
1664  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
1665 
1666  /* fill in the message */
1667  mp->context = context;
1668  if (acl)
1669  {
1670  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1671  mp->count = htonl (acl->count);
1672  mp->acl_index = htonl (acl - am->macip_acls);
1673  rules = mp->r;
1674  for (i = 0; i < acl->count; i++)
1675  {
1676  r = &acl->rules[i];
1677  rules[i].is_permit = r->is_permit;
1678  rules[i].is_ipv6 = r->is_ipv6;
1679  memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
1680  memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
1681  sizeof (r->src_mac_mask));
1682  if (r->is_ipv6)
1683  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
1684  sizeof (r->src_ip_addr.ip6));
1685  else
1686  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
1687  sizeof (r->src_ip_addr.ip4));
1688  rules[i].src_ip_prefix_len = r->src_prefixlen;
1689  }
1690  }
1691  else
1692  {
1693  /* No martini, no party - no ACL applied to this interface. */
1694  mp->acl_index = ~0;
1695  mp->count = 0;
1696  }
1697 
1698  vl_msg_api_send_shmem (q, (u8 *) & mp);
1699 }
1700 
1701 
1702 static void
1704 {
1705  acl_main_t *am = &acl_main;
1706  macip_acl_list_t *acl;
1707 
1709 
1711  if (q == 0)
1712  {
1713  return;
1714  }
1715 
1716  if (mp->acl_index == ~0)
1717  {
1718  /* Just dump all ACLs for now, with sw_if_index = ~0 */
1719  pool_foreach (acl, am->macip_acls, (
1720  {
1721  send_macip_acl_details (am, q, acl,
1722  mp->
1723  context);}
1724  ));
1725  /* *INDENT-ON* */
1726  }
1727  else
1728  {
1729  u32 acl_index = ntohl (mp->acl_index);
1730  if (!pool_is_free_index (am->macip_acls, acl_index))
1731  {
1732  acl = &am->macip_acls[acl_index];
1733  send_macip_acl_details (am, q, acl, mp->context);
1734  }
1735  }
1736 }
1737 
1738 static void
1740  mp)
1741 {
1742  acl_main_t *am = &acl_main;
1744  u32 count = vec_len (am->macip_acl_by_sw_if_index);
1745  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
1747  int i;
1748 
1750  if (q == 0)
1751  {
1752  return;
1753  }
1754 
1755  rmp = vl_msg_api_alloc (msg_size);
1756  memset (rmp, 0, msg_size);
1757  rmp->_vl_msg_id =
1758  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
1759  rmp->context = mp->context;
1760  rmp->count = htonl (count);
1761  for (i = 0; i < count; i++)
1762  {
1763  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
1764  }
1765 
1766  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1767 }
1768 
1769 /* Set up the API message handling tables */
1770 static clib_error_t *
1772 {
1773  acl_main_t *am = &acl_main;
1774 #define _(N,n) \
1775  vl_msg_api_set_handlers((VL_API_##N + am->msg_id_base), \
1776  #n, \
1777  vl_api_##n##_t_handler, \
1778  vl_noop_handler, \
1779  vl_api_##n##_t_endian, \
1780  vl_api_##n##_t_print, \
1781  sizeof(vl_api_##n##_t), 1);
1783 #undef _
1784 
1785  return 0;
1786 }
1787 
1788 #define vl_msg_name_crc_list
1789 #include <acl/acl_all_api_h.h>
1790 #undef vl_msg_name_crc_list
1791 
1792 static void
1794 {
1795 #define _(id,n,crc) \
1796  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + am->msg_id_base);
1797  foreach_vl_msg_name_crc_acl;
1798 #undef _
1799 }
1800 
1801 static void
1803 {
1804  vlib_main_t *vm = vlib_get_main ();
1805  acl_main_t *am = &acl_main;
1806  vlib_node_t *n, *n4, *n6;
1807 
1808  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
1809  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip4-l2");
1810  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip6-l2");
1811 
1812 
1814  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1816  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1817 
1821 
1825 
1826 
1827  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
1828  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip4-l2");
1829  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip6-l2");
1830 
1832  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1834  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1835 
1839 
1843 }
1844 
1845 static void
1846 acl_set_timeout_sec(int timeout_type, u32 value)
1847 {
1848  acl_main_t *am = &acl_main;
1849  clib_time_t *ct = &am->vlib_main->clib_time;
1850 
1851  if (timeout_type < ACL_N_TIMEOUTS) {
1852  am->session_timeout_sec[timeout_type] = value;
1853  } else {
1854  clib_warning("Unknown timeout type %d", timeout_type);
1855  return;
1856  }
1857  am->session_timeout[timeout_type] = (u64)(((f64)value)/ct->seconds_per_clock);
1858 }
1859 
1860 static void
1862 {
1863  acl_main_t *am = &acl_main;
1864  am->fa_conn_table_max_entries = value;
1865 }
1866 
1867 static int
1869 {
1870  acl_main_t *am = &acl_main;
1871 
1872  if ((eh < 256) && (value < 2))
1873  {
1875  return 1;
1876  }
1877  else
1878  return 0;
1879 }
1880 
1881 
1882 static clib_error_t *
1883 acl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
1884 {
1885  acl_main_t *am = &acl_main;
1886  if (0 == is_add) {
1889  /* also unapply any ACLs in case the users did not do so. */
1890  macip_acl_interface_del_acl(am, sw_if_index);
1891  acl_interface_reset_inout_acls (sw_if_index, 0);
1892  acl_interface_reset_inout_acls (sw_if_index, 1);
1893  }
1894  return 0;
1895 }
1896 
1898 
1899 
1900 
1901 static clib_error_t *
1903  unformat_input_t * input,
1904  vlib_cli_command_t * cmd)
1905 {
1906  clib_error_t *error = 0;
1907  u32 timeout = 0;
1908  u32 val = 0;
1909  u32 eh_val = 0;
1910  uword memory_size = 0;
1911  acl_main_t *am = &acl_main;
1912 
1913  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val)) {
1914  if(!acl_set_skip_ipv6_eh(eh_val, val)) {
1915  error = clib_error_return(0, "expecting eh=0..255, value=0..1");
1916  }
1917  goto done;
1918  }
1919  if (unformat (input, "use-hash-acl-matching %u", &val))
1920  {
1921  am->use_hash_acl_matching = (val !=0);
1922  goto done;
1923  }
1924  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
1925  {
1926  am->l4_match_nonfirst_fragment = (val != 0);
1927  goto done;
1928  }
1929  if (unformat (input, "heap"))
1930  {
1931  if (unformat(input, "main"))
1932  {
1933  if (unformat(input, "validate %u", &val))
1935  else if (unformat(input, "trace %u", &val))
1937  goto done;
1938  }
1939  else if (unformat(input, "hash"))
1940  {
1941  if (unformat(input, "validate %u", &val))
1943  else if (unformat(input, "trace %u", &val))
1945  goto done;
1946  }
1947  goto done;
1948  }
1949  if (unformat (input, "session")) {
1950  if (unformat (input, "table")) {
1951  /* The commands here are for tuning/testing. No user-serviceable parts inside */
1952  if (unformat (input, "max-entries")) {
1953  if (!unformat(input, "%u", &val)) {
1954  error = clib_error_return(0,
1955  "expecting maximum number of entries, got `%U`",
1956  format_unformat_error, input);
1957  goto done;
1958  } else {
1960  goto done;
1961  }
1962  }
1963  if (unformat (input, "hash-table-buckets")) {
1964  if (!unformat(input, "%u", &val)) {
1965  error = clib_error_return(0,
1966  "expecting maximum number of hash table buckets, got `%U`",
1967  format_unformat_error, input);
1968  goto done;
1969  } else {
1971  goto done;
1972  }
1973  }
1974  if (unformat (input, "hash-table-memory")) {
1975  if (!unformat(input, "%U", unformat_memory_size, &memory_size)) {
1976  error = clib_error_return(0,
1977  "expecting maximum amount of hash table memory, got `%U`",
1978  format_unformat_error, input);
1979  goto done;
1980  } else {
1982  goto done;
1983  }
1984  }
1985  goto done;
1986  }
1987  if (unformat (input, "timeout")) {
1988  if (unformat(input, "udp")) {
1989  if(unformat(input, "idle")) {
1990  if (!unformat(input, "%u", &timeout)) {
1991  error = clib_error_return(0,
1992  "expecting timeout value in seconds, got `%U`",
1993  format_unformat_error, input);
1994  goto done;
1995  } else {
1997  goto done;
1998  }
1999  }
2000  }
2001  if (unformat(input, "tcp")) {
2002  if(unformat(input, "idle")) {
2003  if (!unformat(input, "%u", &timeout)) {
2004  error = clib_error_return(0,
2005  "expecting timeout value in seconds, got `%U`",
2006  format_unformat_error, input);
2007  goto done;
2008  } else {
2010  goto done;
2011  }
2012  }
2013  if(unformat(input, "transient")) {
2014  if (!unformat(input, "%u", &timeout)) {
2015  error = clib_error_return(0,
2016  "expecting timeout value in seconds, got `%U`",
2017  format_unformat_error, input);
2018  goto done;
2019  } else {
2021  goto done;
2022  }
2023  }
2024  }
2025  goto done;
2026  }
2027  }
2028 done:
2029  return error;
2030 }
2031 
2032 static u8 *
2033 my_format_mac_address (u8 * s, va_list * args)
2034 {
2035  u8 *a = va_arg (*args, u8 *);
2036  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
2037  a[0], a[1], a[2], a[3], a[4], a[5]);
2038 }
2039 
2040 static inline u8 *
2042 {
2043  macip_acl_rule_t *a = va_arg (*args, macip_acl_rule_t *);
2044 
2045  out = format(out, "%s action %d ip %U/%d mac %U mask %U",
2046  a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
2048  a->src_prefixlen,
2051  return(out);
2052 }
2053 
2054 static void
2055 macip_acl_print(acl_main_t *am, u32 macip_acl_index)
2056 {
2057  vlib_main_t * vm = am->vlib_main;
2058  int i;
2059 
2060  /* Don't try to print someone else's memory */
2061  if (macip_acl_index > vec_len(am->macip_acls))
2062  return;
2063 
2064  macip_acl_list_t *a = vec_elt_at_index(am->macip_acls, macip_acl_index);
2065  int free_pool_slot = pool_is_free_index(am->macip_acls, macip_acl_index);
2066 
2067  vlib_cli_output(vm, "MACIP acl_index: %d, count: %d (true len %d) tag {%s} is free pool slot: %d\n",
2068  macip_acl_index, a->count, vec_len(a->rules), a->tag, free_pool_slot);
2069  vlib_cli_output(vm, " ip4_table_index %d, ip6_table_index %d, l2_table_index %d\n",
2071  for(i=0; i<vec_len(a->rules); i++)
2072  vlib_cli_output(vm, " rule %d: %U\n", i, my_macip_acl_rule_t_pretty_format,
2073  vec_elt_at_index(a->rules, i));
2074 
2075 }
2076 
2077 static clib_error_t *
2079  unformat_input_t * input,
2080  vlib_cli_command_t * cmd)
2081 {
2082  clib_error_t *error = 0;
2083  acl_main_t *am = &acl_main;
2084  int i;
2085  if (unformat (input, "interface"))
2086  {
2087  for(i=0; i < vec_len(am->macip_acl_by_sw_if_index); i++)
2088  {
2089  vlib_cli_output(vm, " sw_if_index %d: %d\n", i, vec_elt(am->macip_acl_by_sw_if_index, i));
2090  }
2091  }
2092  else if (unformat (input, "acl"))
2093  {
2094  for(i=0; i < vec_len(am->macip_acls); i++)
2095  macip_acl_print(am, i);
2096  }
2097  return error;
2098 }
2099 
2100 
2101 static clib_error_t *
2103  unformat_input_t * input,
2104  vlib_cli_command_t * cmd)
2105 {
2106  clib_error_t *error = 0;
2107  acl_main_t *am = &acl_main;
2109  u32 *pj;
2110 
2111  vnet_sw_interface_t *swif;
2112 
2113  if (unformat (input, "sessions"))
2114  {
2115  u8 * out0 = format(0, "");
2116  u16 wk;
2117  u32 show_bihash_verbose = 0;
2118  u32 show_session_thread_id = ~0;
2119  u32 show_session_session_index = ~0;
2120  unformat (input, "thread %u index %u", &show_session_thread_id, &show_session_session_index);
2121  unformat (input, "verbose %u", &show_bihash_verbose);
2122  {
2123  u64 n_adds = am->fa_session_total_adds;
2124  u64 n_dels = am->fa_session_total_dels;
2125  out0 = format(out0, "Sessions total: add %lu - del %lu = %lu\n", n_adds, n_dels, n_adds - n_dels);
2126  }
2127  out0 = format(out0, "\n\nPer-thread data:\n");
2128  for (wk = 0; wk < vec_len (am->per_worker_data); wk++) {
2130  out0 = format(out0, "Thread #%d:\n", wk);
2131  if (show_session_thread_id == wk && show_session_session_index < pool_len(pw->fa_sessions_pool)) {
2132  out0 = format(out0, " session index %u:\n", show_session_session_index);
2133  fa_session_t *sess = pw->fa_sessions_pool + show_session_session_index;
2134  u64 *m = (u64 *)&sess->info;
2135  out0 = format(out0, " info: %016llx %016llx %016llx %016llx %016llx %016llx\n", m[0], m[1], m[2], m[3], m[4], m[5]);
2136  out0 = format(out0, " sw_if_index: %u\n", sess->sw_if_index);
2137  out0 = format(out0, " tcp_flags_seen: %x\n", sess->tcp_flags_seen.as_u16);
2138  out0 = format(out0, " last active time: %lu\n", sess->last_active_time);
2139  out0 = format(out0, " thread index: %u\n", sess->thread_index);
2140  out0 = format(out0, " link enqueue time: %lu\n", sess->link_enqueue_time);
2141  out0 = format(out0, " link next index: %u\n", sess->link_next_idx);
2142  out0 = format(out0, " link prev index: %u\n", sess->link_prev_idx);
2143  out0 = format(out0, " link list id: %u\n", sess->link_list_id);
2144  }
2145  out0 = format(out0, " connection add/del stats:\n", wk);
2146  pool_foreach (swif, im->sw_interfaces,
2147  ({
2148  u32 sw_if_index = swif->sw_if_index;
2149  u64 n_adds = sw_if_index < vec_len(pw->fa_session_adds_by_sw_if_index) ? pw->fa_session_adds_by_sw_if_index[sw_if_index] : 0;
2150  u64 n_dels = sw_if_index < vec_len(pw->fa_session_dels_by_sw_if_index) ? pw->fa_session_dels_by_sw_if_index[sw_if_index] : 0;
2151  out0 = format(out0, " sw_if_index %d: add %lu - del %lu = %lu\n", sw_if_index, n_adds, n_dels, n_adds - n_dels);
2152  }));
2153 
2154  out0 = format(out0, " connection timeout type lists:\n", wk);
2155  u8 tt = 0;
2156  for(tt = 0; tt < ACL_N_TIMEOUTS; tt++) {
2157  u32 head_session_index = pw->fa_conn_list_head[tt];
2158  out0 = format(out0, " fa_conn_list_head[%d]: %d\n", tt, head_session_index);
2159  if (~0 != head_session_index) {
2160  fa_session_t *sess = pw->fa_sessions_pool + head_session_index;
2161  out0 = format(out0, " last active time: %lu\n", sess->last_active_time);
2162  out0 = format(out0, " link enqueue time: %lu\n", sess->link_enqueue_time);
2163  }
2164  }
2165 
2166  out0 = format(out0, " Next expiry time: %lu\n", pw->next_expiry_time);
2167  out0 = format(out0, " Requeue until time: %lu\n", pw->requeue_until_time);
2168  out0 = format(out0, " Current time wait interval: %lu\n", pw->current_time_wait_interval);
2169  out0 = format(out0, " Count of deleted sessions: %lu\n", pw->cnt_deleted_sessions);
2170  out0 = format(out0, " Delete already deleted: %lu\n", pw->cnt_already_deleted_sessions);
2171  out0 = format(out0, " Session timers restarted: %lu\n", pw->cnt_session_timer_restarted);
2172  out0 = format(out0, " Swipe until this time: %lu\n", pw->swipe_end_time);
2173  out0 = format(out0, " sw_if_index serviced bitmap: %U\n", format_bitmap_hex, pw->serviced_sw_if_index_bitmap);
2174  out0 = format(out0, " pending clear intfc bitmap : %U\n", format_bitmap_hex, pw->pending_clear_sw_if_index_bitmap);
2175  out0 = format(out0, " clear in progress: %u\n", pw->clear_in_process);
2176  out0 = format(out0, " interrupt is pending: %d\n", pw->interrupt_is_pending);
2177  out0 = format(out0, " interrupt is needed: %d\n", pw->interrupt_is_needed);
2178  out0 = format(out0, " interrupt is unwanted: %d\n", pw->interrupt_is_unwanted);
2179  out0 = format(out0, " interrupt generation: %d\n", pw->interrupt_generation);
2180  }
2181  out0 = format(out0, "\n\nConn cleaner thread counters:\n");
2182 #define _(cnt, desc) out0 = format(out0, " %20lu: %s\n", am->cnt, desc);
2184 #undef _
2185  vec_terminate_c_string(out0);
2186  vlib_cli_output(vm, "\n\n%s\n\n", out0);
2187  vlib_cli_output(vm, "Interrupt generation: %d\n", am->fa_interrupt_generation);
2188  vlib_cli_output(vm, "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
2191 
2192  vec_free(out0);
2193  show_fa_sessions_hash(vm, show_bihash_verbose);
2194  }
2195  else if (unformat (input, "interface"))
2196  {
2197  u32 sw_if_index = ~0;
2198  u32 swi;
2199  u8 * out0 = format(0, "");
2200  unformat (input, "sw_if_index %u", &sw_if_index);
2201  for(swi = 0; (swi < vec_len(am->input_acl_vec_by_sw_if_index)) ||
2202  (swi < vec_len(am->output_acl_vec_by_sw_if_index)); swi++) {
2203  out0 = format(out0, "sw_if_index %d:\n", swi);
2204 
2205  if ((swi < vec_len(am->input_acl_vec_by_sw_if_index)) &&
2206  (vec_len(am->input_acl_vec_by_sw_if_index[swi]) > 0)) {
2207  out0 = format(out0, " input acl(s): ");
2209  out0 = format(out0, "%d ", *pj);
2210  }
2211  out0 = format(out0, "\n");
2212  }
2213 
2214  if ((swi < vec_len(am->output_acl_vec_by_sw_if_index)) &&
2215  (vec_len(am->output_acl_vec_by_sw_if_index[swi]) > 0)) {
2216  out0 = format(out0, " output acl(s): ");
2218  out0 = format(out0, "%d ", *pj);
2219  }
2220  out0 = format(out0, "\n");
2221  }
2222 
2223  }
2224  vec_terminate_c_string(out0);
2225  vlib_cli_output(vm, "\n%s\n", out0);
2226  vec_free(out0);
2227  }
2228  else if (unformat (input, "acl"))
2229  {
2230  u32 acl_index = ~0;
2231  u32 i;
2232  u8 * out0 = format(0, "");
2233  unformat (input, "index %u", &acl_index);
2234  for(i=0; i<vec_len(am->acls); i++) {
2235  if (acl_is_not_defined(am, i)) {
2236  /* don't attempt to show the ACLs that do not exist */
2237  continue;
2238  }
2239  if ((acl_index != ~0) && (acl_index != i)) {
2240  continue;
2241  }
2242  out0 = format(out0, "acl-index %u count %u tag {%s}\n", i, am->acls[i].count, am->acls[i].tag);
2243  acl_rule_t *r;
2244  int j;
2245  for(j=0; j<am->acls[i].count; j++) {
2246  r = &am->acls[i].rules[j];
2247  out0 = format(out0, " %4d: %s ", j, r->is_ipv6 ? "ipv6" : "ipv4");
2248  out0 = format_acl_action(out0, r->is_permit);
2249  out0 = format(out0, " src %U/%d", format_ip46_address, &r->src, IP46_TYPE_ANY, r->src_prefixlen);
2250  out0 = format(out0, " dst %U/%d", format_ip46_address, &r->dst, IP46_TYPE_ANY, r->dst_prefixlen);
2251  out0 = format(out0, " proto %d", r->proto);
2252  out0 = format(out0, " sport %d", r->src_port_or_type_first);
2254  out0 = format(out0, "-%d", r->src_port_or_type_last);
2255  }
2256  out0 = format(out0, " dport %d", r->dst_port_or_code_first);
2258  out0 = format(out0, "-%d", r->dst_port_or_code_last);
2259  }
2260  if (r->tcp_flags_mask || r->tcp_flags_value) {
2261  out0 = format(out0, " tcpflags %d mask %d", r->tcp_flags_value, r->tcp_flags_mask);
2262  }
2263  out0 = format(out0, "\n");
2264  }
2265 
2267  out0 = format(out0, " applied inbound on sw_if_index: ");
2269  out0 = format(out0, "%d ", *pj);
2270  }
2271  out0 = format(out0, "\n");
2272  }
2274  out0 = format(out0, " applied outbound on sw_if_index: ");
2276  out0 = format(out0, "%d ", *pj);
2277  }
2278  out0 = format(out0, "\n");
2279  }
2280  }
2281  vec_terminate_c_string(out0);
2282  vlib_cli_output(vm, "\n%s\n", out0);
2283  vec_free(out0);
2284  }
2285  else if (unformat (input, "memory"))
2286  {
2287  vlib_cli_output (vm, "ACL plugin main heap statistics:\n");
2288  if (am->acl_mheap) {
2289  vlib_cli_output (vm, " %U\n", format_mheap, am->acl_mheap, 1);
2290  } else {
2291  vlib_cli_output (vm, " Not initialized\n");
2292  }
2293  vlib_cli_output (vm, "ACL hash lookup support heap statistics:\n");
2294  if (am->hash_lookup_mheap) {
2295  vlib_cli_output (vm, " %U\n", format_mheap, am->hash_lookup_mheap, 1);
2296  } else {
2297  vlib_cli_output (vm, " Not initialized\n");
2298  }
2299  }
2300  else if (unformat (input, "tables"))
2301  {
2302  ace_mask_type_entry_t *mte;
2303  u32 acl_index = ~0;
2304  u32 sw_if_index = ~0;
2305  int show_acl_hash_info = 0;
2306  int show_applied_info = 0;
2307  int show_mask_type = 0;
2308  int show_bihash = 0;
2309  u32 show_bihash_verbose = 0;
2310 
2311  if (unformat (input, "acl")) {
2312  show_acl_hash_info = 1;
2313  /* mask-type is handy to see as well right there */
2314  show_mask_type = 1;
2315  unformat (input, "index %u", &acl_index);
2316  } else if (unformat (input, "applied")) {
2317  show_applied_info = 1;
2318  unformat (input, "sw_if_index %u", &sw_if_index);
2319  } else if (unformat (input, "mask")) {
2320  show_mask_type = 1;
2321  } else if (unformat (input, "hash")) {
2322  show_bihash = 1;
2323  unformat (input, "verbose %u", &show_bihash_verbose);
2324  }
2325 
2326  if ( ! (show_mask_type || show_acl_hash_info || show_applied_info || show_bihash) ) {
2327  /* if no qualifiers specified, show all */
2328  show_mask_type = 1;
2329  show_acl_hash_info = 1;
2330  show_applied_info = 1;
2331  show_bihash = 1;
2332  }
2333 
2334  if (show_mask_type) {
2335  vlib_cli_output(vm, "Mask-type entries:");
2336  /* *INDENT-OFF* */
2338  ({
2339  vlib_cli_output(vm, " %3d: %016llx %016llx %016llx %016llx %016llx %016llx refcount %d",
2340  mte - am->ace_mask_type_pool,
2341  mte->mask.kv.key[0], mte->mask.kv.key[1], mte->mask.kv.key[2],
2342  mte->mask.kv.key[3], mte->mask.kv.key[4], mte->mask.kv.value, mte->refcount);
2343  }));
2344  /* *INDENT-ON* */
2345  }
2346 
2347  if (show_acl_hash_info) {
2348  u32 i,j;
2349  u8 * out0 = format(0, "");
2350  u64 *m;
2351  out0 = format(out0, "Mask-ready ACL representations\n");
2352  for (i=0; i< vec_len(am->hash_acl_infos); i++) {
2353  if ((acl_index != ~0) && (acl_index != i)) {
2354  continue;
2355  }
2356  hash_acl_info_t *ha = &am->hash_acl_infos[i];
2357  out0 = format(out0, "acl-index %u bitmask-ready layout\n", i);
2358  out0 = format(out0, " applied inbound on sw_if_index list: %U\n", format_vec32, ha->inbound_sw_if_index_list, "%d");
2359  out0 = format(out0, " applied outbound on sw_if_index list: %U\n", format_vec32, ha->outbound_sw_if_index_list, "%d");
2360  out0 = format(out0, " mask type index bitmap: %U\n", format_bitmap_hex, ha->mask_type_index_bitmap);
2361  for(j=0; j<vec_len(ha->rules); j++) {
2362  hash_ace_info_t *pa = &ha->rules[j];
2363  m = (u64 *)&pa->match;
2364  out0 = format(out0, " %4d: %016llx %016llx %016llx %016llx %016llx %016llx mask index %d acl %d rule %d action %d src/dst portrange not ^2: %d,%d\n",
2365  j, m[0], m[1], m[2], m[3], m[4], m[5], pa->mask_type_index,
2366  pa->acl_index, pa->ace_index, pa->action,
2368  }
2369  }
2370  vec_terminate_c_string(out0);
2371  vlib_cli_output(vm, "\n%s\n", out0);
2372  vec_free(out0);
2373  }
2374 
2375  if (show_applied_info) {
2376  u32 swi, j;
2377  u8 * out0 = format(0, "");
2378  out0 = format(out0, "Applied lookup entries for interfaces\n");
2379 
2380  for(swi = 0; (swi < vec_len(am->input_applied_hash_acl_info_by_sw_if_index)) ||
2383  (swi < vec_len(am->output_hash_entry_vec_by_sw_if_index)); swi++) {
2384  if ((sw_if_index != ~0) && (sw_if_index != swi)) {
2385  continue;
2386  }
2387  out0 = format(out0, "sw_if_index %d:\n", swi);
2390  out0 = format(out0, " input lookup mask_type_index_bitmap: %U\n", format_bitmap_hex, pal->mask_type_index_bitmap);
2391  out0 = format(out0, " input applied acls: %U\n", format_vec32, pal->applied_acls, "%d");
2392  }
2394  out0 = format(out0, " input lookup applied entries:\n");
2395  for(j=0; j<vec_len(am->input_hash_entry_vec_by_sw_if_index[swi]); j++) {
2397  out0 = format(out0, " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d\n",
2398  j, pae->acl_index, pae->ace_index, pae->action, pae->hash_ace_info_index,
2400  }
2401  }
2402 
2405  out0 = format(out0, " output lookup mask_type_index_bitmap: %U\n", format_bitmap_hex, pal->mask_type_index_bitmap);
2406  out0 = format(out0, " output applied acls: %U\n", format_vec32, pal->applied_acls, "%d");
2407  }
2409  out0 = format(out0, " output lookup applied entries:\n");
2410  for(j=0; j<vec_len(am->output_hash_entry_vec_by_sw_if_index[swi]); j++) {
2412  out0 = format(out0, " %4d: acl %d rule %d action %d bitmask-ready rule %d next %d prev %d tail %d\n",
2413  j, pae->acl_index, pae->ace_index, pae->action, pae->hash_ace_info_index,
2415  }
2416  }
2417 
2418  }
2419  vec_terminate_c_string(out0);
2420  vlib_cli_output(vm, "\n%s\n", out0);
2421  vec_free(out0);
2422  }
2423 
2424  if (show_bihash) {
2425  show_hash_acl_hash(vm, am, show_bihash_verbose);
2426  }
2427  }
2428  return error;
2429 }
2430 
2431 static clib_error_t *
2433  unformat_input_t * input,
2434  vlib_cli_command_t * cmd)
2435 {
2436  clib_error_t *error = 0;
2437  acl_main_t *am = &acl_main;
2440  return error;
2441 }
2442 
2443  /* *INDENT-OFF* */
2444 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
2445  .path = "set acl-plugin",
2446  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
2447  .function = acl_set_aclplugin_fn,
2448 };
2449 
2450 VLIB_CLI_COMMAND (aclplugin_show_command, static) = {
2451  .path = "show acl-plugin",
2452  .short_help = "show acl-plugin {sessions|acl|interface|tables}",
2453  .function = acl_show_aclplugin_fn,
2454 };
2455 
2456 VLIB_CLI_COMMAND (aclplugin_show_macip_command, static) = {
2457  .path = "show acl-plugin macip",
2458  .short_help = "show acl-plugin macip {acl|interface}",
2459  .function = acl_show_aclplugin_macip_fn,
2460 };
2461 
2462 
2463 VLIB_CLI_COMMAND (aclplugin_clear_command, static) = {
2464  .path = "clear acl-plugin sessions",
2465  .short_help = "clear acl-plugin sessions",
2466  .function = acl_clear_aclplugin_fn,
2467 };
2468 /* *INDENT-ON* */
2469 
2470 
2471 
2472 static clib_error_t *
2474 {
2475  acl_main_t *am = &acl_main;
2476  clib_error_t *error = 0;
2477  memset (am, 0, sizeof (*am));
2478  am->vlib_main = vm;
2479  am->vnet_main = vnet_get_main ();
2480 
2481  u8 *name = format (0, "acl_%08x%c", api_version, 0);
2482 
2483  /* Ask for a correctly-sized block of API message decode slots */
2484  am->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
2486 
2487  error = acl_plugin_api_hookup (vm);
2488 
2489  /* Add our API messages to the global name_crc hash table */
2491 
2492  vec_free (name);
2493 
2495 
2499 
2505  {
2506  u16 wk;
2507  u8 tt;
2508  for (wk = 0; wk < vec_len (am->per_worker_data); wk++) {
2512  for(tt = 0; tt < ACL_N_TIMEOUTS; tt++) {
2513  pw->fa_conn_list_head[tt] = ~0;
2514  pw->fa_conn_list_tail[tt] = ~0;
2515  }
2516  }
2517  }
2518 
2522 
2523  am->fa_cleaner_cnt_delete_by_sw_index = 0;
2524  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
2525  am->fa_cleaner_cnt_unknown_event = 0;
2526  am->fa_cleaner_cnt_timer_restarted = 0;
2527  am->fa_cleaner_cnt_wait_with_timeout = 0;
2528 
2529 
2530 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
2532 #undef _
2533 
2535 
2536  /* use the new fancy hash-based matching */
2537  am->use_hash_acl_matching = 1;
2538 
2539  return error;
2540 }
2541 
acl_rule_t * rules
Definition: acl.h:100
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
macip_acl_rule_t * rules
Definition: acl.h:107
u32 * acl_ip4_output_classify_table_by_sw_if_index
Definition: acl.h:168
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1212
u8 src_mac[6]
Definition: acl.h:87
u32 fa_cleaner_node_index
Definition: acl.h:181
u32 session_timeout_sec[ACL_N_TIMEOUTS]
Definition: acl.h:183
static u8 * format_bitmap_hex(u8 *s, va_list *args)
Format a bitmap as a string of hex bytes.
Definition: bitmap.h:744
Use acl_interface_set_acl_list instead Append/remove an ACL index to/from the list of ACLs checked fo...
Definition: acl.api:206
u32 fa_acl_in_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:196
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1274
static clib_error_t * acl_clear_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2432
static int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:1868
static int acl_hook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:591
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:837
static int verify_message_len(void *mp, u32 expected_len, char *where)
Definition: acl.c:1308
static int acl_classify_add_del_table_tiny(vnet_classify_main_t *cm, u8 *mask, u32 mask_len, u32 next_table_index, u32 miss_next_index, u32 *table_index, int is_add)
Definition: acl.c:390
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:35
void acl_plugin_hash_acl_set_trace_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:291
static void send_macip_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, macip_acl_list_t *acl, u32 context)
Definition: acl.c:1653
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:2473
static void acl_setup_fa_nodes(void)
Definition: acl.c:1802
void show_fa_sessions_hash(vlib_main_t *vm, u32 verbose)
Definition: fa_node.c:1687
int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:680
u8 is_ipv6
Definition: acl.h:69
char ** l2output_get_feat_names(void)
Definition: l2_output.c:38
static int acl_interface_del_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:771
uword * pending_clear_sw_if_index_bitmap
Definition: fa_node.h:134
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:127
Definition: acl.h:118
a
Definition: bitmap.h:516
int acl_interface_in_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:655
u64 fa_current_cleaner_timer_wait_interval
Definition: acl.h:231
u32 acl_index
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:229
static clib_error_t * acl_show_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2102
#define foreach_acl_plugin_api_msg
Definition: acl.c:64
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:146
u16 msg_id_base
Definition: acl.h:129
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:280
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:318
static int count_skip(u8 *p, u32 size)
Definition: acl.c:375
vnet_interface_main_t interface_main
Definition: vnet.h:56
static void vl_api_acl_add_replace_t_handler(vl_api_acl_add_replace_t *mp)
Definition: acl.c:1322
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:1703
int l4_match_nonfirst_fragment
Definition: acl.h:205
u8 src_ip_addr[16]
Definition: acl.api:91
void * mheap_alloc(void *memory, uword size)
Definition: mheap.c:947
Control ping from the client to the server response.
Definition: acl.api:63
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_NUM_BUCKETS
Definition: fa_node.h:18
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:33
#define REPLY_MACRO2(t, body)
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:238
static void vl_api_macip_acl_add_t_handler(vl_api_macip_acl_add_t *mp)
Definition: acl.c:1597
f64 clocks_per_second
Definition: time.h:53
u8 dst_prefixlen
Definition: acl.h:73
u8 action
u32 hash_ace_info_index
u32 * acl_ip6_input_classify_table_by_sw_if_index
Definition: acl.h:167
fa_5tuple_t info
Definition: fa_node.h:58
u32 count
Definition: acl.h:99
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:994
u32 l2_table_index
Definition: acl.h:111
void vnet_l2_input_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
static mheap_t * mheap_header(u8 *v)
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
format_function_t format_ip46_address
Definition: format.h:61
u64 session_timeout[ACL_N_TIMEOUTS]
Definition: acl.h:239
fa_session_t * fa_sessions_pool
Definition: fa_node.h:108
u32 l2_input_classify_next_acl_ip4
Definition: acl.h:191
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
Access List Rule entry.
Definition: acl.api:87
applied_hash_acl_info_t * output_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:141
clib_time_t clib_time
Definition: main.h:62
u8 link_list_id
Definition: fa_node.h:69
u16 dstport_or_icmpcode_last
Definition: acl.api:112
static clib_error_t * acl_show_aclplugin_macip_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2078
#define MHEAP_FLAG_THREAD_SAFE
Delete a MACIP ACL.
Definition: acl.api:340
u8 * format_mheap(u8 *s, va_list *va)
Definition: mheap.c:1162
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
static u32 macip_find_match_type(macip_match_type_t *mv, u8 *mac_mask, u8 prefix_len, u8 is_ipv6)
Definition: acl.c:926
u32 table_index
Definition: acl.c:921
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Details about one MACIP ACL.
Definition: acl.api:386
u32 fa_acl_out_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:198
f64 fa_cleaner_wait_time_increment
Definition: acl.h:229
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
void hash_acl_add(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:769
uword fa_conn_table_hash_memory_size
Definition: acl.h:209
u16 dst_port_or_code_last
Definition: acl.h:78
static clib_error_t * acl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: acl.c:1883
u8 src_mac_mask[6]
Definition: acl.h:88
u32 l2_output_classify_next_acl_ip4
Definition: acl.h:193
u8 src_prefixlen
Definition: acl.h:71
ip46_address_t src_ip_addr
Definition: acl.h:89
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:66
u32 next_applied_entry_index
void acl_plugin_hash_acl_set_validate_heap(acl_main_t *am, int on)
Definition: hash_lookup.c:276
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
u32 link_prev_idx
Definition: fa_node.h:67
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static int acl_is_not_defined(acl_main_t *am, u32 acl_list_index)
Definition: acl.c:705
u16 dstport_or_icmpcode_first
Definition: acl.api:111
u64 fa_conn_table_max_entries
Definition: acl.h:210
vnet_main_t * vnet_main
Definition: acl.h:259
unsigned long long u32x4
Definition: ixge.c:28
ip46_address_t src
Definition: acl.h:70
u8 src_ip_prefix_len
Definition: acl.api:92
u8 tcp_flags_value
Definition: acl.api:119
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:205
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Add or delete a MACIP ACL to/from interface.
Definition: acl.api:355
#define clib_error_return(e, args...)
Definition: error.h:99
static u8 * format_acl_action(u8 *s, u8 action)
Definition: manual_fns.h:93
u8 src_prefixlen
Definition: acl.h:90
u8 is_permit
Definition: acl.h:68
#define ACL_FA_CONN_TABLE_DEFAULT_MAX_ENTRIES
Definition: fa_node.h:20
unsigned long u64
Definition: types.h:89
int vnet_l2_output_classify_set_tables(u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 other_table_index)
Set l2 per-protocol, per-interface output classification tables.
u8 mac_mask[6]
Definition: acl.c:918
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:941
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(acl_sw_interface_add_del)
u32 ip4_table_index
Definition: acl.h:109
void hash_acl_unapply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:523
u32 * inbound_sw_if_index_list
void * vl_msg_api_alloc(int nbytes)
u32 fa_acl_out_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:199
static u8 * my_macip_acl_rule_t_pretty_format(u8 *out, va_list *args)
Definition: acl.c:2041
u32 * acl_ip4_input_classify_table_by_sw_if_index
Definition: acl.h:166
ip46_address_t dst
Definition: acl.h:72
uword * mask_type_index_bitmap
int vnet_classify_add_del_session(vnet_classify_main_t *cm, u32 table_index, u8 *match, u32 hit_next_index, u32 opaque_index, i32 advance, u8 action, u32 metadata, int is_add)
static int acl_unhook_l2_input_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:446
applied_hash_acl_info_t * input_applied_hash_acl_info_by_sw_if_index
Definition: acl.h:140
Reply to add MACIP ACL.
Definition: acl.api:327
static int acl_hook_l2_input_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:529
static void acl_set_session_max_entries(u32 value)
Definition: acl.c:1861
Control ping from client to api server request.
Definition: acl.api:51
static void setup_message_id_table(acl_main_t *am, api_main_t *apim)
Definition: acl.c:1793
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:946
VLIB_PLUGIN_REGISTER()
#define ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT
Definition: acl.h:228
u16 dst_port_or_code_first
Definition: acl.h:77
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: acl.h:36
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:1472
#define v
Definition: acl.c:320
struct _unformat_input_t unformat_input_t
uword * fa_ipv6_known_eh_bitmap
Definition: acl.h:202
Replace an existing ACL in-place or create a new ACL.
Definition: acl.api:159
#define ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:225
hash_acl_info_t * hash_acl_infos
Definition: acl.h:132
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
void acl_plugin_acl_set_validate_heap(acl_main_t *am, int on)
Definition: acl.c:100
Details about a single ACL contents.
Definition: acl.api:295
hash_ace_info_t * rules
#define REPLY_MACRO(t)
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
vl_api_acl_rule_t r[count]
Definition: acl.api:166
static int get_l3_src_offset(int is6)
Definition: acl.c:963
f64 seconds_per_clock
Definition: time.h:57
void show_hash_acl_hash(vlib_main_t *vm, acl_main_t *am, u32 verbose)
Definition: hash_lookup.c:888
u64 last_active_time
Definition: fa_node.h:59
u32 l2_input_classify_next_acl_ip6
Definition: acl.h:192
u8 proto
Definition: acl.h:74
u8 dst_ip_addr[16]
Definition: acl.api:93
static u8 * my_format_mac_address(u8 *s, va_list *args)
Definition: acl.c:2033
static void send_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, acl_list_t *acl, u32 context)
Definition: acl.c:1440
u16 src_port_or_type_first
Definition: acl.h:75
u64 fa_min_deleted_sessions_per_interval
Definition: acl.h:226
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:955
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
vl_api_acl_rule_t r[count]
Definition: acl.api:271
static int acl_unhook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:487
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:948
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1238
Dump one or all defined MACIP ACLs.
Definition: acl.api:371
api_main_t api_main
Definition: api_shared.c:35
static int acl_classify_add_del_table_small(vnet_classify_main_t *cm, u8 *mask, u32 mask_len, u32 next_table_index, u32 miss_next_index, u32 *table_index, int is_add)
Definition: acl.c:417
applied_hash_ace_entry_t ** output_hash_entry_vec_by_sw_if_index
Definition: acl.h:139
u64 fa_session_total_adds
Definition: acl.h:185
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
void acl_plugin_acl_set_trace_heap(acl_main_t *am, int on)
Definition: acl.c:115
static void feat_bitmap_init_next_nodes(vlib_main_t *vm, u32 node_index, u32 num_features, char **feat_names, u32 *next_nodes)
Initialize the feature next-node indexes of a graph node.
Definition: feat_bitmap.h:43
u32 * outbound_sw_if_index_list
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:223
u16 srcport_or_icmptype_first
Definition: acl.api:109
void hash_acl_delete(acl_main_t *am, int acl_index)
Definition: hash_lookup.c:826
Reply to add/replace ACL.
Definition: acl.api:175
#define clib_warning(format, args...)
Definition: error.h:59
static int acl_interface_add_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:712
u64 memory_size
Definition: vhost-user.h:76
Definition: acl.h:66
Reply with the vector of MACIP ACLs by sw_if_index.
Definition: acl.api:412
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u8 * format_vec32(u8 *s, va_list *va)
Definition: std-formats.c:43
u32 sw_if_index
Definition: fa_node.h:60
int vnet_l2_input_classify_set_tables(u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 other_table_index)
Set l2 per-protocol, per-interface input classification tables.
int use_hash_acl_matching
Definition: acl.h:157
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define foreach_fa_cleaner_counter
Definition: acl.h:244
void acl_fa_enable_disable(u32 sw_if_index, int is_input, int enable_disable)
Definition: fa_node.c:1632
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:58
u8 is_ipv6
Definition: acl.h:86
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:72
u16 srcport_or_icmptype_last
Definition: acl.api:110
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static void vl_api_acl_interface_add_del_t_handler(vl_api_acl_interface_add_del_t *mp)
Definition: acl.c:1358
#define ASSERT(truth)
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1187
unsigned int u32
Definition: types.h:88
u8 tag[64]
Definition: acl.h:98
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:1621
u16 src_port_or_type_last
Definition: acl.h:76
MACIP Access List Rule entry.
Definition: acl.api:131
static int macip_create_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:972
static void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:1846
static void send_acl_interface_list_details(acl_main_t *am, unix_shared_memory_queue_t *q, u32 sw_if_index, u32 context)
Definition: acl.c:1515
u64 size
Definition: vhost-user.h:75
#define MHEAP_FLAG_VALIDATE
u8 dst_ip_prefix_len
Definition: acl.api:94
acl_main_t acl_main
Definition: acl.c:57
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
Delete an ACL.
Definition: acl.api:188
Reply to get the plugin version.
Definition: acl.api:40
static clib_error_t * acl_plugin_api_hookup(vlib_main_t *vm)
Definition: acl.c:1771
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1137
union fa_session_t::@283 tcp_flags_seen
uword * serviced_sw_if_index_bitmap
Definition: fa_node.h:132
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:392
u32 fa_acl_in_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:197
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Reply to set the ACL list on an interface.
Definition: acl.api:250
u32 link_next_idx
Definition: fa_node.h:68
u64 uword
Definition: types.h:112
int vnet_classify_add_del_table(vnet_classify_main_t *cm, u8 *mask, u32 nbuckets, u32 memory_size, u32 skip, u32 match, u32 next_table_index, u32 miss_next_index, u32 *table_index, u8 current_data_flag, i16 current_data_offset, int is_add, int del_chain)
#define MHEAP_FLAG_TRACE
#define vec_elt(v, i)
Get vector value at index i.
ace_mask_type_entry_t * ace_mask_type_pool
Definition: acl.h:160
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
static void macip_acl_print(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:2055
u32 prev_applied_entry_index
u32 * macip_acl_by_sw_if_index
Definition: acl.h:172
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:400
#define XX
Definition: acl.c:317
u32 * acl_ip6_output_classify_table_by_sw_if_index
Definition: acl.h:169
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:1561
u16 as_u16
Definition: fa_node.h:63
static int acl_add_list(u32 count, vl_api_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:167
unsigned short u16
Definition: types.h:57
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1346
macip_acl_list_t * macip_acls
Definition: acl.h:143
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
Details about a single ACL contents.
Definition: acl.api:265
u32 ip6_table_index
Definition: acl.h:110
u8 tcp_flags_mask
Definition: acl.h:80
acl_fa_per_worker_data_t * per_worker_data
Definition: acl.h:236
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:644
int fa_interrupt_generation
Definition: acl.h:233
u32 ** input_sw_if_index_vec_by_acl
Definition: acl.h:150
void vnet_l2_output_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
static void vl_api_acl_interface_set_acl_list_t_handler(vl_api_acl_interface_set_acl_list_t *mp)
Definition: acl.c:1378
u64 fa_max_deleted_sessions_per_interval
Definition: acl.h:218
void * acl_mheap
Definition: acl.h:126
static clib_error_t * acl_set_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:1902
u16 thread_index
Definition: fa_node.h:64
unformat_function_t unformat_memory_size
Definition: format.h:294
static void acl_interface_reset_inout_acls(u32 sw_if_index, u8 is_input)
Definition: acl.c:840
void hash_acl_apply(acl_main_t *am, u32 sw_if_index, u8 is_input, int acl_index)
Definition: hash_lookup.c:303
static int acl_interface_add_del_inout_acl(u32 sw_if_index, u8 is_add, u8 is_input, u32 acl_list_index)
Definition: acl.c:889
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 tcp_flags_value
Definition: acl.h:79
Get the plugin version.
Definition: acl.api:28
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1414
void mheap_validate(void *v)
Definition: mheap.c:1338
#define vec_foreach(var, vec)
Vector iterator.
static void * acl_set_heap(acl_main_t *am)
Definition: acl.c:88
void * hash_lookup_mheap
Definition: acl.h:136
int vnet_set_input_acl_intfc(vlib_main_t *vm, u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 l2_table_index, u32 is_add)
Definition: input_acl.c:59
u32 tail_applied_entry_index
Add a MACIP ACL.
Definition: acl.api:312
u32 vl_msg_api_get_msg_length(void *msg_arg)
Definition: api_shared.c:628
Definition: acl.h:96
u32 client_index
Definition: acl.api:252
u32 ** output_sw_if_index_vec_by_acl
Definition: acl.h:151
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:32
u8 tag[64]
Definition: acl.h:105
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:485
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 l2_output_classify_next_acl_ip6
Definition: acl.h:194
u8 ip6_5tuple_mask[]
Definition: acl.c:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
#define ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:217
static void vl_api_acl_plugin_control_ping_t_handler(vl_api_acl_plugin_control_ping_t *mp)
Definition: acl.c:152
acl_list_t * acls
Definition: acl.h:131
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:147
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: acl.h:37
u8 is_permit
Definition: acl.h:85
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:1634
u32 ace_index
u32 arp_table_index
Definition: acl.c:922
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u64 link_enqueue_time
Definition: fa_node.h:66
u32 fa_conn_table_hash_num_buckets
Definition: acl.h:208
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE
Definition: fa_node.h:19
u64 fa_session_total_dels
Definition: acl.h:186
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:248
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1114
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:1739
applied_hash_ace_entry_t ** input_hash_entry_vec_by_sw_if_index
Definition: acl.h:138
u8 ip4_5tuple_mask[]
Definition: acl.c:322
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:258