FD.io VPP  v17.01.1-3-gc6833f8
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 
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 "node_in.h"
55 #include "node_out.h"
56 
58 
59 /*
60  * A handy macro to set up a message reply.
61  * Assumes that the following variables are available:
62  * mp - pointer to request message
63  * rmp - pointer to reply message type
64  * rv - return value
65  */
66 
67 #define REPLY_MACRO(t) \
68 do { \
69  unix_shared_memory_queue_t * q = \
70  vl_api_client_index_to_input_queue (mp->client_index); \
71  if (!q) \
72  return; \
73  \
74  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
75  rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \
76  rmp->context = mp->context; \
77  rmp->retval = ntohl(rv); \
78  \
79  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
80 } while(0);
81 
82 #define REPLY_MACRO2(t, body) \
83 do { \
84  unix_shared_memory_queue_t * q; \
85  rv = vl_msg_api_pd_handler (mp, rv); \
86  q = vl_api_client_index_to_input_queue (mp->client_index); \
87  if (!q) \
88  return; \
89  \
90  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
91  rmp->_vl_msg_id = ntohs((t)+am->msg_id_base); \
92  rmp->context = mp->context; \
93  rmp->retval = ntohl(rv); \
94  do {body;} while (0); \
95  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
96 } while(0);
97 
98 #define REPLY_MACRO3(t, n, body) \
99 do { \
100  unix_shared_memory_queue_t * q; \
101  rv = vl_msg_api_pd_handler (mp, rv); \
102  q = vl_api_client_index_to_input_queue (mp->client_index); \
103  if (!q) \
104  return; \
105  \
106  rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \
107  rmp->_vl_msg_id = ntohs((t)+am->msg_id_base); \
108  rmp->context = mp->context; \
109  rmp->retval = ntohl(rv); \
110  do {body;} while (0); \
111  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
112 } while(0);
113 
114 
115 /* List of message types that this plugin understands */
116 
117 #define foreach_acl_plugin_api_msg \
118 _(ACL_PLUGIN_GET_VERSION, acl_plugin_get_version) \
119 _(ACL_ADD_REPLACE, acl_add_replace) \
120 _(ACL_DEL, acl_del) \
121 _(ACL_INTERFACE_ADD_DEL, acl_interface_add_del) \
122 _(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list) \
123 _(ACL_DUMP, acl_dump) \
124 _(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump) \
125 _(MACIP_ACL_ADD, macip_acl_add) \
126 _(MACIP_ACL_DEL, macip_acl_del) \
127 _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
128 _(MACIP_ACL_DUMP, macip_acl_dump) \
129 _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get)
130 
131 /*
132  * This routine exists to convince the vlib plugin framework that
133  * we haven't accidentally copied a random .dll into the plugin directory.
134  *
135  * Also collects global variable pointers passed from the vpp engine
136  */
137 
138 clib_error_t *
140  int from_early_init)
141 {
142  acl_main_t *am = &acl_main;
143  clib_error_t *error = 0;
144 
145  am->vlib_main = vm;
146  am->vnet_main = h->vnet_main;
147  am->ethernet_main = h->ethernet_main;
148 
149  l2sess_vlib_plugin_register(vm, h, from_early_init);
150 
151  return error;
152 }
153 
154 
155 static void
157 {
158  acl_main_t *am = &acl_main;
160  int msg_size = sizeof (*rmp);
162 
164  if (q == 0)
165  {
166  return;
167  }
168 
169  rmp = vl_msg_api_alloc (msg_size);
170  memset (rmp, 0, msg_size);
171  rmp->_vl_msg_id =
172  ntohs (VL_API_ACL_PLUGIN_GET_VERSION_REPLY + am->msg_id_base);
173  rmp->context = mp->context;
174  rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
175  rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
176 
177  vl_msg_api_send_shmem (q, (u8 *) & rmp);
178 }
179 
180 
181 static int
183  u32 * acl_list_index, u8 * tag)
184 {
185  acl_main_t *am = &acl_main;
186  acl_list_t *a;
187  acl_rule_t *r;
188  acl_rule_t *acl_new_rules;
189  int i;
190 
191  if (*acl_list_index != ~0)
192  {
193  /* They supplied some number, let's see if this ACL exists */
194  if (pool_is_free_index (am->acls, *acl_list_index))
195  {
196  /* tried to replace a non-existent ACL, no point doing anything */
197  return -1;
198  }
199  }
200 
201  /* Create and populate the rules */
202  acl_new_rules = clib_mem_alloc_aligned (sizeof (acl_rule_t) * count,
204  if (!acl_new_rules)
205  {
206  /* Could not allocate rules. New or existing ACL - bail out regardless */
207  return -1;
208  }
209 
210  for (i = 0; i < count; i++)
211  {
212  r = &acl_new_rules[i];
213  r->is_permit = rules[i].is_permit;
214  r->is_ipv6 = rules[i].is_ipv6;
215  if (r->is_ipv6)
216  {
217  memcpy (&r->src, rules[i].src_ip_addr, sizeof (r->src));
218  memcpy (&r->dst, rules[i].dst_ip_addr, sizeof (r->dst));
219  }
220  else
221  {
222  memcpy (&r->src.ip4, rules[i].src_ip_addr, sizeof (r->src.ip4));
223  memcpy (&r->dst.ip4, rules[i].dst_ip_addr, sizeof (r->dst.ip4));
224  }
225  r->src_prefixlen = rules[i].src_ip_prefix_len;
226  r->dst_prefixlen = rules[i].dst_ip_prefix_len;
227  r->proto = rules[i].proto;
232  r->tcp_flags_value = rules[i].tcp_flags_value;
233  r->tcp_flags_mask = rules[i].tcp_flags_mask;
234  }
235 
236  if (~0 == *acl_list_index)
237  {
238  /* Get ACL index */
240  memset (a, 0, sizeof (*a));
241  /* Will return the newly allocated ACL index */
242  *acl_list_index = a - am->acls;
243  }
244  else
245  {
246  a = am->acls + *acl_list_index;
247  /* Get rid of the old rules */
248  clib_mem_free (a->rules);
249  }
250  a->rules = acl_new_rules;
251  a->count = count;
252  memcpy (a->tag, tag, sizeof (a->tag));
253 
254  return 0;
255 }
256 
257 static int
258 acl_del_list (u32 acl_list_index)
259 {
260  acl_main_t *am = &acl_main;
261  acl_list_t *a;
262  int i, ii;
263  if (pool_is_free_index (am->acls, acl_list_index))
264  {
265  return -1;
266  }
267 
268  /* delete any references to the ACL */
269  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index); i++)
270  {
271  for (ii = 0; ii < vec_len (am->output_acl_vec_by_sw_if_index[i]);
272  /* see body */ )
273  {
274  if (acl_list_index == am->output_acl_vec_by_sw_if_index[i][ii])
275  {
277  }
278  else
279  {
280  ii++;
281  }
282  }
283  }
284  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index); i++)
285  {
286  for (ii = 0; ii < vec_len (am->input_acl_vec_by_sw_if_index[i]);
287  /* see body */ )
288  {
289  if (acl_list_index == am->input_acl_vec_by_sw_if_index[i][ii])
290  {
292  }
293  else
294  {
295  ii++;
296  }
297  }
298  }
299 
300  /* now we can delete the ACL itself */
301  a = &am->acls[acl_list_index];
302  if (a->rules)
303  {
304  clib_mem_free (a->rules);
305  }
306  pool_put (am->acls, a);
307  return 0;
308 }
309 
310 /* Some aids in ASCII graphing the content */
311 #define XX "\377"
312 #define __ "\000"
313 #define _(x)
314 #define v
315 
317 _(" dmac smac etype ")
318 _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
319  _(" v ihl totlen ")
320  _(0x0000)
321  __ __ __ __
322  _(" ident fl+fo ")
323  _(0x0004)
324  __ __ __ __
325  _(" ttl pr checksum ")
326  _(0x0008)
327  __ XX __ __
328  _(" src address ")
329  _(0x000C)
330  XX XX XX XX
331  _(" dst address ")
332  _(0x0010)
333  XX XX XX XX
334  _("L4 T/U sport dport ")
335  _(tcpudp)
336  XX XX XX XX
337  _(padpad)
338  __ __ __ __
339  _(padpad)
340  __ __ __ __
341  _(padeth)
342  __ __;
343 
345  _(" dmac smac etype ")
346  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
347  _(" v tc + flow ")
348  _(0x0000) __ __ __ __
349  _(" plen nh hl ")
350  _(0x0004) __ __ XX __
351  _(" src address ")
352  _(0x0008) XX XX XX XX
353  _(0x000C) XX XX XX XX
354  _(0x0010) XX XX XX XX
355  _(0x0014) XX XX XX XX
356  _(" dst address ")
357  _(0x0018) XX XX XX XX
358  _(0x001C) XX XX XX XX
359  _(0x0020) XX XX XX XX
360  _(0x0024) XX XX XX XX
361  _("L4T/U sport dport ")
362  _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
363 
364 #undef XX
365 #undef __
366 #undef _
367 #undef v
368 
369  static int count_skip (u8 * p, u32 size)
370 {
371  u64 *p64 = (u64 *) p;
372  /* Be tolerant to null pointer */
373  if (0 == p)
374  return 0;
375 
376  while ((0ULL == *p64) && ((u8 *) p64 - p) < size)
377  {
378  p64++;
379  }
380  return (p64 - (u64 *) p) / 2;
381 }
382 
383 static int
385  u32 mask_len, u32 next_table_index,
386  u32 miss_next_index, u32 * table_index,
387  int is_add)
388 {
389  u32 nbuckets = 65536;
390  u32 memory_size = 2 << 30;
391  u32 skip = count_skip (mask, mask_len);
392  u32 match = (mask_len / 16) - skip;
393  u8 *skip_mask_ptr = mask + 16 * skip;
394  u32 current_data_flag = 0;
395  int current_data_offset = 0;
396 
397  if (0 == match)
398  match = 1;
399 
400  return vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
401  memory_size, skip, match,
402  next_table_index, miss_next_index,
403  table_index, current_data_flag,
404  current_data_offset, is_add,
405  1 /* delete_chain */);
406 }
407 
408 static int
410  u32 mask_len, u32 next_table_index,
411  u32 miss_next_index, u32 * table_index,
412  int is_add)
413 {
414  u32 nbuckets = 32;
415  u32 memory_size = 2 << 20;
416  u32 skip = count_skip (mask, mask_len);
417  u32 match = (mask_len / 16) - skip;
418  u8 *skip_mask_ptr = mask + 16 * skip;
419  u32 current_data_flag = 0;
420  int current_data_offset = 0;
421 
422  if (0 == match)
423  match = 1;
424 
425  return vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
426  memory_size, skip, match,
427  next_table_index, miss_next_index,
428  table_index, current_data_flag,
429  current_data_offset, is_add,
430  1 /* delete_chain */);
431 }
432 
433 
434 static int
436 {
438  u32 ip4_table_index = ~0;
439  u32 ip6_table_index = ~0;
440 
442  sw_if_index, ~0);
444  sw_if_index, ~0);
445 
446  vnet_l2_input_classify_enable_disable (sw_if_index, 0);
447 
448  if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
449  {
450  ip4_table_index =
452  am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
453  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
454  sizeof (ip4_5tuple_mask) - 1, ~0,
456  &ip4_table_index, 0);
457  }
458  if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
459  {
460  ip6_table_index =
462  am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
464  sizeof (ip6_5tuple_mask) - 1, ~0,
466  &ip6_table_index, 0);
467  }
468 
469  return 0;
470 }
471 
472 static int
474 {
476  u32 ip4_table_index = ~0;
477  u32 ip6_table_index = ~0;
478 
480  sw_if_index, ~0);
482  sw_if_index, ~0);
483 
485 
486  if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
487  {
488  ip4_table_index =
490  am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
491  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
492  sizeof (ip4_5tuple_mask) - 1, ~0,
494  &ip4_table_index, 0);
495  }
496  if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
497  {
498  ip6_table_index =
500  am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
502  sizeof (ip6_5tuple_mask) - 1, ~0,
504  &ip6_table_index, 0);
505  }
506 
507  return 0;
508 }
509 
510 static int
512 {
514  u32 ip4_table_index = ~0;
515  u32 ip6_table_index = ~0;
516  int rv;
517 
518  /* in case there were previous tables attached */
519  acl_unhook_l2_input_classify (am, sw_if_index);
520  rv =
521  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
522  sizeof (ip4_5tuple_mask) - 1, ~0,
524  &ip4_table_index, 1);
525  if (rv)
526  return rv;
527  rv =
529  sizeof (ip6_5tuple_mask) - 1, ~0,
531  &ip6_table_index, 1);
532  if (rv)
533  {
534  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
535  sizeof (ip4_5tuple_mask) - 1, ~0,
537  &ip4_table_index, 0);
538  return rv;
539  }
540  rv =
541  vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
542  ip6_table_index, ~0);
544  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
545  sw_if_index, ip4_table_index, ip6_table_index);
546  if (rv)
547  {
549  sizeof (ip6_5tuple_mask) - 1, ~0,
551  &ip6_table_index, 0);
552  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
553  sizeof (ip4_5tuple_mask) - 1, ~0,
555  &ip4_table_index, 0);
556  return rv;
557  }
558 
560  ip4_table_index;
562  ip6_table_index;
563 
564  vnet_l2_input_classify_enable_disable (sw_if_index, 1);
565  return rv;
566 }
567 
568 static int
570 {
572  u32 ip4_table_index = ~0;
573  u32 ip6_table_index = ~0;
574  int rv;
575 
576  /* in case there were previous tables attached */
577  acl_unhook_l2_output_classify (am, sw_if_index);
578  rv =
579  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
580  sizeof (ip4_5tuple_mask) - 1, ~0,
582  &ip4_table_index, 1);
583  if (rv)
584  return rv;
585  rv =
587  sizeof (ip6_5tuple_mask) - 1, ~0,
589  &ip6_table_index, 1);
590  if (rv)
591  {
592  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
593  sizeof (ip4_5tuple_mask) - 1, ~0,
595  &ip4_table_index, 0);
596  return rv;
597  }
598  rv =
599  vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
600  ip6_table_index, ~0);
602  ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
603  sw_if_index, ip4_table_index, ip6_table_index);
604  if (rv)
605  {
607  sizeof (ip6_5tuple_mask) - 1, ~0,
609  &ip6_table_index, 0);
610  acl_classify_add_del_table_big (cm, ip4_5tuple_mask,
611  sizeof (ip4_5tuple_mask) - 1, ~0,
613  &ip4_table_index, 0);
614  return rv;
615  }
616 
618  ip4_table_index;
620  ip6_table_index;
621 
623  return rv;
624 }
625 
626 
627 int
629  int enable_disable)
630 {
631  int rv;
632 
633  /* Utterly wrong? */
635  sw_if_index))
636  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
637 
638  if (enable_disable)
639  {
640  rv = acl_hook_l2_input_classify (am, sw_if_index);
641  }
642  else
643  {
644  rv = acl_unhook_l2_input_classify (am, sw_if_index);
645  }
646 
647  return rv;
648 }
649 
650 int
652  int enable_disable)
653 {
654  int rv;
655 
656  /* Utterly wrong? */
658  sw_if_index))
659  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
660 
661  if (enable_disable)
662  {
663  rv = acl_hook_l2_output_classify (am, sw_if_index);
664  }
665  else
666  {
667  rv = acl_unhook_l2_output_classify (am, sw_if_index);
668  }
669 
670  return rv;
671 }
672 
673 
674 static int
675 acl_interface_add_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
676 {
677  acl_main_t *am = &acl_main;
678  if (is_input)
679  {
680  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
681  vec_add (am->input_acl_vec_by_sw_if_index[sw_if_index], &acl_list_index,
682  1);
683  acl_interface_in_enable_disable (am, sw_if_index, 1);
684  }
685  else
686  {
687  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
688  vec_add (am->output_acl_vec_by_sw_if_index[sw_if_index],
689  &acl_list_index, 1);
690  acl_interface_out_enable_disable (am, sw_if_index, 1);
691  }
692  return 0;
693 }
694 
695 static int
696 acl_interface_del_inout_acl (u32 sw_if_index, u8 is_input, u32 acl_list_index)
697 {
698  acl_main_t *am = &acl_main;
699  int i;
700  int rv = -1;
701  if (is_input)
702  {
703  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
704  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
705  i++)
706  {
707  if (acl_list_index ==
708  am->input_acl_vec_by_sw_if_index[sw_if_index][i])
709  {
710  vec_del1 (am->input_acl_vec_by_sw_if_index[sw_if_index], i);
711  rv = 0;
712  break;
713  }
714  }
715  if (0 == vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]))
716  {
717  acl_interface_in_enable_disable (am, sw_if_index, 0);
718  }
719  }
720  else
721  {
722  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
723  for (i = 0;
724  i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]); i++)
725  {
726  if (acl_list_index ==
727  am->output_acl_vec_by_sw_if_index[sw_if_index][i])
728  {
729  vec_del1 (am->output_acl_vec_by_sw_if_index[sw_if_index], i);
730  rv = 0;
731  break;
732  }
733  }
734  if (0 == vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]))
735  {
736  acl_interface_out_enable_disable (am, sw_if_index, 0);
737  }
738  }
739  return rv;
740 }
741 
742 static void
743 acl_interface_reset_inout_acls (u32 sw_if_index, u8 is_input)
744 {
745  acl_main_t *am = &acl_main;
746  if (is_input)
747  {
748  acl_interface_in_enable_disable (am, sw_if_index, 0);
749  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
751  }
752  else
753  {
754  acl_interface_out_enable_disable (am, sw_if_index, 0);
755  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
757  }
758 }
759 
760 static int
761 acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
762  u32 acl_list_index)
763 {
764  int rv = -1;
765  if (is_add)
766  {
767  rv =
768  acl_interface_add_inout_acl (sw_if_index, is_input, acl_list_index);
769  }
770  else
771  {
772  rv =
773  acl_interface_del_inout_acl (sw_if_index, is_input, acl_list_index);
774  }
775  return rv;
776 }
777 
778 
779 static void *
781 {
782  u8 *p = vlib_buffer_get_current (b0) + offset;
783  return p;
784 }
785 
786 static u8
787 acl_get_l4_proto (vlib_buffer_t * b0, int node_is_ip6)
788 {
789  u8 proto;
790  int proto_offset;
791  if (node_is_ip6)
792  {
793  proto_offset = 20;
794  }
795  else
796  {
797  proto_offset = 23;
798  }
799  proto = *((u8 *) vlib_buffer_get_current (b0) + proto_offset);
800  return proto;
801 }
802 
803 static int
804 acl_match_addr (ip46_address_t * addr1, ip46_address_t * addr2, int prefixlen,
805  int is_ip6)
806 {
807  if (prefixlen == 0)
808  {
809  /* match any always succeeds */
810  return 1;
811  }
812  if (is_ip6)
813  {
814  if (memcmp (addr1, addr2, prefixlen / 8))
815  {
816  /* If the starting full bytes do not match, no point in bittwidling the thumbs further */
817  return 0;
818  }
819  if (prefixlen % 8)
820  {
821  u8 b1 = *((u8 *) addr1 + 1 + prefixlen / 8);
822  u8 b2 = *((u8 *) addr2 + 1 + prefixlen / 8);
823  u8 mask0 = (0xff - ((1 << (8 - (prefixlen % 8))) - 1));
824  return (b1 & mask0) == b2;
825  }
826  else
827  {
828  /* The prefix fits into integer number of bytes, so nothing left to do */
829  return 1;
830  }
831  }
832  else
833  {
834  uint32_t a1 = ntohl (addr1->ip4.as_u32);
835  uint32_t a2 = ntohl (addr2->ip4.as_u32);
836  uint32_t mask0 = 0xffffffff - ((1 << (32 - prefixlen)) - 1);
837  return (a1 & mask0) == a2;
838  }
839 }
840 
841 static int
842 acl_match_port (u16 port, u16 port_first, u16 port_last, int is_ip6)
843 {
844  return ((port >= port_first) && (port <= port_last));
845 }
846 
847 static int
849  u8 * r_action, int *r_is_ip6, u32 * r_acl_match_p,
850  u32 * r_rule_match_p, u32 * trace_bitmap)
851 {
852  ethernet_header_t *h0;
853  u16 type0;
854 
855  ip46_address_t src, dst;
856  int is_ip6;
857  int is_ip4;
858  u8 proto;
859  u16 src_port;
860  u16 dst_port;
861  u8 tcp_flags = 0;
862  int i;
863  acl_list_t *a;
864  acl_rule_t *r;
865 
866  h0 = vlib_buffer_get_current (b0);
867  type0 = clib_net_to_host_u16 (h0->type);
868  is_ip4 = (type0 == ETHERNET_TYPE_IP4);
869  is_ip6 = (type0 == ETHERNET_TYPE_IP6);
870 
871  if (!(is_ip4 || is_ip6))
872  {
873  return 0;
874  }
875  /* The bunch of hardcoded offsets here is intentional to get rid of them
876  ASAP, when getting to a faster matching code */
877  if (is_ip4)
878  {
879  clib_memcpy (&src.ip4, get_ptr_to_offset (b0, 26), 4);
880  clib_memcpy (&dst.ip4, get_ptr_to_offset (b0, 30), 4);
881  proto = acl_get_l4_proto (b0, 0);
882  if (1 == proto)
883  {
884  *trace_bitmap |= 0x00000001;
885  /* type */
886  src_port = *(u8 *) get_ptr_to_offset (b0, 34);
887  /* code */
888  dst_port = *(u8 *) get_ptr_to_offset (b0, 35);
889  }
890  else
891  {
892  /* assume TCP/UDP */
893  src_port = (*(u16 *) get_ptr_to_offset (b0, 34));
894  dst_port = (*(u16 *) get_ptr_to_offset (b0, 36));
895  /* UDP gets ability to check on an oddball data byte as a bonus */
896  tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 20 + 13);
897  }
898  }
899  else /* is_ipv6 implicitly */
900  {
901  clib_memcpy (&src, get_ptr_to_offset (b0, 22), 16);
902  clib_memcpy (&dst, get_ptr_to_offset (b0, 38), 16);
903  proto = acl_get_l4_proto (b0, 1);
904  if (58 == proto)
905  {
906  *trace_bitmap |= 0x00000002;
907  /* type */
908  src_port = *(u8 *) get_ptr_to_offset (b0, 54);
909  /* code */
910  dst_port = *(u8 *) get_ptr_to_offset (b0, 55);
911  }
912  else
913  {
914  /* assume TCP/UDP */
915  src_port = (*(u16 *) get_ptr_to_offset (b0, 54));
916  dst_port = (*(u16 *) get_ptr_to_offset (b0, 56));
917  tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 40 + 13);
918  }
919  }
920  if (pool_is_free_index (am->acls, acl_index))
921  {
922  if (r_acl_match_p)
923  *r_acl_match_p = acl_index;
924  if (r_rule_match_p)
925  *r_rule_match_p = -1;
926  /* the ACL does not exist but is used for policy. Block traffic. */
927  return 0;
928  }
929  a = am->acls + acl_index;
930  for (i = 0; i < a->count; i++)
931  {
932  r = a->rules + i;
933  if (is_ip6 != r->is_ipv6)
934  {
935  continue;
936  }
937  if (!acl_match_addr (&dst, &r->dst, r->dst_prefixlen, is_ip6))
938  continue;
939  if (!acl_match_addr (&src, &r->src, r->src_prefixlen, is_ip6))
940  continue;
941  if (r->proto)
942  {
943  if (proto != r->proto)
944  continue;
945  if (!acl_match_port
947  is_ip6))
948  continue;
949  if (!acl_match_port
951  is_ip6))
952  continue;
953  /* No need for check of proto == TCP, since in other rules both fields should be zero, so this match will succeed */
954  if ((tcp_flags & r->tcp_flags_mask) != r->tcp_flags_value)
955  continue;
956  }
957  /* everything matches! */
958  *r_action = r->is_permit;
959  *r_is_ip6 = is_ip6;
960  if (r_acl_match_p)
961  *r_acl_match_p = acl_index;
962  if (r_rule_match_p)
963  *r_rule_match_p = i;
964  return 1;
965  }
966  return 0;
967 }
968 
969 void
970 input_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
971  u32 * acl_match_p, u32 * rule_match_p,
972  u32 * trace_bitmap)
973 {
974  acl_main_t *am = &acl_main;
975  uint8_t action = 0;
976  int is_ip6 = 0;
977  int i;
978  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
979  for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
980  i++)
981  {
982  if (acl_packet_match
983  (am, am->input_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
984  &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
985  {
986  if (is_ip6)
987  {
988  *nextp = am->acl_in_ip6_match_next[action];
989  }
990  else
991  {
992  *nextp = am->acl_in_ip4_match_next[action];
993  }
994  return;
995  }
996  }
997  if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
998  {
999  /* If there are ACLs and none matched, deny by default */
1000  *nextp = 0;
1001  }
1002 
1003 }
1004 
1005 void
1006 output_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
1007  u32 * acl_match_p, u32 * rule_match_p,
1008  u32 * trace_bitmap)
1009 {
1010  acl_main_t *am = &acl_main;
1011  uint8_t action = 0;
1012  int is_ip6 = 0;
1013  int i;
1014  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1015  for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1016  i++)
1017  {
1018  if (acl_packet_match
1019  (am, am->output_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
1020  &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
1021  {
1022  if (is_ip6)
1023  {
1024  *nextp = am->acl_out_ip6_match_next[action];
1025  }
1026  else
1027  {
1028  *nextp = am->acl_out_ip4_match_next[action];
1029  }
1030  return;
1031  }
1032  }
1033  if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
1034  {
1035  /* If there are ACLs and none matched, deny by default */
1036  *nextp = 0;
1037  }
1038 }
1039 
1040 typedef struct
1041 {
1043  u8 mac_mask[6];
1049 
1050 static u32
1051 macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
1052  u8 is_ipv6)
1053 {
1054  u32 i;
1055  if (mv)
1056  {
1057  for (i = 0; i < vec_len (mv); i++)
1058  {
1059  if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
1060  && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
1061  {
1062  return i;
1063  }
1064  }
1065  }
1066  return ~0;
1067 }
1068 
1069 
1070 /* Get metric used to sort match types.
1071  The more specific and the more often seen - the bigger the metric */
1072 static int
1074 {
1075  /* FIXME: count the ones in the MAC mask as well, check how well this heuristic works in real life */
1076  return m->prefix_len + m->is_ipv6 + 10 * m->count;
1077 }
1078 
1079 static int
1081 {
1082  /* Ascending sort based on the metric values */
1083  return match_type_metric (m1) - match_type_metric (m2);
1084 }
1085 
1086 /* Get the offset of L3 source within ethernet packet */
1087 static int
1089 {
1090  if(is6)
1091  return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
1092  else
1093  return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
1094 }
1095 
1096 static int
1098 {
1099  macip_match_type_t *mvec = NULL;
1100  macip_match_type_t *mt;
1101  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
1102  int i;
1103  u32 match_type_index;
1104  u32 last_table;
1105  u8 mask[5 * 16];
1107 
1108  /* Count the number of different types of rules */
1109  for (i = 0; i < a->count; i++)
1110  {
1111  if (~0 ==
1112  (match_type_index =
1114  a->rules[i].src_prefixlen,
1115  a->rules[i].is_ipv6)))
1116  {
1117  match_type_index = vec_len (mvec);
1118  vec_validate (mvec, match_type_index);
1119  memcpy (mvec[match_type_index].mac_mask,
1120  a->rules[match_type_index].src_mac_mask, 6);
1121  mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
1122  mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
1123  mvec[match_type_index].table_index = ~0;
1124  }
1125  mvec[match_type_index].count++;
1126  }
1127  /* Put the most frequently used tables last in the list so we can create classifier tables in reverse order */
1129  /* Create the classifier tables */
1130  last_table = ~0;
1131  /* First add ARP tables */
1132  vec_foreach (mt, mvec)
1133  {
1134  int mask_len;
1135  int is6 = mt->is_ipv6;
1136 
1137  mt->arp_table_index = ~0;
1138  if (!is6)
1139  {
1140  memset (mask, 0, sizeof (mask));
1141  memcpy (&mask[6], mt->mac_mask, 6);
1142  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1143  memcpy (&mask[14 + 8], mt->mac_mask, 6);
1144 
1145  for (i = 0; i < (mt->prefix_len / 8); i++)
1146  mask[14 + 14 + i] = 0xff;
1147  if (mt->prefix_len % 8)
1148  mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1149 
1150  mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
1151  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1152  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1153  (~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
1154  1);
1155  last_table = mt->arp_table_index;
1156  }
1157  }
1158  /* Now add IP[46] tables */
1159  vec_foreach (mt, mvec)
1160  {
1161  int mask_len;
1162  int is6 = mt->is_ipv6;
1163  int l3_src_offs = get_l3_src_offset(is6);
1164  memset (mask, 0, sizeof (mask));
1165  memcpy (&mask[6], mt->mac_mask, 6);
1166  for (i = 0; i < (mt->prefix_len / 8); i++)
1167  {
1168  mask[l3_src_offs + i] = 0xff;
1169  }
1170  if (mt->prefix_len % 8)
1171  {
1172  mask[l3_src_offs + (mt->prefix_len / 8)] =
1173  0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
1174  }
1175  /*
1176  * Round-up the number of bytes needed to store the prefix,
1177  * and round up the number of vectors too
1178  */
1179  mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
1180  (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
1181  acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
1182  (~0 == last_table) ? 0 : ~0, &mt->table_index,
1183  1);
1184  last_table = mt->table_index;
1185  }
1186  a->ip4_table_index = ~0;
1187  a->ip6_table_index = ~0;
1188  a->l2_table_index = last_table;
1189 
1190  /* Populate the classifier tables with rules from the MACIP ACL */
1191  for (i = 0; i < a->count; i++)
1192  {
1193  u32 action = 0;
1194  u32 metadata = 0;
1195  int is6 = a->rules[i].is_ipv6;
1196  int l3_src_offs = get_l3_src_offset(is6);
1197  memset (mask, 0, sizeof (mask));
1198  memcpy (&mask[6], a->rules[i].src_mac, 6);
1199  memset (&mask[12], 0xff, 2); /* ethernet protocol */
1200  if (is6)
1201  {
1202  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
1203  mask[12] = 0x86;
1204  mask[13] = 0xdd;
1205  }
1206  else
1207  {
1208  memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
1209  mask[12] = 0x08;
1210  mask[13] = 0x00;
1211  }
1212  match_type_index =
1214  a->rules[i].src_prefixlen,
1215  a->rules[i].is_ipv6);
1216  /* add session to table mvec[match_type_index].table_index; */
1217  vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
1218  mask, a->rules[i].is_permit ? ~0 : 0, i,
1219  0, action, metadata, 1);
1220  /* add ARP table entry too */
1221  if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
1222  {
1223  memset (mask, 0, sizeof (mask));
1224  memcpy (&mask[6], a->rules[i].src_mac, 6);
1225  mask[12] = 0x08;
1226  mask[13] = 0x06;
1227  memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
1228  memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
1229  vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
1230  mask, a->rules[i].is_permit ? ~0 : 0, i,
1231  0, action, metadata, 1);
1232  }
1233  }
1234  return 0;
1235 }
1236 
1237 static void
1239 {
1241  macip_acl_list_t *a = &am->macip_acls[macip_acl_index];
1242 
1243  if (a->ip4_table_index != ~0)
1244  {
1245  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip4_table_index, 0);
1246  a->ip4_table_index = ~0;
1247  }
1248  if (a->ip6_table_index != ~0)
1249  {
1250  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->ip6_table_index, 0);
1251  a->ip6_table_index = ~0;
1252  }
1253  if (a->l2_table_index != ~0)
1254  {
1255  acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, &a->l2_table_index, 0);
1256  a->l2_table_index = ~0;
1257  }
1258 }
1259 
1260 static int
1262  u32 * acl_list_index, u8 * tag)
1263 {
1264  acl_main_t *am = &acl_main;
1266  macip_acl_rule_t *r;
1267  macip_acl_rule_t *acl_new_rules;
1268  int i;
1269 
1270  /* Create and populate the rules */
1271  acl_new_rules = clib_mem_alloc_aligned (sizeof (macip_acl_rule_t) * count,
1273  if (!acl_new_rules)
1274  {
1275  /* Could not allocate rules. New or existing ACL - bail out regardless */
1276  return -1;
1277  }
1278 
1279  for (i = 0; i < count; i++)
1280  {
1281  r = &acl_new_rules[i];
1282  r->is_permit = rules[i].is_permit;
1283  r->is_ipv6 = rules[i].is_ipv6;
1284  memcpy (&r->src_mac, rules[i].src_mac, 6);
1285  memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
1286  if(rules[i].is_ipv6)
1287  memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
1288  else
1289  memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
1290  r->src_prefixlen = rules[i].src_ip_prefix_len;
1291  }
1292 
1293  /* Get ACL index */
1295  memset (a, 0, sizeof (*a));
1296  /* Will return the newly allocated ACL index */
1297  *acl_list_index = a - am->macip_acls;
1298 
1299  a->rules = acl_new_rules;
1300  a->count = count;
1301  memcpy (a->tag, tag, sizeof (a->tag));
1302 
1303  /* Create and populate the classifer tables */
1304  macip_create_classify_tables (am, *acl_list_index);
1305 
1306  return 0;
1307 }
1308 
1309 
1310 /* No check for validity of sw_if_index - the callers were supposed to validate */
1311 
1312 static int
1314 {
1315  int rv;
1316  u32 macip_acl_index;
1318  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1319  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
1320  /* No point in deleting MACIP ACL which is not applied */
1321  if (~0 == macip_acl_index)
1322  return -1;
1323  a = &am->macip_acls[macip_acl_index];
1324  /* remove the classifier tables off the interface L2 ACL */
1325  rv =
1326  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1327  a->ip6_table_index, a->l2_table_index, 0);
1328  /* Unset the MACIP ACL index */
1329  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
1330  return rv;
1331 }
1332 
1333 /* No check for validity of sw_if_index - the callers were supposed to validate */
1334 
1335 static int
1337  u32 macip_acl_index)
1338 {
1340  int rv;
1341  if (pool_is_free_index (am->macip_acls, macip_acl_index))
1342  {
1343  return -1;
1344  }
1345  a = &am->macip_acls[macip_acl_index];
1346  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
1347  /* If there already a MACIP ACL applied, unapply it */
1348  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
1349  macip_acl_interface_del_acl(am, sw_if_index);
1350  am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
1351  /* Apply the classifier tables for L2 ACLs */
1352  rv =
1353  vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
1354  a->ip6_table_index, a->l2_table_index, 1);
1355  return rv;
1356 }
1357 
1358 static int
1359 macip_acl_del_list (u32 acl_list_index)
1360 {
1361  acl_main_t *am = &acl_main;
1363  int i;
1364  if (pool_is_free_index (am->macip_acls, acl_list_index))
1365  {
1366  return -1;
1367  }
1368 
1369  /* delete any references to the ACL */
1370  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
1371  {
1372  if (am->macip_acl_by_sw_if_index[i] == acl_list_index)
1373  {
1375  }
1376  }
1377 
1378  /* Now that classifier tables are detached, clean them up */
1379  macip_destroy_classify_tables (am, acl_list_index);
1380 
1381  /* now we can delete the ACL itself */
1382  a = &am->macip_acls[acl_list_index];
1383  if (a->rules)
1384  {
1385  clib_mem_free (a->rules);
1386  }
1387  pool_put (am->macip_acls, a);
1388  return 0;
1389 }
1390 
1391 
1392 static int
1394  u32 acl_list_index)
1395 {
1396  acl_main_t *am = &acl_main;
1397  int rv = -1;
1398  if (is_add)
1399  {
1400  rv = macip_acl_interface_add_acl (am, sw_if_index, acl_list_index);
1401  }
1402  else
1403  {
1404  rv = macip_acl_interface_del_acl (am, sw_if_index);
1405  }
1406  return rv;
1407 }
1408 
1409 /* API message handler */
1410 static void
1412 {
1414  acl_main_t *am = &acl_main;
1415  int rv;
1416  u32 acl_list_index = ntohl (mp->acl_index);
1417 
1418  rv = acl_add_list (ntohl (mp->count), mp->r, &acl_list_index, mp->tag);
1419 
1420  /* *INDENT-OFF* */
1421  REPLY_MACRO2(VL_API_ACL_ADD_REPLACE_REPLY,
1422  ({
1423  rmp->acl_index = htonl(acl_list_index);
1424  }));
1425  /* *INDENT-ON* */
1426 }
1427 
1428 static void
1430 {
1431  acl_main_t *sm = &acl_main;
1433  int rv;
1434 
1435  rv = acl_del_list (ntohl (mp->acl_index));
1436 
1437  REPLY_MACRO (VL_API_ACL_DEL_REPLY);
1438 }
1439 
1440 static void
1442 {
1443  acl_main_t *sm = &acl_main;
1445  u32 sw_if_index = ntohl (mp->sw_if_index);
1447  int rv = -1;
1448 
1449  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1450  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1451  else
1452  rv =
1453  acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
1454  mp->is_input, ntohl (mp->acl_index));
1455 
1456  REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
1457 }
1458 
1459 static void
1462 {
1463  acl_main_t *sm = &acl_main;
1465  int rv = 0;
1466  int i;
1468  u32 sw_if_index = ntohl (mp->sw_if_index);
1469 
1470  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1471  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1472  else
1473  {
1474  acl_interface_reset_inout_acls (sw_if_index, 0);
1475  acl_interface_reset_inout_acls (sw_if_index, 1);
1476 
1477  for (i = 0; i < mp->count; i++)
1478  {
1479  acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
1480  ntohl (mp->acls[i]));
1481  }
1482  }
1483 
1484  REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
1485 }
1486 
1487 static void
1489 {
1490  api_rule->is_permit = r->is_permit;
1491  api_rule->is_ipv6 = r->is_ipv6;
1492  if(r->is_ipv6)
1493  {
1494  memcpy (api_rule->src_ip_addr, &r->src, sizeof (r->src));
1495  memcpy (api_rule->dst_ip_addr, &r->dst, sizeof (r->dst));
1496  }
1497  else
1498  {
1499  memcpy (api_rule->src_ip_addr, &r->src.ip4, sizeof (r->src.ip4));
1500  memcpy (api_rule->dst_ip_addr, &r->dst.ip4, sizeof (r->dst.ip4));
1501  }
1502  api_rule->src_ip_prefix_len = r->src_prefixlen;
1503  api_rule->dst_ip_prefix_len = r->dst_prefixlen;
1504  api_rule->proto = r->proto;
1509  api_rule->tcp_flags_mask = r->tcp_flags_mask;
1510  api_rule->tcp_flags_value = r->tcp_flags_value;
1511 }
1512 
1513 static void
1515  acl_list_t * acl, u32 context)
1516 {
1518  vl_api_acl_rule_t *rules;
1519  int i;
1520  int msg_size = sizeof (*mp) + sizeof (mp->r[0]) * acl->count;
1521 
1522  mp = vl_msg_api_alloc (msg_size);
1523  memset (mp, 0, msg_size);
1524  mp->_vl_msg_id = ntohs (VL_API_ACL_DETAILS + am->msg_id_base);
1525 
1526  /* fill in the message */
1527  mp->context = context;
1528  mp->count = htonl (acl->count);
1529  mp->acl_index = htonl (acl - am->acls);
1530  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1531  // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
1532  rules = mp->r;
1533  for (i = 0; i < acl->count; i++)
1534  {
1535  copy_acl_rule_to_api_rule (&rules[i], &acl->rules[i]);
1536  }
1537 
1538  clib_warning("Sending acl details for ACL index %d", ntohl(mp->acl_index));
1539  vl_msg_api_send_shmem (q, (u8 *) & mp);
1540 }
1541 
1542 
1543 static void
1545 {
1546  acl_main_t *am = &acl_main;
1547  u32 acl_index;
1548  acl_list_t *acl;
1549 
1550  int rv = -1;
1552 
1554  if (q == 0)
1555  {
1556  return;
1557  }
1558 
1559  if (mp->acl_index == ~0)
1560  {
1561  /* *INDENT-OFF* */
1562  /* Just dump all ACLs */
1563  pool_foreach (acl, am->acls,
1564  ({
1565  send_acl_details(am, q, acl, mp->context);
1566  }));
1567  /* *INDENT-ON* */
1568  }
1569  else
1570  {
1571  acl_index = ntohl (mp->acl_index);
1572  if (!pool_is_free_index (am->acls, acl_index))
1573  {
1574  acl = &am->acls[acl_index];
1575  send_acl_details (am, q, acl, mp->context);
1576  }
1577  }
1578 
1579  if (rv == -1)
1580  {
1581  /* FIXME API: should we signal an error here at all ? */
1582  return;
1583  }
1584 }
1585 
1586 static void
1589  u32 sw_if_index, u32 context)
1590 {
1592  int msg_size;
1593  int n_input;
1594  int n_output;
1595  int count;
1596  int i = 0;
1597 
1598  vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
1599  vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
1600 
1601  n_input = vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
1602  n_output = vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
1603  count = n_input + n_output;
1604 
1605  msg_size = sizeof (*mp);
1606  msg_size += sizeof (mp->acls[0]) * count;
1607 
1608  mp = vl_msg_api_alloc (msg_size);
1609  memset (mp, 0, msg_size);
1610  mp->_vl_msg_id =
1611  ntohs (VL_API_ACL_INTERFACE_LIST_DETAILS + am->msg_id_base);
1612 
1613  /* fill in the message */
1614  mp->context = context;
1615  mp->sw_if_index = htonl (sw_if_index);
1616  mp->count = count;
1617  mp->n_input = n_input;
1618  for (i = 0; i < n_input; i++)
1619  {
1620  mp->acls[i] = htonl (am->input_acl_vec_by_sw_if_index[sw_if_index][i]);
1621  }
1622  for (i = 0; i < n_output; i++)
1623  {
1624  mp->acls[n_input + i] =
1625  htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
1626  }
1627 
1628  vl_msg_api_send_shmem (q, (u8 *) & mp);
1629 }
1630 
1631 static void
1633  mp)
1634 {
1635  acl_main_t *am = &acl_main;
1636  vnet_sw_interface_t *swif;
1638 
1639  u32 sw_if_index;
1641 
1643  if (q == 0)
1644  {
1645  return;
1646  }
1647 
1648  if (mp->sw_if_index == ~0)
1649  {
1650  /* *INDENT-OFF* */
1651  pool_foreach (swif, im->sw_interfaces,
1652  ({
1653  send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
1654  }));
1655  /* *INDENT-ON* */
1656  }
1657  else
1658  {
1659  sw_if_index = ntohl (mp->sw_if_index);
1660  if (!pool_is_free_index(im->sw_interfaces, sw_if_index))
1661  send_acl_interface_list_details (am, q, sw_if_index, mp->context);
1662  }
1663 }
1664 
1665 /* MACIP ACL API handlers */
1666 
1667 static void
1669 {
1671  acl_main_t *am = &acl_main;
1672  int rv;
1673  u32 acl_list_index = ~0;
1674 
1675  rv =
1676  macip_acl_add_list (ntohl (mp->count), mp->r, &acl_list_index, mp->tag);
1677 
1678  /* *INDENT-OFF* */
1679  REPLY_MACRO2(VL_API_MACIP_ACL_ADD_REPLY,
1680  ({
1681  rmp->acl_index = htonl(acl_list_index);
1682  }));
1683  /* *INDENT-ON* */
1684 }
1685 
1686 static void
1688 {
1689  acl_main_t *sm = &acl_main;
1691  int rv;
1692 
1693  rv = macip_acl_del_list (ntohl (mp->acl_index));
1694 
1695  REPLY_MACRO (VL_API_MACIP_ACL_DEL_REPLY);
1696 }
1697 
1698 static void
1701 {
1702  acl_main_t *sm = &acl_main;
1704  int rv = -1;
1706  u32 sw_if_index = ntohl (mp->sw_if_index);
1707 
1708  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
1709  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1710  else
1711  rv =
1713  ntohl (mp->acl_index));
1714 
1715  REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
1716 }
1717 
1718 static void
1720  macip_acl_list_t * acl, u32 context)
1721 {
1723  vl_api_macip_acl_rule_t *rules;
1724  macip_acl_rule_t *r;
1725  int i;
1726  int msg_size = sizeof (*mp) + (acl ? sizeof (mp->r[0]) * acl->count : 0);
1727 
1728  mp = vl_msg_api_alloc (msg_size);
1729  memset (mp, 0, msg_size);
1730  mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_DETAILS + am->msg_id_base);
1731 
1732  /* fill in the message */
1733  mp->context = context;
1734  if (acl)
1735  {
1736  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
1737  mp->count = htonl (acl->count);
1738  mp->acl_index = htonl (acl - am->macip_acls);
1739  rules = mp->r;
1740  for (i = 0; i < acl->count; i++)
1741  {
1742  r = &acl->rules[i];
1743  rules[i].is_permit = r->is_permit;
1744  rules[i].is_ipv6 = r->is_ipv6;
1745  memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
1746  memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
1747  sizeof (r->src_mac_mask));
1748  if (r->is_ipv6)
1749  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
1750  sizeof (r->src_ip_addr.ip6));
1751  else
1752  memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
1753  sizeof (r->src_ip_addr.ip4));
1754  rules[i].src_ip_prefix_len = r->src_prefixlen;
1755  }
1756  }
1757  else
1758  {
1759  /* No martini, no party - no ACL applied to this interface. */
1760  mp->acl_index = ~0;
1761  mp->count = 0;
1762  }
1763 
1764  vl_msg_api_send_shmem (q, (u8 *) & mp);
1765 }
1766 
1767 
1768 static void
1770 {
1771  acl_main_t *am = &acl_main;
1772  macip_acl_list_t *acl;
1773 
1775 
1777  if (q == 0)
1778  {
1779  return;
1780  }
1781 
1782  if (mp->acl_index == ~0)
1783  {
1784  /* Just dump all ACLs for now, with sw_if_index = ~0 */
1785  pool_foreach (acl, am->macip_acls, (
1786  {
1787  send_macip_acl_details (am, q, acl,
1788  mp->
1789  context);}
1790  ));
1791  /* *INDENT-ON* */
1792  }
1793  else
1794  {
1795  u32 acl_index = ntohl (mp->acl_index);
1796  if (!pool_is_free_index (am->macip_acls, acl_index))
1797  {
1798  acl = &am->macip_acls[acl_index];
1799  send_macip_acl_details (am, q, acl, mp->context);
1800  }
1801  }
1802 }
1803 
1804 static void
1806  mp)
1807 {
1808  acl_main_t *am = &acl_main;
1810  u32 count = vec_len (am->macip_acl_by_sw_if_index);
1811  int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
1813  int i;
1814 
1816  if (q == 0)
1817  {
1818  return;
1819  }
1820 
1821  rmp = vl_msg_api_alloc (msg_size);
1822  memset (rmp, 0, msg_size);
1823  rmp->_vl_msg_id =
1824  ntohs (VL_API_MACIP_ACL_INTERFACE_GET_REPLY + am->msg_id_base);
1825  rmp->context = mp->context;
1826  rmp->count = htonl (count);
1827  for (i = 0; i < count; i++)
1828  {
1829  rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
1830  }
1831 
1832  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1833 }
1834 
1835 /* Set up the API message handling tables */
1836 static clib_error_t *
1838 {
1839  acl_main_t *sm = &acl_main;
1840 #define _(N,n) \
1841  vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
1842  #n, \
1843  vl_api_##n##_t_handler, \
1844  vl_noop_handler, \
1845  vl_api_##n##_t_endian, \
1846  vl_api_##n##_t_print, \
1847  sizeof(vl_api_##n##_t), 1);
1849 #undef _
1850 
1851  return 0;
1852 }
1853 
1854 #define vl_msg_name_crc_list
1855 #include <acl/acl_all_api_h.h>
1856 #undef vl_msg_name_crc_list
1857 
1858 static void
1860 {
1861 #define _(id,n,crc) \
1862  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
1863  foreach_vl_msg_name_crc_acl;
1864 #undef _
1865 }
1866 
1867 u32
1868 register_match_action_nexts (u32 next_in_ip4, u32 next_in_ip6,
1869  u32 next_out_ip4, u32 next_out_ip6)
1870 {
1871  acl_main_t *am = &acl_main;
1872  u32 act = am->n_match_actions;
1873  if (am->n_match_actions == 255)
1874  {
1875  return ~0;
1876  }
1877  am->n_match_actions++;
1878  am->acl_in_ip4_match_next[act] = next_in_ip4;
1879  am->acl_in_ip6_match_next[act] = next_in_ip6;
1880  am->acl_out_ip4_match_next[act] = next_out_ip4;
1881  am->acl_out_ip6_match_next[act] = next_out_ip6;
1882  return act;
1883 }
1884 
1885 void
1887 {
1888  vlib_main_t *vm = vlib_get_main ();
1889  acl_main_t *am = &acl_main;
1890  vlib_node_t *n;
1891 
1892  n = vlib_get_node_by_name (vm, (u8 *) "l2-input-classify");
1894  vlib_node_add_next_with_slot (vm, n->index, acl_in_node.index, ~0);
1895  n = vlib_get_node_by_name (vm, (u8 *) "l2-output-classify");
1897  vlib_node_add_next_with_slot (vm, n->index, acl_out_node.index, ~0);
1898 
1902 
1906 
1907  memset (&am->acl_in_ip4_match_next[0], 0,
1908  sizeof (am->acl_in_ip4_match_next));
1909  memset (&am->acl_in_ip6_match_next[0], 0,
1910  sizeof (am->acl_in_ip6_match_next));
1911  memset (&am->acl_out_ip4_match_next[0], 0,
1912  sizeof (am->acl_out_ip4_match_next));
1913  memset (&am->acl_out_ip6_match_next[0], 0,
1914  sizeof (am->acl_out_ip6_match_next));
1915  am->n_match_actions = 0;
1916 
1917  register_match_action_nexts (0, 0, 0, 0); /* drop */
1918  register_match_action_nexts (~0, ~0, ~0, ~0); /* permit */
1920 }
1921 
1922 
1923 
1924 static clib_error_t *
1926 {
1927  acl_main_t *am = &acl_main;
1928  clib_error_t *error = 0;
1929  memset (am, 0, sizeof (*am));
1930  am->vlib_main = vm;
1931  am->vnet_main = vnet_get_main ();
1932 
1933  u8 *name = format (0, "acl_%08x%c", api_version, 0);
1934 
1935  /* Ask for a correctly-sized block of API message decode slots */
1936  am->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
1938 
1939  error = acl_plugin_api_hookup (vm);
1940  acl_setup_nodes ();
1941 
1942  /* Add our API messages to the global name_crc hash table */
1944 
1945  vec_free (name);
1946 
1947  return error;
1948 }
1949 
acl_rule_t * rules
Definition: acl.h:84
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
macip_acl_rule_t * rules
Definition: acl.h:91
u32 * acl_ip4_output_classify_table_by_sw_if_index
Definition: acl.h:115
static int macip_acl_interface_add_acl(acl_main_t *am, u32 sw_if_index, u32 macip_acl_index)
Definition: acl.c:1336
u8 src_mac[6]
Definition: acl.h:71
Use acl_interface_set_acl_list instead Append/remove an ACL index to/from the list of ACLs checked fo...
Definition: acl.api:193
static int macip_acl_interface_add_del_acl(u32 sw_if_index, u8 is_add, u32 acl_list_index)
Definition: acl.c:1393
static int acl_hook_l2_output_classify(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:569
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:1719
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:1925
int acl_interface_out_enable_disable(acl_main_t *am, u32 sw_if_index, int enable_disable)
Definition: acl.c:651
u8 is_ipv6
Definition: acl.h:53
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:696
static void vl_api_acl_plugin_get_version_t_handler(vl_api_acl_plugin_get_version_t *mp)
Definition: acl.c:156
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:628
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:1006
Set the vector of input/output ACLs checked for an interface.
Definition: acl.api:227
#define REPLY_MACRO2(t, body)
Definition: acl.c:82
#define foreach_acl_plugin_api_msg
Definition: acl.c:117
u8 tcp_flags_mask
Definition: acl.api:94
u32 ** input_acl_vec_by_sw_if_index
Definition: acl.h:106
u16 msg_id_base
Definition: acl.h:100
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Dump the list(s) of ACL applied to specific or all interfaces.
Definition: acl.api:284
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:322
void acl_setup_nodes(void)
Definition: acl.c:1886
static int count_skip(u8 *p, u32 size)
Definition: acl.c:369
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:1411
static void vl_api_macip_acl_dump_t_handler(vl_api_macip_acl_dump_t *mp)
Definition: acl.c:1769
u32 acl_out_node_feat_next_node_index[32]
Definition: acl.h:127
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:156
u8 src_ip_addr[16]
Definition: acl.api:67
#define ACL_PLUGIN_VERSION_MINOR
Definition: acl.h:29
#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:1668
u8 dst_prefixlen
Definition: acl.h:57
u32 * acl_ip6_input_classify_table_by_sw_if_index
Definition: acl.h:114
u32 acl_in_ip4_match_next[256]
Definition: acl.h:131
u32 count
Definition: acl.h:83
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u32 l2_table_index
Definition: acl.h:95
void vnet_l2_input_classify_enable_disable(u32 sw_if_index, int enable_disable)
Enable/disable l2 input classification on a specific interface.
Access List Rule entry.
Definition: acl.api:63
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:1051
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Details about one MACIP ACL.
Definition: acl.api:412
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
ethernet_main_t * ethernet_main
Definition: plugin.h:27
api_main_t api_main
Definition: api_shared.c:39
u16 dst_port_or_code_last
Definition: acl.h:62
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u8 src_mac_mask[6]
Definition: acl.h:72
static int acl_match_addr(ip46_address_t *addr1, ip46_address_t *addr2, int prefixlen, int is_ip6)
Definition: acl.c:804
u8 src_prefixlen
Definition: acl.h:55
ip46_address_t src_ip_addr
Definition: acl.h:73
void mv(vnet_classify_table_t *t)
Definition: vnet_classify.c:66
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u16 dstport_or_icmpcode_first
Definition: acl.api:87
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
vnet_main_t * vnet_main
Definition: acl.h:140
unsigned long long u32x4
Definition: ixge.c:28
ip46_address_t src
Definition: acl.h:54
u8 src_ip_prefix_len
Definition: acl.api:68
u8 tcp_flags_value
Definition: acl.api:95
Add or delete a MACIP ACL to/from interface.
Definition: acl.api:370
u8 src_prefixlen
Definition: acl.h:74
u8 is_permit
Definition: acl.h:52
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:970
#define clib_warning(format, args...)
Definition: error.h:59
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:1043
u32 ip4_table_index
Definition: acl.h:93
u32 n_match_actions
Definition: acl.h:135
static int acl_match_port(u16 port, u16 port_first, u16 port_last, int is_ip6)
Definition: acl.c:842
u32 * acl_ip4_input_classify_table_by_sw_if_index
Definition: acl.h:113
ip46_address_t dst
Definition: acl.h:56
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:435
u32 acl_in_node_feat_next_node_index[32]
Definition: acl.h:126
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:511
u16 dst_port_or_code_first
Definition: acl.h:61
static void vl_api_acl_dump_t_handler(vl_api_acl_dump_t *mp)
Definition: acl.c:1544
#define v
Definition: acl.c:314
Replace an existing ACL in-place or create a new ACL.
Definition: acl.api:135
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
Details about a single ACL contents.
Definition: acl.api:299
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:765
vl_api_acl_rule_t r[count]
Definition: acl.api:142
static int get_l3_src_offset(int is6)
Definition: acl.c:1088
vlib_node_registration_t acl_in_node
(constructor) VLIB_REGISTER_NODE (acl_in_node)
Definition: node_in.c:154
u8 proto
Definition: acl.h:58
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:1514
u16 src_port_or_type_first
Definition: acl.h:59
static int match_type_compare(macip_match_type_t *m1, macip_match_type_t *m2)
Definition: acl.c:1080
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
ethernet_main_t * ethernet_main
Definition: acl.h:141
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:473
Reply to alter the ACL list.
Definition: acl.api:212
static int match_type_metric(macip_match_type_t *m)
Definition: acl.c:1073
static int macip_acl_del_list(u32 acl_list_index)
Definition: acl.c:1359
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:409
void * vl_msg_api_alloc(int nbytes)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
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:384
u32 register_match_action_nexts(u32 next_in_ip4, u32 next_in_ip6, u32 next_out_ip4, u32 next_out_ip6)
Definition: acl.c:1868
u16 srcport_or_icmptype_first
Definition: acl.api:85
Reply to add/replace ACL.
Definition: acl.api:151
static int acl_interface_add_inout_acl(u32 sw_if_index, u8 is_input, u32 acl_list_index)
Definition: acl.c:675
u64 memory_size
Definition: vhost-user.h:75
Definition: acl.h:50
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
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:211
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
Definition: acl.c:139
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:57
Definition: acl.h:98
u8 is_ipv6
Definition: acl.h:70
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:1441
static int macip_acl_interface_del_acl(acl_main_t *am, u32 sw_if_index)
Definition: acl.c:1313
unsigned int u32
Definition: types.h:88
u8 tag[64]
Definition: acl.h:82
static void vl_api_macip_acl_del_t_handler(vl_api_macip_acl_del_t *mp)
Definition: acl.c:1687
u16 src_port_or_type_last
Definition: acl.h:60
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:1097
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:1587
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:848
u64 size
Definition: vhost-user.h:74
static void clib_mem_free(void *p)
Definition: mem.h:176
u8 dst_ip_prefix_len
Definition: acl.api:70
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: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:1837
static int macip_acl_add_list(u32 count, vl_api_macip_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:1261
u32 count
Definition: acl.h:90
vl_api_macip_acl_rule_t r[count]
Definition: acl.api:418
u32 acl_out_ip6_match_next[256]
Definition: acl.h:134
Dump the specific ACL contents or all of the ACLs&#39; contents.
Definition: acl.api:254
vlib_main_t * vlib_main
Definition: acl.h:139
#define REPLY_MACRO(t)
Definition: acl.c:67
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:119
Get the vector of MACIP ACL IDs applied to the interfaces.
Definition: acl.api:426
#define XX
Definition: acl.c:311
u32 * acl_ip6_output_classify_table_by_sw_if_index
Definition: acl.h:116
static void vl_api_acl_interface_list_dump_t_handler(vl_api_acl_interface_list_dump_t *mp)
Definition: acl.c:1632
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
static int acl_add_list(u32 count, vl_api_acl_rule_t rules[], u32 *acl_list_index, u8 *tag)
Definition: acl.c:182
unsigned short u16
Definition: types.h:57
static void vl_api_acl_del_t_handler(vl_api_acl_del_t *mp)
Definition: acl.c:1429
macip_acl_list_t * macip_acls
Definition: acl.h:103
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void * get_ptr_to_offset(vlib_buffer_t *b0, int offset)
Definition: acl.c:780
unsigned char u8
Definition: types.h:56
u32 l2_input_classify_next_acl
Definition: acl.h:122
Details about a single ACL contents.
Definition: acl.api:269
u32 ip6_table_index
Definition: acl.h:94
Reply to apply/unapply the MACIP ACL.
Definition: acl.api:385
u8 tcp_flags_mask
Definition: acl.h:64
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:920
Reply to delete the ACL.
Definition: acl.api:176
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:606
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:1461
vnet_main_t * vnet_main
Definition: plugin.h:26
static void acl_interface_reset_inout_acls(u32 sw_if_index, u8 is_input)
Definition: acl.c:743
struct clib_bihash_value offset
template key/value backing page structure
u32 l2_output_classify_next_acl
Definition: acl.h:123
u32 acl_in_ip6_match_next[256]
Definition: acl.h:132
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
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:761
u8 tcp_flags_value
Definition: acl.h:63
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
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:1488
Reply to delete the MACIP ACL.
Definition: acl.api:356
#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:133
u16 vl_msg_api_get_msg_ids(char *name, int n)
Definition: api_shared.c:1309
Add a MACIP ACL.
Definition: acl.api:316
Definition: acl.h:80
u32 client_index
Definition: acl.api:256
#define ACL_PLUGIN_VERSION_MAJOR
Definition: acl.h:28
u8 tag[64]
Definition: acl.h:89
void l2sess_vlib_plugin_register(vlib_main_t *vm, void *hh, int from_early_init)
Definition: l2sess.c:34
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:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
static void setup_message_id_table(acl_main_t *sm, api_main_t *am)
Definition: acl.c:1859
u8 ip6_5tuple_mask[]
Definition: acl.c:344
acl_list_t * acls
Definition: acl.h:102
u32 ** output_acl_vec_by_sw_if_index
Definition: acl.h:107
u8 is_permit
Definition: acl.h:69
static void vl_api_macip_acl_interface_add_del_t_handler(vl_api_macip_acl_interface_add_del_t *mp)
Definition: acl.c:1700
u32 arp_table_index
Definition: acl.c:1047
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static int acl_del_list(u32 acl_list_index)
Definition: acl.c:258
static void macip_destroy_classify_tables(acl_main_t *am, u32 macip_acl_index)
Definition: acl.c:1238
static u8 acl_get_l4_proto(vlib_buffer_t *b0, int node_is_ip6)
Definition: acl.c:787
static void vl_api_macip_acl_interface_get_t_handler(vl_api_macip_acl_interface_get_t *mp)
Definition: acl.c:1805
u8 ip4_5tuple_mask[]
Definition: acl.c:316