FD.io VPP  v17.04-9-g99c0734
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 #include <acl/l2sess.h>
22 
23 #include <vnet/l2/l2_classify.h>
25 #include <vpp/app/version.h>
26 
27 #include <vlibapi/api.h>
28 #include <vlibmemory/api.h>
29 #include <vlibsocket/api.h>
30 
31 /* define message IDs */
32 #include <acl/acl_msg_enum.h>
33 
34 /* define message structures */
35 #define vl_typedefs
36 #include <acl/acl_all_api_h.h>
37 #undef vl_typedefs
38 
39 /* define generated endian-swappers */
40 #define vl_endianfun
41 #include <acl/acl_all_api_h.h>
42 #undef vl_endianfun
43 
44 /* instantiate all the print functions we know about */
45 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46 #define vl_printfun
47 #include <acl/acl_all_api_h.h>
48 #undef vl_printfun
49 
50 /* Get the API version number */
51 #define vl_api_version(n,v) static u32 api_version=(v);
52 #include <acl/acl_all_api_h.h>
53 #undef vl_api_version
54 
55 #include "node_in.h"
56 #include "node_out.h"
57 #include "fa_node.h"
58 
60 
61 #define REPLY_MSG_ID_BASE am->msg_id_base
63 
64 /* List of message types that this plugin understands */
65 
66 #define foreach_acl_plugin_api_msg \
67 _(ACL_PLUGIN_GET_VERSION, acl_plugin_get_version) \
68 _(ACL_ADD_REPLACE, acl_add_replace) \
69 _(ACL_DEL, acl_del) \
70 _(ACL_INTERFACE_ADD_DEL, acl_interface_add_del) \
71 _(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list) \
72 _(ACL_DUMP, acl_dump) \
73 _(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump) \
74 _(MACIP_ACL_ADD, macip_acl_add) \
75 _(MACIP_ACL_DEL, macip_acl_del) \
76 _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
77 _(MACIP_ACL_DUMP, macip_acl_dump) \
78 _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get)
79 
80 /* *INDENT-OFF* */
82  .version = VPP_BUILD_VER,
83  .description = "Access Control Lists",
84 };
85 /* *INDENT-ON* */
86 
87 static void
89 {
90  acl_main_t *am = &acl_main;
92  int msg_size = sizeof (*rmp);
94 
96  if (q == 0)
97  {
98  return;
99  }
100 
101  rmp = vl_msg_api_alloc (msg_size);
102  memset (rmp, 0, msg_size);
103  rmp->_vl_msg_id =
104  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
105  rmp->context = mp->context;
106  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
107  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
108 
109  vl_msg_api_send_shmem (q, (u8 *) & rmp);
110 }
111 
112 
113 static int
115  u32 * acl_list_index, u8 * tag)
116 {
117  acl_main_t *am = &acl_main;
118  acl_list_t *a;
119  acl_rule_t *r;
120  acl_rule_t *acl_new_rules;
121  int i;
122 
123  if (*acl_list_index != ~0)
124  {
125  /* They supplied some number, let's see if this ACL exists */
126  if (pool_is_free_index (am->acls, *acl_list_index))
127  {
128  /* tried to replace a non-existent ACL, no point doing anything */
129  return -1;
130  }
131  }
132 
133  /* Create and populate the rules */
134  acl_new_rules = clib_mem_alloc_aligned (sizeof (acl_rule_t) * count,
136  if (!acl_new_rules)
137  {
138  /* Could not allocate rules. New or existing ACL - bail out regardless */
139  return -1;
140  }
141 
142  for (i = 0; i < count; i++)
143  {
144  r = &acl_new_rules[i];
145  r->is_permit = rules[i].is_permit;
146  r->is_ipv6 = rules[i].is_ipv6;
147  if (r->is_ipv6)
148  {
149  memcpy (&r->src, rules[i].src_ip_addr, sizeof (r->src));
150  memcpy (&r->dst, rules[i].dst_ip_addr, sizeof (r->dst));
151  }
152  else
153  {
154  memcpy (&r->src.ip4, rules[i].src_ip_addr, sizeof (r->src.ip4));
155  memcpy (&r->dst.ip4, rules[i].dst_ip_addr, sizeof (r->dst.ip4));
156  }
157  r->src_prefixlen = rules[i].src_ip_prefix_len;
158  r->dst_prefixlen = rules[i].dst_ip_prefix_len;
159  r->proto = rules[i].proto;
160  r->src_port_or_type_first = ntohs ( rules[i].srcport_or_icmptype_first );
161  r->src_port_or_type_last = ntohs ( rules[i].srcport_or_icmptype_last );
162  r->dst_port_or_code_first = ntohs ( rules[i].dstport_or_icmpcode_first );
163  r->dst_port_or_code_last = ntohs ( rules[i].dstport_or_icmpcode_last );
164  r->tcp_flags_value = rules[i].tcp_flags_value;
165  r->tcp_flags_mask = rules[i].tcp_flags_mask;
166  }
167 
168  if (~0 == *acl_list_index)
169  {
170  /* Get ACL index */
172  memset (a, 0, sizeof (*a));
173  /* Will return the newly allocated ACL index */
174  *acl_list_index = a - am->acls;
175  }
176  else
177  {
178  a = am->acls + *acl_list_index;
179  /* Get rid of the old rules */
180  clib_mem_free (a->rules);
181  }
182  a->rules = acl_new_rules;
183  a->count = count;
184  memcpy (a->tag, tag, sizeof (a->tag));
185 
186  return 0;
187 }
188 
189 static int
190 acl_del_list (u32 acl_list_index)
191 {
192  acl_main_t *am = &acl_main;
193  acl_list_t *a;
194  int i, ii;
195  if (pool_is_free_index (am->acls, acl_list_index))
196  {
197  return -1;
198  }
199 
200  /* delete any references to the ACL */
201  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index); i++)
202  {
203  for (ii = 0; ii < vec_len (am->output_acl_vec_by_sw_if_index[i]);
204  /* see body */ )
205  {
206  if (acl_list_index == am->output_acl_vec_by_sw_if_index[i][ii])
207  {
209  }
210  else
211  {
212  ii++;
213  }
214  }
215  }
216  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index); i++)
217  {
218  for (ii = 0; ii < vec_len (am->input_acl_vec_by_sw_if_index[i]);
219  /* see body */ )
220  {
221  if (acl_list_index == am->input_acl_vec_by_sw_if_index[i][ii])
222  {
224  }
225  else
226  {
227  ii++;
228  }
229  }
230  }
231 
232  /* now we can delete the ACL itself */
233  a = &am->acls[acl_list_index];
234  if (a->rules)
235  {
236  clib_mem_free (a->rules);
237  }
238  pool_put (am->acls, a);
239  return 0;
240 }
241 
242 /* Some aids in ASCII graphing the content */
243 #define XX "\377"
244 #define __ "\000"
245 #define _(x)
246 #define v
247 
249 _(" dmac smac etype ")
250 _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
251  _(" v ihl totlen ")
252  _(0x0000)
253  __ __ __ __
254  _(" ident fl+fo ")
255  _(0x0004)
256  __ __ __ __
257  _(" ttl pr checksum ")
258  _(0x0008)
259  __ XX __ __
260  _(" src address ")
261  _(0x000C)
262  XX XX XX XX
263  _(" dst address ")
264  _(0x0010)
265  XX XX XX XX
266  _("L4 T/U sport dport ")
267  _(tcpudp)
268  XX XX XX XX
269  _(padpad)
270  __ __ __ __
271  _(padpad)
272  __ __ __ __
273  _(padeth)
274  __ __;
275 
277  _(" dmac smac etype ")
278  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
279  _(" v tc + flow ")
280  _(0x0000) __ __ __ __
281  _(" plen nh hl ")
282  _(0x0004) __ __ XX __
283  _(" src address ")
284  _(0x0008) XX XX XX XX
285  _(0x000C) XX XX XX XX
286  _(0x0010) XX XX XX XX
287  _(0x0014) XX XX XX XX
288  _(" dst address ")
289  _(0x0018) XX XX XX XX
290  _(0x001C) XX XX XX XX
291  _(0x0020) XX XX XX XX
292  _(0x0024) XX XX XX XX
293  _("L4T/U sport dport ")
294  _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
295 
296 #undef XX
297 #undef __
298 #undef _
299 #undef v
300 
301  static int count_skip (u8 * p, u32 size)
302 {
303  u64 *p64 = (u64 *) p;
304  /* Be tolerant to null pointer */
305  if (0 == p)
306  return 0;
307 
308  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
309  {
310  p64++;
311  }
312  return (p64 - (u64 *) p) / 2;
313 }
314 
315 static int
317  u32 mask_len, u32 next_table_index,
318  u32 miss_next_index, u32 * table_index,
319  int is_add)
320 {
321  u32 nbuckets = 65536;
322  u32 memory_size = 2 << 30;
323  u32 skip = count_skip (mask, mask_len);
324  u32 match = (mask_len / 16) - skip;
325  u8 *skip_mask_ptr = mask + 16 * skip;
326  u32 current_data_flag = 0;
327  int current_data_offset = 0;
328 
329  if (0 == match)
330  match = 1;
331 
332  return vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
333  memory_size, skip, match,
334  next_table_index, miss_next_index,
335  table_index, current_data_flag,
336  current_data_offset, is_add,
337  1 /* delete_chain */);
338 }
339 
340 static int
342  u32 mask_len, u32 next_table_index,
343  u32 miss_next_index, u32 * table_index,
344  int is_add)
345 {
346  u32 nbuckets = 32;
347  u32 memory_size = 2 << 20;
348  u32 skip = count_skip (mask, mask_len);
349  u32 match = (mask_len / 16) - skip;
350  u8 *skip_mask_ptr = mask + 16 * skip;
351  u32 current_data_flag = 0;
352  int current_data_offset = 0;
353 
354  if (0 == match)
355  match = 1;
356 
357  return vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
358  memory_size, skip, match,
359  next_table_index, miss_next_index,
360  table_index, current_data_flag,
361  current_data_offset, is_add,
362  1 /* delete_chain */);
363 }
364 
365 
366 static int
368 {
370  u32 ip4_table_index = ~0;
371  u32 ip6_table_index = ~0;
372 
374  sw_if_index, ~0);
376  sw_if_index, ~0);
377 
378  vnet_l2_input_classify_enable_disable (sw_if_index, 0);
379 
380  if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
381  {
382  ip4_table_index =
384  am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
385  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
386  sizeof (ip4_5tuple_mask) - 1, ~0,
388  &ip4_table_index, 0);
389  }
390  if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
391  {
392  ip6_table_index =
394  am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
396  sizeof (ip6_5tuple_mask) - 1, ~0,
398  &ip6_table_index, 0);
399  }
400 
401  return 0;
402 }
403 
404 static int
406 {
408  u32 ip4_table_index = ~0;
409  u32 ip6_table_index = ~0;
410 
412  sw_if_index, ~0);
414  sw_if_index, ~0);
415 
417 
418  if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
419  {
420  ip4_table_index =
422  am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
423  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
424  sizeof (ip4_5tuple_mask) - 1, ~0,
426  &ip4_table_index, 0);
427  }
428  if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
429  {
430  ip6_table_index =
432  am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
434  sizeof (ip6_5tuple_mask) - 1, ~0,
436  &ip6_table_index, 0);
437  }
438 
439  return 0;
440 }
441 
442 static int
444 {
446  u32 ip4_table_index = ~0;
447  u32 ip6_table_index = ~0;
448  int rv;
449 
450  /* in case there were previous tables attached */
451  acl_unhook_l2_input_classify (am, sw_if_index);
452  rv =
453  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
454  sizeof (ip4_5tuple_mask) - 1, ~0,
456  &ip4_table_index, 1);
457  if (rv)
458  return rv;
459  rv =
461  sizeof (ip6_5tuple_mask) - 1, ~0,
463  &ip6_table_index, 1);
464  if (rv)
465  {
466  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
467  sizeof (ip4_5tuple_mask) - 1, ~0,
469  &ip4_table_index, 0);
470  return rv;
471  }
472  rv =
473  vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
474  ip6_table_index, ~0);
476  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
477  sw_if_index, ip4_table_index, ip6_table_index);
478  if (rv)
479  {
481  sizeof (ip6_5tuple_mask) - 1, ~0,
483  &ip6_table_index, 0);
484  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
485  sizeof (ip4_5tuple_mask) - 1, ~0,
487  &ip4_table_index, 0);
488  return rv;
489  }
490 
492  ip4_table_index;
494  ip6_table_index;
495 
496  vnet_l2_input_classify_enable_disable (sw_if_index, 1);
497  return rv;
498 }
499 
500 static int
502 {
504  u32 ip4_table_index = ~0;
505  u32 ip6_table_index = ~0;
506  int rv;
507 
508  /* in case there were previous tables attached */
509  acl_unhook_l2_output_classify (am, sw_if_index);
510  rv =
511  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
512  sizeof (ip4_5tuple_mask) - 1, ~0,
514  &ip4_table_index, 1);
515  if (rv)
516  return rv;
517  rv =
519  sizeof (ip6_5tuple_mask) - 1, ~0,
521  &ip6_table_index, 1);
522  if (rv)
523  {
524  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
525  sizeof (ip4_5tuple_mask) - 1, ~0,
527  &ip4_table_index, 0);
528  return rv;
529  }
530  rv =
531  vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
532  ip6_table_index, ~0);
534  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
535  sw_if_index, ip4_table_index, ip6_table_index);
536  if (rv)
537  {
539  sizeof (ip6_5tuple_mask) - 1, ~0,
541  &ip6_table_index, 0);
542  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
543  sizeof (ip4_5tuple_mask) - 1, ~0,
545  &ip4_table_index, 0);
546  return rv;
547  }
548 
550  ip4_table_index;
552  ip6_table_index;
553 
555  return rv;
556 }
557 
558 
559 
560 int
562  int enable_disable)
563 {
564  int rv;
565 
566  /* Utterly wrong? */
568  sw_if_index))
569  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
570 
571  acl_fa_enable_disable(sw_if_index, 1, enable_disable);
572 
573  if (enable_disable)
574  {
575  rv = acl_hook_l2_input_classify (am, sw_if_index);
576  }
577  else
578  {
579  rv = acl_unhook_l2_input_classify (am, sw_if_index);
580  }
581 
582  return rv;
583 }
584 
585 int
587  int enable_disable)
588 {
589  int rv;
590 
591  /* Utterly wrong? */
593  sw_if_index))
594  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
595 
596  acl_fa_enable_disable(sw_if_index, 0, enable_disable);
597 
598  if (enable_disable)
599  {
600  rv = acl_hook_l2_output_classify (am, sw_if_index);
601  }
602  else
603  {
604  rv = acl_unhook_l2_output_classify (am, sw_if_index);
605  }
606 
607  return rv;
608 }
609 
610 
611 static int
612 acl_interface_add_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
613 {
614  acl_main_t *am = &acl_main;
615  if (is_input)
616  {
617  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
618  vec_add (am->input_acl_vec_by_sw_if_index[sw_if_index], &acl_list_index,
619  1);
620  acl_interface_in_enable_disable (am, sw_if_index, 1);
621  }
622  else
623  {
624  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
625  vec_add (am->output_acl_vec_by_sw_if_index[sw_if_index],
626  &acl_list_index, 1);
627  acl_interface_out_enable_disable (am, sw_if_index, 1);
628  }
629  return 0;
630 }
631 
632 static int
633 acl_interface_del_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
634 {
635  acl_main_t *am = &acl_main;
636  int i;
637  int rv = -1;
638  if (is_input)
639  {
640  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
641  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
642  i++)
643  {
644  if (acl_list_index ==
645  am->input_acl_vec_by_sw_if_index[sw_if_index][i])
646  {
647  vec_del1 (am->input_acl_vec_by_sw_if_index[sw_if_index], i);
648  rv = 0;
649  break;
650  }
651  }
652  if (0 == vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
653  {
654  acl_interface_in_enable_disable (am, sw_if_index, 0);
655  }
656  }
657  else
658  {
659  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
660  for (i = 0;
661  i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]); i++)
662  {
663  if (acl_list_index ==
664  am->output_acl_vec_by_sw_if_index[sw_if_index][i])
665  {
666  vec_del1 (am->output_acl_vec_by_sw_if_index[sw_if_index], i);
667  rv = 0;
668  break;
669  }
670  }
671  if (0 == vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
672  {
673  acl_interface_out_enable_disable (am, sw_if_index, 0);
674  }
675  }
676  return rv;
677 }
678 
679 static void
680 acl_interface_reset_inout_acls (u32 sw_if_index, u8 is_input)
681 {
682  acl_main_t *am = &acl_main;
683  if (is_input)
684  {
685  acl_interface_in_enable_disable (am, sw_if_index, 0);
686  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
688  }
689  else
690  {
691  acl_interface_out_enable_disable (am, sw_if_index, 0);
692  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
694  }
695 }
696 
697 static int
698 acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
699  u32 acl_list_index)
700 {
701  int rv = -1;
702  if (is_add)
703  {
704  rv =
705  acl_interface_add_inout_acl (sw_if_index, is_input, acl_list_index);
706  }
707  else
708  {
709  rv =
710  acl_interface_del_inout_acl (sw_if_index, is_input, acl_list_index);
711  }
712  return rv;
713 }
714 
715 
716 static void *
718 {
719  u8 *p = vlib_buffer_get_current (b0) + offset;
720  return p;
721 }
722 
723 static u8
724 acl_get_l4_proto (vlib_buffer_t * b0, int node_is_ip6)
725 {
726  u8 proto;
727  int proto_offset;
728  if (node_is_ip6)
729  {
730  proto_offset = 20;
731  }
732  else
733  {
734  proto_offset = 23;
735  }
736  proto = *((u8 *) vlib_buffer_get_current (b0) + proto_offset);
737  return proto;
738 }
739 
740 static int
741 acl_match_addr (ip46_address_t * addr1, ip46_address_t * addr2, int prefixlen,
742  int is_ip6)
743 {
744  if (prefixlen == 0)
745  {
746  /* match any always succeeds */
747  return 1;
748  }
749  if (is_ip6)
750  {
751  if (memcmp (addr1, addr2, prefixlen / 8))
752  {
753  /* If the starting full bytes do not match, no point in bittwidling the thumbs further */
754  return 0;
755  }
756  if (prefixlen % 8)
757  {
758  u8 b1 = *((u8 *) addr1 + 1 + prefixlen / 8);
759  u8 b2 = *((u8 *) addr2 + 1 + prefixlen / 8);
760  u8 mask0 = (0xff - ((1 << (8 - (prefixlen % 8))) - 1));
761  return (b1 & mask0) == b2;
762  }
763  else
764  {
765  /* The prefix fits into integer number of bytes, so nothing left to do */
766  return 1;
767  }
768  }
769  else
770  {
771  uint32_t a1 = ntohl (addr1->ip4.as_u32);
772  uint32_t a2 = ntohl (addr2->ip4.as_u32);
773  uint32_t mask0 = 0xffffffff - ((1 << (32 - prefixlen)) - 1);
774  return (a1 & mask0) == a2;
775  }
776 }
777 
778 static int
779 acl_match_port (u16 port, u16 port_first, u16 port_last, int is_ip6)
780 {
781  return ((port >= port_first) && (port <= port_last));
782 }
783 
784 static int
786  u8 * r_action, int *r_is_ip6, u32 * r_acl_match_p,
787  u32 * r_rule_match_p, u32 * trace_bitmap)
788 {
789  ethernet_header_t *h0;
790  u16 type0;
791 
792  ip46_address_t src, dst;
793  int is_ip6;
794  int is_ip4;
795  u8 proto;
796  u16 src_port = 0;
797  u16 dst_port = 0;
798  u8 tcp_flags = 0;
799  int i;
800  acl_list_t *a;
801  acl_rule_t *r;
802 
803  h0 = vlib_buffer_get_current (b0);
804  type0 = clib_net_to_host_u16 (h0->type);
805  is_ip4 = (type0 == ETHERNET_TYPE_IP4);
806  is_ip6 = (type0 == ETHERNET_TYPE_IP6);
807 
808  if (!(is_ip4 || is_ip6))
809  {
810  return 0;
811  }
812  /* The bunch of hardcoded offsets here is intentional to get rid of them
813  ASAP, when getting to a faster matching code */
814  if (is_ip4)
815  {
816  clib_memcpy (&src.ip4, get_ptr_to_offset (b0, 26), 4);
817  clib_memcpy (&dst.ip4, get_ptr_to_offset (b0, 30), 4);
818  proto = acl_get_l4_proto (b0, 0);
819  if (1 == proto)
820  {
821  *trace_bitmap |= 0x00000001;
822  /* type */
823  src_port = ((u16) (*(u8 *) get_ptr_to_offset (b0, 34)));
824  /* code */
825  dst_port = ((u16) (*(u8 *) get_ptr_to_offset (b0, 35)));
826  } else {
827  /* assume TCP/UDP */
828  src_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 34)));
829  dst_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 36)));
830  /* UDP gets ability to check on an oddball data byte as a bonus */
831  tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 20 + 13);
832  }
833  }
834  else /* is_ipv6 implicitly */
835  {
836  clib_memcpy (&src, get_ptr_to_offset (b0, 22), 16);
837  clib_memcpy (&dst, get_ptr_to_offset (b0, 38), 16);
838  proto = acl_get_l4_proto (b0, 1);
839  if (58 == proto)
840  {
841  *trace_bitmap |= 0x00000002;
842  /* type */
843  src_port = (u16) (*(u8 *) get_ptr_to_offset (b0, 54));
844  /* code */
845  dst_port = (u16) (*(u8 *) get_ptr_to_offset (b0, 55));
846  }
847  else
848  {
849  /* assume TCP/UDP */
850  src_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 54)));
851  dst_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 56)));
852  tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 40 + 13);
853  }
854  }
855  if (pool_is_free_index (am->acls, acl_index))
856  {
857  if (r_acl_match_p)
858  *r_acl_match_p = acl_index;
859  if (r_rule_match_p)
860  *r_rule_match_p = -1;
861  /* the ACL does not exist but is used for policy. Block traffic. */
862  return 0;
863  }
864  a = am->acls + acl_index;
865  for (i = 0; i < a->count; i++)
866  {
867  r = a->rules + i;
868  if (is_ip6 != r->is_ipv6)
869  {
870  continue;
871  }
872  if (!acl_match_addr (&dst, &r->dst, r->dst_prefixlen, is_ip6))
873  continue;
874  if (!acl_match_addr (&src, &r->src, r->src_prefixlen, is_ip6))
875  continue;
876  if (r->proto)
877  {
878  if (proto != r->proto)
879  continue;
880  if (!acl_match_port
882  is_ip6))
883  continue;
884  if (!acl_match_port
886  is_ip6))
887  continue;
888  /* No need for check of proto == TCP, since in other rules both fields should be zero, so this match will succeed */
889  if ((tcp_flags & r->tcp_flags_mask) != r->tcp_flags_value)
890  continue;
891  }
892  /* everything matches! */
893  *r_action = r->is_permit;
894  *r_is_ip6 = is_ip6;
895  if (r_acl_match_p)
896  *r_acl_match_p = acl_index;
897  if (r_rule_match_p)
898  *r_rule_match_p = i;
899  return 1;
900  }
901  return 0;
902 }
903 
904 void
905 input_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
906  u32 * acl_match_p, u32 * rule_match_p,
907  u32 * trace_bitmap)
908 {
909  acl_main_t *am = &acl_main;
910  uint8_t action = 0;
911  int is_ip6 = 0;
912  int i;
913  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
914  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
915  i++)
916  {
917  if (acl_packet_match
918  (am, am->input_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
919  &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
920  {
921  if (is_ip6)
922  {
923  *nextp = am->acl_in_ip6_match_next[action];
924  }
925  else
926  {
927  *nextp = am->acl_in_ip4_match_next[action];
928  }
929  return;
930  }
931  }
932  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
933  {
934  /* If there are ACLs and none matched, deny by default */
935  *nextp = 0;
936  }
937 
938 }
939 
940 void
941 output_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
942  u32 * acl_match_p, u32 * rule_match_p,
943  u32 * trace_bitmap)
944 {
945  acl_main_t *am = &acl_main;
946  uint8_t action = 0;
947  int is_ip6 = 0;
948  int i;
949  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
950  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
951  i++)
952  {
953  if (acl_packet_match
954  (am, am->output_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
955  &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
956  {
957  if (is_ip6)
958  {
959  *nextp = am->acl_out_ip6_match_next[action];
960  }
961  else
962  {
963  *nextp = am->acl_out_ip4_match_next[action];
964  }
965  return;
966  }
967  }
968  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
969  {
970  /* If there are ACLs and none matched, deny by default */
971  *nextp = 0;
972  }
973 }
974 
975 typedef struct
976 {
978  u8 mac_mask[6];
984 
985 static u32
986 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
987  u8 is_ipv6)
988 {
989  u32 i;
990  if (mv)
991  {
992  for (i = 0; i < vec_len (mv); i++)
993  {
994  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
995  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
996  {
997  return i;
998  }
999  }
1000  }
1001  return ~0;
1002 }
1003 
1004 
1005 /* Get metric used to sort match types.
1006  The more specific and the more often seen - the bigger the metric */
1007 static int
1009 {
1010  /* FIXME: count the ones in the MAC mask as well, check how well this heuristic works in real life */
1011  return m->prefix_len + m->is_ipv6 + 10 * m->count;
1012 }
1013 
1014 static int
1016 {
1017  /* Ascending sort based on the metric values */
1018  return match_type_metric (m1) - match_type_metric (m2);
1019 }
1020 
1021 /* Get the offset of L3 source within ethernet packet */
1022 static int
1024 {
1025  if(is6)
1026  return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
1027  else
1028  return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
1029 }
1030 
1031 static int
1033 {
1034  macip_match_type_t *mvec = NULL;
1035  macip_match_type_t *mt;
1036  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
1037  int i;
1038  u32 match_type_index;
1039  u32 last_table;
1040  u8 mask[5 * 16];
1042 
1043  /* Count the number of different types of rules */
1044  for (i = 0; i < a->count; i++)
1045  {
1046  if (~0 ==
1047  (match_type_index =
1049  a->rules[i].src_prefixlen,
1050  a->rules[i].is_ipv6)))
1051  {
1052  match_type_index = vec_len (mvec);
1053  vec_validate (mvec, match_type_index);
1054  memcpy (mvec[match_type_index].mac_mask,
1055  a->rules[match_type_index].src_mac_mask, 6);
1056  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1057  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1058  mvec[match_type_index].table_index = ~0;
1059  }
1060  mvec[match_type_index].count++;
1061  }
1062  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1064  /* Create the classifier tables */
1065  last_table = ~0;
1066  /* First add ARP tables */
1067  vec_foreach (mt, mvec)
1068  {
1069  int mask_len;
1070  int is6 = mt->is_ipv6;
1071 
1072  mt->arp_table_index = ~0;
1073  if (!is6)
1074  {
1075  memset (mask, 0, sizeof (mask));
1076  memcpy (&mask[6], mt->mac_mask, 6);
1077  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1078  memcpy (&mask[14 + 8], mt->mac_mask, 6);
1079 
1080  for (i = 0; i < (mt->prefix_len / 8); i++)
1081  mask[14 + 14 + i] = 0xff;
1082  if (mt->prefix_len % 8)
1083  mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1084 
1085  mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
1086  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1087  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1088  (~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
1089  1);
1090  last_table = mt->arp_table_index;
1091  }
1092  }
1093  /* Now add IP[46] tables */
1094  vec_foreach (mt, mvec)
1095  {
1096  int mask_len;
1097  int is6 = mt->is_ipv6;
1098  int l3_src_offs = get_l3_src_offset(is6);
1099  memset (mask, 0, sizeof (mask));
1100  memcpy (&mask[6], mt->mac_mask, 6);
1101  for (i = 0; i < (mt->prefix_len / 8); i++)
1102  {
1103  mask[l3_src_offs + i] = 0xff;
1104  }
1105  if (mt->prefix_len % 8)
1106  {
1107  mask[l3_src_offs + (mt->prefix_len / 8)] =
1108  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1109  }
1110  /*
1111  * Round-up the number of bytes needed to store the prefix,
1112  * and round up the number of vectors too
1113  */
1114  mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
1115  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1116  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1117  (~0 == last_table) ? 0 : ~0, &mt->table_index,
1118  1);
1119  last_table = mt->table_index;
1120  }
1121  a->ip4_table_index = ~0;
1122  a->ip6_table_index = ~0;
1123  a->l2_table_index = last_table;
1124 
1125  /* Populate the classifier tables with rules from the MACIP ACL */
1126  for (i = 0; i < a->count; i++)
1127  {
1128  u32 action = 0;
1129  u32 metadata = 0;
1130  int is6 = a->rules[i].is_ipv6;
1131  int l3_src_offs = get_l3_src_offset(is6);
1132  memset (mask, 0, sizeof (mask));
1133  memcpy (&mask[6], a->rules[i].src_mac, 6);
1134  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1135  if (is6)
1136  {
1137  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1138  mask[12] = 0x86;
1139  mask[13] = 0xdd;
1140  }
1141  else
1142  {
1143  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1144  mask[12] = 0x08;
1145  mask[13] = 0x00;
1146  }
1147  match_type_index =
1149  a->rules[i].src_prefixlen,
1150  a->rules[i].is_ipv6);
1151  /* add session to table mvec[match_type_index].table_index; */
1152  vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
1153  mask, a->rules[i].is_permit ? ~0 : 0, i,
1154  0, action, metadata, 1);
1155  /* add ARP table entry too */
1156  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1157  {
1158  memset (mask, 0, sizeof (mask));
1159  memcpy (&mask[6], a->rules[i].src_mac, 6);
1160  mask[12] = 0x08;
1161  mask[13] = 0x06;
1162  memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
1163  memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
1164  vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
1165  mask, a->rules[i].is_permit ? ~0 : 0, i,
1166  0, action, metadata, 1);
1167  }
1168  }
1169  return 0;
1170 }
1171 
1172 static void
1174 {
1176  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
1177 
1178  if (a->ip4_table_index != ~0)
1179  {
1180  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip4_table_index, 0);
1181  a->ip4_table_index = ~0;
1182  }
1183  if (a->ip6_table_index != ~0)
1184  {
1185  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip6_table_index, 0);
1186  a->ip6_table_index = ~0;
1187  }
1188  if (a->l2_table_index != ~0)
1189  {
1190  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index, 0);
1191  a->l2_table_index = ~0;
1192  }
1193 }
1194 
1195 static int
1197  u32 * acl_list_index, u8 * tag)
1198 {
1199  acl_main_t *am = &acl_main;
1201  macip_acl_rule_t *r;
1202  macip_acl_rule_t *acl_new_rules;
1203  int i;
1204 
1205  /* Create and populate the rules */
1206  acl_new_rules = clib_mem_alloc_aligned (sizeof (macip_acl_rule_t) * count,
1208  if (!acl_new_rules)
1209  {
1210  /* Could not allocate rules. New or existing ACL - bail out regardless */
1211  return -1;
1212  }
1213 
1214  for (i = 0; i < count; i++)
1215  {
1216  r = &acl_new_rules[i];
1217  r->is_permit = rules[i].is_permit;
1218  r->is_ipv6 = rules[i].is_ipv6;
1219  memcpy (&r->src_mac, rules[i].src_mac, 6);
1220  memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
1221  if(rules[i].is_ipv6)
1222  memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
1223  else
1224  memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
1225  r->src_prefixlen = rules[i].src_ip_prefix_len;
1226  }
1227 
1228  /* Get ACL index */
1230  memset (a, 0, sizeof (*a));
1231  /* Will return the newly allocated ACL index */
1232  *acl_list_index = a - am->macip_acls;
1233 
1234  a->rules = acl_new_rules;
1235  a->count = count;
1236  memcpy (a->tag, tag, sizeof (a->tag));
1237 
1238  /* Create and populate the classifer tables */
1239  macip_create_classify_tables (am, *acl_list_index);
1240 
1241  return 0;
1242 }
1243 
1244 
1245 /* No check for validity of sw_if_index - the callers were supposed to validate */
1246 
1247 static int
1249 {
1250  int rv;
1251  u32 macip_acl_index;
1253  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1254  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1255  /* No point in deleting MACIP ACL which is not applied */
1256  if (~0 == macip_acl_index)
1257  return -1;
1258  a = &am->macip_acls[macip_acl_index];
1259  /* remove the classifier tables off the interface L2 ACL */
1260  rv =
1261  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1262  a->ip6_table_index, a->l2_table_index, 0);
1263  /* Unset the MACIP ACL index */
1264  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
1265  return rv;
1266 }
1267 
1268 /* No check for validity of sw_if_index - the callers were supposed to validate */
1269 
1270 static int
1272  u32 macip_acl_index)
1273 {
1275  int rv;
1276  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1277  {
1278  return -1;
1279  }
1280  a = &am->macip_acls[macip_acl_index];
1281  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1282  /* If there already a MACIP ACL applied, unapply it */
1283  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1284  macip_acl_interface_del_acl(am, sw_if_index);
1285  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1286  /* Apply the classifier tables for L2 ACLs */
1287  rv =
1288  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1289  a->ip6_table_index, a->l2_table_index, 1);
1290  return rv;
1291 }
1292 
1293 static int
1294 macip_acl_del_list (u32 acl_list_index)
1295 {
1296  acl_main_t *am = &acl_main;
1298  int i;
1299  if (pool_is_free_index (am->macip_acls, acl_list_index))
1300  {
1301  return -1;
1302  }
1303 
1304  /* delete any references to the ACL */
1305  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1306  {
1307  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1308  {
1310  }
1311  }
1312 
1313  /* Now that classifier tables are detached, clean them up */
1314  macip_destroy_classify_tables (am, acl_list_index);
1315 
1316  /* now we can delete the ACL itself */
1317  a = &am->macip_acls[acl_list_index];
1318  if (a->rules)
1319  {
1320  clib_mem_free (a->rules);
1321  }
1322  pool_put (am->macip_acls, a);
1323  return 0;
1324 }
1325 
1326 
1327 static int
1329  u32 acl_list_index)
1330 {
1331  acl_main_t *am = &acl_main;
1332  int rv = -1;
1333  if (is_add)
1334  {
1335  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1336  }
1337  else
1338  {
1339  rv = macip_acl_interface_del_acl (am, sw_if_index);
1340  }
1341  return rv;
1342 }
1343 
1344 /* API message handler */
1345 static void
1347 {
1349  acl_main_t *am = &acl_main;
1350  int rv;
1351  u32 acl_list_index = ntohl (mp->acl_index);
1352 
1353  rv = acl_add_list (ntohl (mp->count), mp->r, &acl_list_index, mp->tag);
1354 
1355  /* *INDENT-OFF* */
1356  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1357  ({
1358  rmp->acl_index = htonl(acl_list_index);
1359  }));
1360  /* *INDENT-ON* */
1361 }
1362 
1363 static void
1365 {
1366  acl_main_t *am = &acl_main;
1368  int rv;
1369 
1370  rv = acl_del_list (ntohl (mp->acl_index));
1371 
1372  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1373 }
1374 
1375 static void
1377 {
1378  acl_main_t *am = &acl_main;
1380  u32 sw_if_index = ntohl (mp->sw_if_index);
1382  int rv = -1;
1383 
1384  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1385  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1386  else
1387  rv =
1388  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1389  mp->is_input, ntohl (mp->acl_index));
1390 
1391  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1392 }
1393 
1394 static void
1397 {
1398  acl_main_t *am = &acl_main;
1400  int rv = 0;
1401  int i;
1403  u32 sw_if_index = ntohl (mp->sw_if_index);
1404 
1405  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1406  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1407  else
1408  {
1409  acl_interface_reset_inout_acls (sw_if_index, 0);
1410  acl_interface_reset_inout_acls (sw_if_index, 1);
1411 
1412  for (i = 0; i < mp->count; i++)
1413  {
1414  acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
1415  ntohl (mp->acls[i]));
1416  }
1417  }
1418 
1419  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1420 }
1421 
1422 static void
1424 {
1425  api_rule->is_permit = r->is_permit;
1426  api_rule->is_ipv6 = r->is_ipv6;
1427  if(r->is_ipv6)
1428  {
1429  memcpy (api_rule->src_ip_addr, &r->src, sizeof (r->src));
1430  memcpy (api_rule->dst_ip_addr, &r->dst, sizeof (r->dst));
1431  }
1432  else
1433  {
1434  memcpy (api_rule->src_ip_addr, &r->src.ip4, sizeof (r->src.ip4));
1435  memcpy (api_rule->dst_ip_addr, &r->dst.ip4, sizeof (r->dst.ip4));
1436  }
1437  api_rule->src_ip_prefix_len = r->src_prefixlen;
1438  api_rule->dst_ip_prefix_len = r->dst_prefixlen;
1439  api_rule->proto = r->proto;
1440  api_rule->srcport_or_icmptype_first = htons (r->src_port_or_type_first);
1441  api_rule->srcport_or_icmptype_last = htons (r->src_port_or_type_last);
1442  api_rule->dstport_or_icmpcode_first = htons (r->dst_port_or_code_first);
1443  api_rule->dstport_or_icmpcode_last = htons (r->dst_port_or_code_last);
1444  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1445  api_rule->tcp_flags_value = r->tcp_flags_value;
1446 }
1447 
1448 static void
1450  acl_list_t * acl, u32 context)
1451 {
1453  vl_api_acl_rule_t *rules;
1454  int i;
1455  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * acl->count;
1456 
1457  mp = vl_msg_api_alloc (msg_size);
1458  memset (mp, 0, msg_size);
1459  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
1460 
1461  /* fill in the message */
1462  mp->context = context;
1463  mp->count = htonl (acl->count);
1464  mp->acl_index = htonl (acl - am->acls);
1465  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1466  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
1467  rules = mp->r;
1468  for (i = 0; i < acl->count; i++)
1469  {
1470  copy_acl_rule_to_api_rule (&rules[i], &acl->rules[i]);
1471  }
1472 
1473  clib_warning("Sending acl details for ACL index %d", ntohl(mp->acl_index));
1474  vl_msg_api_send_shmem (q, (u8 *) & mp);
1475 }
1476 
1477 
1478 static void
1480 {
1481  acl_main_t *am = &acl_main;
1482  u32 acl_index;
1483  acl_list_t *acl;
1484 
1485  int rv = -1;
1487 
1489  if (q == 0)
1490  {
1491  return;
1492  }
1493 
1494  if (mp->acl_index == ~0)
1495  {
1496  /* *INDENT-OFF* */
1497  /* Just dump all ACLs */
1498  pool_foreach (acl, am->acls,
1499  ({
1500  send_acl_details(am, q, acl, mp->context);
1501  }));
1502  /* *INDENT-ON* */
1503  }
1504  else
1505  {
1506  acl_index = ntohl (mp->acl_index);
1507  if (!pool_is_free_index (am->acls, acl_index))
1508  {
1509  acl = &am->acls[acl_index];
1510  send_acl_details (am, q, acl, mp->context);
1511  }
1512  }
1513 
1514  if (rv == -1)
1515  {
1516  /* FIXME API: should we signal an error here at all ? */
1517  return;
1518  }
1519 }
1520 
1521 static void
1524  u32 sw_if_index, u32 context)
1525 {
1527  int msg_size;
1528  int n_input;
1529  int n_output;
1530  int count;
1531  int i = 0;
1532 
1533  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1534  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1535 
1536  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1537  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1538  count = n_input + n_output;
1539 
1540  msg_size = sizeof (*mp);
1541  msg_size += sizeof (mp->acls[0]) * count;
1542 
1543  mp = vl_msg_api_alloc (msg_size);
1544  memset (mp, 0, msg_size);
1545  mp->_vl_msg_id =
1546  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1547 
1548  /* fill in the message */
1549  mp->context = context;
1550  mp->sw_if_index = htonl (sw_if_index);
1551  mp->count = count;
1552  mp->n_input = n_input;
1553  for (i = 0; i < n_input; i++)
1554  {
1555  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
1556  }
1557  for (i = 0; i < n_output; i++)
1558  {
1559  mp->acls[n_input + i] =
1560  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
1561  }
1562 
1563  vl_msg_api_send_shmem (q, (u8 *) & mp);
1564 }
1565 
1566 static void
1568  mp)
1569 {
1570  acl_main_t *am = &acl_main;
1571  vnet_sw_interface_t *swif;
1573 
1574  u32 sw_if_index;
1576 
1578  if (q == 0)
1579  {
1580  return;
1581  }
1582 
1583  if (mp->sw_if_index == ~0)
1584  {
1585  /* *INDENT-OFF* */
1586  pool_foreach (swif, im->sw_interfaces,
1587  ({
1588  send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
1589  }));
1590  /* *INDENT-ON* */
1591  }
1592  else
1593  {
1594  sw_if_index = ntohl (mp->sw_if_index);
1595  if (!pool_is_free_index(im->sw_interfaces, sw_if_index))
1596  send_acl_interface_list_details (am, q, sw_if_index, mp->context);
1597  }
1598 }
1599 
1600 /* MACIP ACL API handlers */
1601 
1602 static void
1604 {
1606  acl_main_t *am = &acl_main;
1607  int rv;
1608  u32 acl_list_index = ~0;
1609 
1610  rv =
1611  macip_acl_add_list (ntohl (mp->count), mp->r, &acl_list_index, mp->tag);
1612 
1613  /* *INDENT-OFF* */
1614  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
1615  ({
1616  rmp->acl_index = htonl(acl_list_index);
1617  }));
1618  /* *INDENT-ON* */
1619 }
1620 
1621 static void
1623 {
1624  acl_main_t *am = &acl_main;
1626  int rv;
1627 
1628  rv = macip_acl_del_list (ntohl (mp->acl_index));
1629 
1630  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
1631 }
1632 
1633 static void
1636 {
1637  acl_main_t *am = &acl_main;
1639  int rv = -1;
1641  u32 sw_if_index = ntohl (mp->sw_if_index);
1642 
1643  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1644  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1645  else
1646  rv =
1648  ntohl (mp->acl_index));
1649 
1650  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
1651 }
1652 
1653 static void
1655  macip_acl_list_t * acl, u32 context)
1656 {
1658  vl_api_macip_acl_rule_t *rules;
1659  macip_acl_rule_t *r;
1660  int i;
1661  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
1662 
1663  mp = vl_msg_api_alloc (msg_size);
1664  memset (mp, 0, msg_size);
1665  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
1666 
1667  /* fill in the message */
1668  mp->context = context;
1669  if (acl)
1670  {
1671  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1672  mp->count = htonl (acl->count);
1673  mp->acl_index = htonl (acl - am->macip_acls);
1674  rules = mp->r;
1675  for (i = 0; i < acl->count; i++)
1676  {
1677  r = &acl->rules[i];
1678  rules[i].is_permit = r->is_permit;
1679  rules[i].is_ipv6 = r->is_ipv6;
1680  memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
1681  memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
1682  sizeof (r->src_mac_mask));
1683  if (r->is_ipv6)
1684  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
1685  sizeof (r->src_ip_addr.ip6));
1686  else
1687  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
1688  sizeof (r->src_ip_addr.ip4));
1689  rules[i].src_ip_prefix_len = r->src_prefixlen;
1690  }
1691  }
1692  else
1693  {
1694  /* No martini, no party - no ACL applied to this interface. */
1695  mp->acl_index = ~0;
1696  mp->count = 0;
1697  }
1698 
1699  vl_msg_api_send_shmem (q, (u8 *) & mp);
1700 }
1701 
1702 
1703 static void
1705 {
1706  acl_main_t *am = &acl_main;
1707  macip_acl_list_t *acl;
1708 
1710 
1712  if (q == 0)
1713  {
1714  return;
1715  }
1716 
1717  if (mp->acl_index == ~0)
1718  {
1719  /* Just dump all ACLs for now, with sw_if_index = ~0 */
1720  pool_foreach (acl, am->macip_acls, (
1721  {
1722  send_macip_acl_details (am, q, acl,
1723  mp->
1724  context);}
1725  ));
1726  /* *INDENT-ON* */
1727  }
1728  else
1729  {
1730  u32 acl_index = ntohl (mp->acl_index);
1731  if (!pool_is_free_index (am->macip_acls, acl_index))
1732  {
1733  acl = &am->macip_acls[acl_index];
1734  send_macip_acl_details (am, q, acl, mp->context);
1735  }
1736  }
1737 }
1738 
1739 static void
1741  mp)
1742 {
1743  acl_main_t *am = &acl_main;
1745  u32 count = vec_len (am->macip_acl_by_sw_if_index);
1746  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
1748  int i;
1749 
1751  if (q == 0)
1752  {
1753  return;
1754  }
1755 
1756  rmp = vl_msg_api_alloc (msg_size);
1757  memset (rmp, 0, msg_size);
1758  rmp->_vl_msg_id =
1759  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
1760  rmp->context = mp->context;
1761  rmp->count = htonl (count);
1762  for (i = 0; i < count; i++)
1763  {
1764  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
1765  }
1766 
1767  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1768 }
1769 
1770 /* Set up the API message handling tables */
1771 static clib_error_t *
1773 {
1774  acl_main_t *am = &acl_main;
1775 #define _(N,n) \
1776  vl_msg_api_set_handlers((VL_API_##N + am->msg_id_base), \
1777  #n, \
1778  vl_api_##n##_t_handler, \
1779  vl_noop_handler, \
1780  vl_api_##n##_t_endian, \
1781  vl_api_##n##_t_print, \
1782  sizeof(vl_api_##n##_t), 1);
1784 #undef _
1785 
1786  return 0;
1787 }
1788 
1789 #define vl_msg_name_crc_list
1790 #include <acl/acl_all_api_h.h>
1791 #undef vl_msg_name_crc_list
1792 
1793 static void
1795 {
1796 #define _(id,n,crc) \
1797  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + am->msg_id_base);
1798  foreach_vl_msg_name_crc_acl;
1799 #undef _
1800 }
1801 
1802 u32
1803 register_match_action_nexts (u32 next_in_ip4, u32 next_in_ip6,
1804  u32 next_out_ip4, u32 next_out_ip6)
1805 {
1806  acl_main_t *am = &acl_main;
1807  if (am->n_match_actions == 255)
1808  {
1809  return ~0;
1810  }
1811  u32 act = am->n_match_actions;
1812  am->n_match_actions++;
1813  am->acl_in_ip4_match_next[act] = next_in_ip4;
1814  am->acl_in_ip6_match_next[act] = next_in_ip6;
1815  am->acl_out_ip4_match_next[act] = next_out_ip4;
1816  am->acl_out_ip6_match_next[act] = next_out_ip6;
1817  return act;
1818 }
1819 
1820 void
1822 {
1824  acl_main_t *am = &acl_main;
1825  vlib_node_t *n;
1826 
1827  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
1829  vlib_node_add_next_with_slot (vm, n->index, acl_in_node.index, ~0);
1830  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
1832  vlib_node_add_next_with_slot (vm, n->index, acl_out_node.index, ~0);
1833 
1837 
1841 
1842  memset (&am->acl_in_ip4_match_next[0], 0,
1843  sizeof (am->acl_in_ip4_match_next));
1844  memset (&am->acl_in_ip6_match_next[0], 0,
1845  sizeof (am->acl_in_ip6_match_next));
1846  memset (&am->acl_out_ip4_match_next[0], 0,
1847  sizeof (am->acl_out_ip4_match_next));
1848  memset (&am->acl_out_ip6_match_next[0], 0,
1849  sizeof (am->acl_out_ip6_match_next));
1850  am->n_match_actions = 0;
1851 
1856 
1857  register_match_action_nexts (0, 0, 0, 0); /* drop */
1858  register_match_action_nexts (~0, ~0, ~0, ~0); /* permit */
1860 }
1861 
1862 void
1864 {
1866  acl_main_t *am = &acl_main;
1867  vlib_node_t *n, *n4, *n6;
1868 
1869  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
1870  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip4-l2");
1871  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-in-ip6-l2");
1872 
1873 
1875  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1877  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1878 
1882 
1886 
1887 
1888  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
1889  n4 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip4-l2");
1890  n6 = vlib_get_node_by_name (vm, (u8 *) "acl-plugin-out-ip6-l2");
1891 
1893  vlib_node_add_next_with_slot (vm, n->index, n4->index, ~0);
1895  vlib_node_add_next_with_slot (vm, n->index, n6->index, ~0);
1896 
1900 
1904 
1909 
1910 }
1911 
1912 void
1913 acl_set_timeout_sec(int timeout_type, u32 value)
1914 {
1915  acl_main_t *am = &acl_main;
1916  l2sess_main_t *sm = &l2sess_main;
1917  clib_time_t *ct = &am->vlib_main->clib_time;
1918 
1919  if (timeout_type < ACL_N_TIMEOUTS) {
1920  am->session_timeout_sec[timeout_type] = value;
1921  } else {
1922  clib_warning("Unknown timeout type %d", timeout_type);
1923  return;
1924  }
1925 
1926  switch(timeout_type) {
1927  case ACL_TIMEOUT_UDP_IDLE:
1928  sm->udp_session_idle_timeout = (u64)(((f64)value)/ct->seconds_per_clock);
1929  break;
1930  case ACL_TIMEOUT_TCP_IDLE:
1931  sm->tcp_session_idle_timeout = (u64)(((f64)value)/ct->seconds_per_clock);
1932  break;
1935  break;
1936  default:
1937  clib_warning("Unknown timeout type %d", timeout_type);
1938  }
1939 }
1940 
1941 void
1943 {
1944  acl_main_t *am = &acl_main;
1945  am->fa_conn_table_max_entries = value;
1946 }
1947 
1948 int
1950 {
1951  acl_main_t *am = &acl_main;
1952  if ((eh < 256) && (value < 2))
1953  {
1955  return 1;
1956  }
1957  else
1958  return 0;
1959 }
1960 
1961 
1962 static clib_error_t *
1963 acl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
1964 {
1965  acl_main_t *am = &acl_main;
1966  if (0 == is_add) {
1969  /* also unapply any ACLs in case the users did not do so. */
1970  macip_acl_interface_del_acl(am, sw_if_index);
1971  acl_interface_reset_inout_acls (sw_if_index, 0);
1972  acl_interface_reset_inout_acls (sw_if_index, 1);
1973  }
1974  return 0;
1975 }
1976 
1978 
1979 static clib_error_t *
1981  unformat_input_t * input,
1982  vlib_cli_command_t * cmd)
1983 {
1984  clib_error_t *error = 0;
1985  u32 timeout = 0;
1986  u32 val = 0;
1987  u32 eh_val = 0;
1988  uword memory_size = 0;
1989  acl_main_t *am = &acl_main;
1990 
1991  /* The new datapath is the default. This command exists out of precaution and for comparing the two */
1992  if (unformat (input, "l2-datapath")) {
1993  if (unformat(input, "old")) {
1998  goto done;
1999  }
2000  if (unformat(input, "new")) {
2005  goto done;
2006  }
2007  goto done;
2008  }
2009  if (unformat (input, "skip-ipv6-extension-header %u %u", &eh_val, &val)) {
2010  if(!acl_set_skip_ipv6_eh(eh_val, val)) {
2011  error = clib_error_return(0, "expecting eh=0..255, value=0..1");
2012  }
2013  goto done;
2014  }
2015  if (unformat (input, "l4-match-nonfirst-fragment %u", &val))
2016  {
2017  am->l4_match_nonfirst_fragment = (val != 0);
2018  goto done;
2019  }
2020  if (unformat (input, "session")) {
2021  if (unformat (input, "clear")) {
2022  acl_main_t *am = &acl_main;
2025  goto done;
2026  }
2027  if (unformat (input, "table")) {
2028  /* The commands here are for tuning/testing. No user-serviceable parts inside */
2029  if (unformat (input, "max-entries")) {
2030  if (!unformat(input, "%u", &val)) {
2031  error = clib_error_return(0,
2032  "expecting maximum number of entries, got `%U`",
2033  format_unformat_error, input);
2034  goto done;
2035  } else {
2037  goto done;
2038  }
2039  }
2040  if (unformat (input, "hash-table-buckets")) {
2041  if (!unformat(input, "%u", &val)) {
2042  error = clib_error_return(0,
2043  "expecting maximum number of hash table buckets, got `%U`",
2044  format_unformat_error, input);
2045  goto done;
2046  } else {
2048  goto done;
2049  }
2050  }
2051  if (unformat (input, "hash-table-memory")) {
2052  if (!unformat(input, "%U", unformat_memory_size, &memory_size)) {
2053  error = clib_error_return(0,
2054  "expecting maximum amount of hash table memory, got `%U`",
2055  format_unformat_error, input);
2056  goto done;
2057  } else {
2059  goto done;
2060  }
2061  }
2062  goto done;
2063  }
2064  if (unformat (input, "timeout")) {
2065  if (unformat(input, "udp")) {
2066  if(unformat(input, "idle")) {
2067  if (!unformat(input, "%u", &timeout)) {
2068  error = clib_error_return(0,
2069  "expecting timeout value in seconds, got `%U`",
2070  format_unformat_error, input);
2071  goto done;
2072  } else {
2074  goto done;
2075  }
2076  }
2077  }
2078  if (unformat(input, "tcp")) {
2079  if(unformat(input, "idle")) {
2080  if (!unformat(input, "%u", &timeout)) {
2081  error = clib_error_return(0,
2082  "expecting timeout value in seconds, got `%U`",
2083  format_unformat_error, input);
2084  goto done;
2085  } else {
2087  goto done;
2088  }
2089  }
2090  if(unformat(input, "transient")) {
2091  if (!unformat(input, "%u", &timeout)) {
2092  error = clib_error_return(0,
2093  "expecting timeout value in seconds, got `%U`",
2094  format_unformat_error, input);
2095  goto done;
2096  } else {
2098  goto done;
2099  }
2100  }
2101  }
2102  goto done;
2103  }
2104  }
2105 done:
2106  return error;
2107 }
2108 
2109 static clib_error_t *
2111  unformat_input_t * input,
2112  vlib_cli_command_t * cmd)
2113 {
2114  clib_error_t *error = 0;
2115  acl_main_t *am = &acl_main;
2117 
2118  vnet_sw_interface_t *swif;
2119 
2120  if (unformat (input, "sessions"))
2121  {
2122  u8 * out0 = 0;
2123  pool_foreach (swif, im->sw_interfaces,
2124  ({
2125  u32 sw_if_index = swif->sw_if_index;
2126  u64 n_adds = sw_if_index < vec_len(am->fa_session_adds_by_sw_if_index) ? am->fa_session_adds_by_sw_if_index[sw_if_index] : 0;
2127  u64 n_dels = sw_if_index < vec_len(am->fa_session_dels_by_sw_if_index) ? am->fa_session_dels_by_sw_if_index[sw_if_index] : 0;
2128  out0 = format(out0, "sw_if_index %d: add %lu - del %lu = %lu\n", sw_if_index, n_adds, n_dels, n_adds - n_dels);
2129  }));
2130  out0 = format(out0, "\n\nConn cleaner thread counters:\n");
2131 #define _(cnt, desc) out0 = format(out0, " %20lu: %s\n", am->cnt, desc);
2133 #undef _
2134  vlib_cli_output(vm, "\n\n%s\n\n", out0);
2135  vlib_cli_output(vm, "Sessions per interval: min %lu max %lu increment: %f ms current: %f ms",
2138 
2139  vec_free(out0);
2140  }
2141  return error;
2142 }
2143 
2144 
2145  /* *INDENT-OFF* */
2146 VLIB_CLI_COMMAND (aclplugin_set_command, static) = {
2147  .path = "set acl-plugin",
2148  .short_help = "set acl-plugin session timeout {{udp idle}|tcp {idle|transient}} <seconds>",
2149  .function = acl_set_aclplugin_fn,
2150 };
2151 
2152 VLIB_CLI_COMMAND (aclplugin_show_command, static) = {
2153  .path = "show acl-plugin",
2154  .short_help = "show acl-plugin sessions",
2155  .function = acl_show_aclplugin_fn,
2156 };
2157 /* *INDENT-ON* */
2158 
2159 
2160 
2161 static clib_error_t *
2163 {
2164  acl_main_t *am = &acl_main;
2165  clib_error_t *error = 0;
2166  memset (am, 0, sizeof (*am));
2167  am->vlib_main = vm;
2168  am->vnet_main = vnet_get_main ();
2169 
2170  u8 *name = format (0, "acl_%08x%c", api_version, 0);
2171 
2172  /* Ask for a correctly-sized block of API message decode slots */
2173  am->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
2175 
2176  error = acl_plugin_api_hookup (vm);
2177  acl_setup_nodes ();
2178 
2179  /* Add our API messages to the global name_crc hash table */
2181 
2182  vec_free (name);
2183 
2188 
2192 
2193  {
2194  u8 tt;
2195  for(tt = 0; tt < ACL_N_TIMEOUTS; tt++) {
2196  am->fa_conn_list_head[tt] = ~0;
2197  am->fa_conn_list_tail[tt] = ~0;
2198  }
2199  }
2200 
2204 
2205  am->fa_cleaner_cnt_delete_by_sw_index = 0;
2206  am->fa_cleaner_cnt_delete_by_sw_index_ok = 0;
2207  am->fa_cleaner_cnt_unknown_event = 0;
2208  am->fa_cleaner_cnt_deleted_sessions = 0;
2209  am->fa_cleaner_cnt_timer_restarted = 0;
2210  am->fa_cleaner_cnt_wait_with_timeout = 0;
2211 
2212 
2213 #define _(N, v, s) am->fa_ipv6_known_eh_bitmap = clib_bitmap_set(am->fa_ipv6_known_eh_bitmap, v, 1);
2215 #undef _
2216 
2218 
2219  return error;
2220 }
2221 
acl_rule_t * rules
Definition: acl.h:94
#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:101
u32 * acl_ip4_output_classify_table_by_sw_if_index
Definition: acl.h:125
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1271
u8 src_mac[6]
Definition: acl.h:81
u32 fa_cleaner_node_index
Definition: acl.h:156
u32 session_timeout_sec[ACL_N_TIMEOUTS]
Definition: acl.h:158
Use acl_interface_set_acl_list instead Append/remove an ACL index to/from the list of ACLs checked fo...
Definition: acl.api:193
u32 fa_acl_in_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:176
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1328
static int acl_hook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:501
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:1654
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
static clib_error_t * acl_init(vlib_main_t *vm)
Definition: acl.c:2162
int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:586
u8 is_ipv6
Definition: acl.h:63
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:633
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:88
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:561
void acl_setup_fa_nodes(void)
Definition: acl.c:1863
u64 fa_current_cleaner_timer_wait_interval
Definition: acl.h:211
void output_acl_packet_match(u32 sw_if_index, vlib_buffer_t *b0, u32 *nextp, u32 *acl_match_p, u32 *rule_match_p, u32 *trace_bitmap)
Definition: acl.c:941
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:227
static clib_error_t * acl_show_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:2110
#define foreach_acl_plugin_api_msg
Definition: acl.c:66
u8 tcp_flags_mask
Definition: acl.api:94
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:116
u16 msg_id_base
Definition: acl.h:110
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:284
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:322
void acl_setup_nodes(void)
Definition: acl.c:1821
static int count_skip(u8 *p, u32 size)
Definition: acl.c:301
vnet_interface_main_t interface_main
Definition: vnet.h:57
static void vl_api_acl_add_replace_t_handler(vl_api_acl_add_replace_t *mp)
Definition: acl.c:1346
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:1704
u32 acl_out_node_feat_next_node_index[32]
Definition: acl.h:137
int l4_match_nonfirst_fragment
Definition: acl.h:185
u8 src_ip_addr[16]
Definition: acl.api:67
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_NUM_BUCKETS
Definition: fa_node.h:18
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:31
#define REPLY_MACRO2(t, body)
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:237
static void vl_api_macip_acl_add_t_handler(vl_api_macip_acl_add_t *mp)
Definition: acl.c:1603
f64 clocks_per_second
Definition: time.h:53
u8 dst_prefixlen
Definition: acl.h:67
u32 * acl_ip6_input_classify_table_by_sw_if_index
Definition: acl.h:124
u32 acl_in_ip4_match_next[256]
Definition: acl.h:141
u32 count
Definition: acl.h:93
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u32 l2_table_index
Definition: acl.h:105
u32 fa_conn_list_tail[ACL_N_TIMEOUTS]
Definition: acl.h:213
void vnet_l2_input_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
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
u32 l2_input_classify_next_acl_ip4
Definition: acl.h:166
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
Access List Rule entry.
Definition: acl.api:63
clib_time_t clib_time
Definition: main.h:62
u16 dstport_or_icmpcode_last
Definition: acl.api:88
Delete a MACIP ACL.
Definition: acl.api:344
vlib_node_registration_t acl_out_node
(constructor) VLIB_REGISTER_NODE (acl_out_node)
Definition: node_out.c:155
static u32 macip_find_match_type(macip_match_type_t *mv, u8 *mac_mask, u8 prefix_len, u8 is_ipv6)
Definition: acl.c:986
u32 table_index
Definition: acl.c:981
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Details about one MACIP ACL.
Definition: acl.api:412
u32 fa_acl_out_ip4_l2_node_feat_next_node_index[32]
Definition: acl.h:178
f64 fa_cleaner_wait_time_increment
Definition: acl.h:209
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
u32 fa_l2_output_classify_next_acl_ip4
Definition: acl.h:173
api_main_t api_main
Definition: api_shared.c:35
uword fa_conn_table_hash_memory_size
Definition: acl.h:189
u16 dst_port_or_code_last
Definition: acl.h:72
static clib_error_t * acl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: acl.c:1963
u8 src_mac_mask[6]
Definition: acl.h:82
static int acl_match_addr(ip46_address_t *addr1, ip46_address_t *addr2, int prefixlen, int is_ip6)
Definition: acl.c:741
u32 l2_output_classify_next_acl_ip4
Definition: acl.h:168
u8 src_prefixlen
Definition: acl.h:65
ip46_address_t src_ip_addr
Definition: acl.h:83
u32 fa_conn_list_head[ACL_N_TIMEOUTS]
Definition: acl.h:212
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:66
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u16 dstport_or_icmpcode_first
Definition: acl.api:87
u64 fa_conn_table_max_entries
Definition: acl.h:190
vnet_main_t * vnet_main
Definition: acl.h:234
unsigned long long u32x4
Definition: ixge.c:28
ip46_address_t src
Definition: acl.h:64
u8 src_ip_prefix_len
Definition: acl.api:68
u8 tcp_flags_value
Definition: acl.api:95
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:156
Add or delete a MACIP ACL to/from interface.
Definition: acl.api:370
#define clib_error_return(e, args...)
Definition: error.h:111
u8 src_prefixlen
Definition: acl.h:84
u8 is_permit
Definition: acl.h:62
void input_acl_packet_match(u32 sw_if_index, vlib_buffer_t *b0, u32 *nextp, u32 *acl_match_p, u32 *rule_match_p, u32 *trace_bitmap)
Definition: acl.c:905
#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:978
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(acl_sw_interface_add_del)
u32 ip4_table_index
Definition: acl.h:103
u32 n_match_actions
Definition: acl.h:145
static int acl_match_port(u16 port, u16 port_first, u16 port_last, int is_ip6)
Definition: acl.c:779
u32 fa_acl_out_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:179
u32 * acl_ip4_input_classify_table_by_sw_if_index
Definition: acl.h:123
ip46_address_t dst
Definition: acl.h:66
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:367
u32 acl_in_node_feat_next_node_index[32]
Definition: acl.h:136
Reply to add MACIP ACL.
Definition: acl.api:331
static int acl_hook_l2_input_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:443
static void setup_message_id_table(acl_main_t *am, api_main_t *apim)
Definition: acl.c:1794
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:930
VLIB_PLUGIN_REGISTER()
#define ACL_FA_DEFAULT_CLEANER_WAIT_TIME_INCREMENT
Definition: acl.h:208
u16 dst_port_or_code_first
Definition: acl.h:71
u32 fa_l2_input_classify_next_acl_ip4
Definition: acl.h:171
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:1479
#define v
Definition: acl.c:246
struct _unformat_input_t unformat_input_t
uword * fa_ipv6_known_eh_bitmap
Definition: acl.h:182
Replace an existing ACL in-place or create a new ACL.
Definition: acl.api:135
#define ACL_FA_DEFAULT_MIN_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:205
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
Details about a single ACL contents.
Definition: acl.api:299
#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:142
static int get_l3_src_offset(int is6)
Definition: acl.c:1023
f64 seconds_per_clock
Definition: time.h:57
u32 fa_l2_output_classify_next_acl_ip6
Definition: acl.h:174
u32 l2_input_classify_next_acl_ip6
Definition: acl.h:167
vlib_node_registration_t acl_in_node
(constructor) VLIB_REGISTER_NODE (acl_in_node)
Definition: node_in.c:154
u8 proto
Definition: acl.h:68
u8 dst_ip_addr[16]
Definition: acl.api:69
static void send_acl_details(acl_main_t *am, unix_shared_memory_queue_t *q, acl_list_t *acl, u32 context)
Definition: acl.c:1449
u16 src_port_or_type_first
Definition: acl.h:69
u64 fa_min_deleted_sessions_per_interval
Definition: acl.h:206
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:1015
u32 fa_l2_input_classify_next_acl_ip6
Definition: acl.h:172
#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:275
static int acl_unhook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:405
Reply to alter the ACL list.
Definition: acl.api:212
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:1008
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1294
Dump one or all defined MACIP ACLs.
Definition: acl.api:397
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:341
void * vl_msg_api_alloc(int nbytes)
vlib_main_t * vm
Definition: buffer.c:276
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
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
static int acl_classify_add_del_table_big(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:316
u32 register_match_action_nexts(u32 next_in_ip4, u32 next_in_ip6, u32 next_out_ip4, u32 next_out_ip6)
Definition: acl.c:1803
u16 srcport_or_icmptype_first
Definition: acl.api:85
Reply to add/replace ACL.
Definition: acl.api:151
#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:612
u64 memory_size
Definition: vhost-user.h:78
Definition: acl.h:60
Reply with the vector of MACIP ACLs by sw_if_index.
Definition: acl.api:438
#define clib_memcpy(a, b, c)
Definition: string.h:69
void acl_set_timeout_sec(int timeout_type, u32 value)
Definition: acl.c:1913
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.
#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:217
void acl_fa_enable_disable(u32 sw_if_index, int is_input, int enable_disable)
Definition: fa_node.c:1284
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:80
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:69
u16 srcport_or_icmptype_last
Definition: acl.api:86
static void vl_api_acl_interface_add_del_t_handler(vl_api_acl_interface_add_del_t *mp)
Definition: acl.c:1376
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1248
unsigned int u32
Definition: types.h:88
u8 tag[64]
Definition: acl.h:92
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:1622
u16 src_port_or_type_last
Definition: acl.h:70
MACIP Access List Rule entry.
Definition: acl.api:107
static int macip_create_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1032
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:1522
static int acl_packet_match(acl_main_t *am, u32 acl_index, vlib_buffer_t *b0, u8 *r_action, int *r_is_ip6, u32 *r_acl_match_p, u32 *r_rule_match_p, u32 *trace_bitmap)
Definition: acl.c:785
u64 size
Definition: vhost-user.h:77
static void clib_mem_free(void *p)
Definition: mem.h:176
u32 l2_output_classify_next_acl_old
Definition: acl.h:133
l2sess_main_t l2sess_main
Definition: l2sess.h:139
u8 dst_ip_prefix_len
Definition: acl.api:70
acl_main_t acl_main
Definition: acl.c:59
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
Delete an ACL.
Definition: acl.api:164
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:1772
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1196
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:418
u32 acl_out_ip6_match_next[256]
Definition: acl.h:144
u32 fa_acl_in_ip6_l2_node_feat_next_node_index[32]
Definition: acl.h:177
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Dump the specific ACL contents or all of the ACLs&#39; contents.
Definition: acl.api:254
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)
template key/value backing page structure
Definition: bihash_doc.h:44
u32 * macip_acl_by_sw_if_index
Definition: acl.h:129
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:426
#define XX
Definition: acl.c:243
u32 * acl_ip6_output_classify_table_by_sw_if_index
Definition: acl.h:126
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:1567
static int acl_add_list(u32 count, vl_api_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:114
#define UDP_SESSION_IDLE_TIMEOUT_SEC
Definition: l2sess.h:82
unsigned short u16
Definition: types.h:57
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1364
macip_acl_list_t * macip_acls
Definition: acl.h:113
#define TCP_SESSION_IDLE_TIMEOUT_SEC
Definition: l2sess.h:83
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
static void * get_ptr_to_offset(vlib_buffer_t *b0, int offset)
Definition: acl.c:717
unsigned char u8
Definition: types.h:56
Details about a single ACL contents.
Definition: acl.api:269
u32 ip6_table_index
Definition: acl.h:104
Reply to apply/unapply the MACIP ACL.
Definition: acl.api:385
u32 l2_input_classify_next_acl_old
Definition: acl.h:132
u8 tcp_flags_mask
Definition: acl.h:74
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
Reply to delete the ACL.
Definition: acl.api:176
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:617
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:1396
u64 fa_max_deleted_sessions_per_interval
Definition: acl.h:198
static clib_error_t * acl_set_aclplugin_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: acl.c:1980
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:680
struct clib_bihash_value offset
template key/value backing page structure
u32 acl_in_ip6_match_next[256]
Definition: acl.h:142
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
u64 udp_session_idle_timeout
Definition: l2sess.h:123
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:698
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 tcp_flags_value
Definition: acl.h:73
Get the plugin version.
Definition: acl.api:28
static void copy_acl_rule_to_api_rule(vl_api_acl_rule_t *api_rule, acl_rule_t *r)
Definition: acl.c:1423
Reply to delete the MACIP ACL.
Definition: acl.api:356
u64 tcp_session_transient_timeout
Definition: l2sess.h:121
#define vec_foreach(var, vec)
Vector iterator.
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 acl_out_ip4_match_next[256]
Definition: acl.h:143
u16 vl_msg_api_get_msg_ids(char *name, int n)
Definition: api_shared.c:831
Add a MACIP ACL.
Definition: acl.api:316
Definition: acl.h:90
u32 client_index
Definition: acl.api:256
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:30
u8 tag[64]
Definition: acl.h:99
Reply to set the ACL list on an interface.
Definition: acl.api:242
#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:169
u8 ip6_5tuple_mask[]
Definition: acl.c:276
void acl_set_session_max_entries(u32 value)
Definition: acl.c:1942
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
#define ACL_FA_DEFAULT_MAX_DELETED_SESSIONS_PER_INTERVAL
Definition: acl.h:197
acl_list_t * acls
Definition: acl.h:112
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:117
u64 tcp_session_idle_timeout
Definition: l2sess.h:122
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC
Definition: l2sess.h:84
u8 is_permit
Definition: acl.h:79
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:1635
u32 arp_table_index
Definition: acl.c:982
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
u32 fa_conn_table_hash_num_buckets
Definition: acl.h:188
int acl_set_skip_ipv6_eh(u32 eh, u32 value)
Definition: acl.c:1949
#define ACL_FA_CONN_TABLE_DEFAULT_HASH_MEMORY_SIZE
Definition: fa_node.h:19
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:190
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1173
static u8 acl_get_l4_proto(vlib_buffer_t *b0, int node_is_ip6)
Definition: acl.c:724
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:1740
u8 ip4_5tuple_mask[]
Definition: acl.c:248
foreach_fa_cleaner_counter vlib_main_t * vlib_main
Definition: acl.h:233