FD.io VPP  v19.04.2-12-g66b1689
Vector Packet Processing
in_out_acl.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include <vnet/ip/ip.h>
18 #include <vnet/l2/l2_output.h>
19 #include <vnet/l2/l2_input.h>
20 
22 
23 static int
25  in_out_acl_main_t * am,
28  int feature_enable, int is_output)
29 {
30 
31  if (tid == IN_OUT_ACL_TABLE_L2)
32  {
33  if (is_output)
34  l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_ACL,
35  feature_enable);
36  else
37  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ACL,
38  feature_enable);
39  }
40  else
41  { /* IP[46] */
43  u8 arc;
44 
45  if (tid == IN_OUT_ACL_TABLE_IP4)
46  {
47  char *arc_name = is_output ? "ip4-output" : "ip4-unicast";
49  is_output ? "ip4-outacl" : "ip4-inacl",
50  sw_if_index, feature_enable, 0, 0);
51  arc = vnet_get_feature_arc_index (arc_name);
52  }
53  else
54  {
55  char *arc_name = is_output ? "ip6-output" : "ip6-unicast";
57  is_output ? "ip6-outacl" : "ip6-inacl",
58  sw_if_index, feature_enable, 0, 0);
59  arc = vnet_get_feature_arc_index (arc_name);
60  }
61 
63  am->vnet_config_main[is_output][tid] = &fcm->config_main;
64  }
65 
66  return 0;
67 }
68 
69 int
71  u32 ip4_table_index,
72  u32 ip6_table_index, u32 l2_table_index,
73  u32 is_add, u32 is_output)
74 {
77  u32 acl[IN_OUT_ACL_N_TABLES] = { ip4_table_index, ip6_table_index,
78  l2_table_index
79  };
80  u32 ti;
81 
82  /* Assume that we've validated sw_if_index in the API layer */
83 
84  for (ti = 0; ti < IN_OUT_ACL_N_TABLES; ti++)
85  {
86  if (acl[ti] == ~0)
87  continue;
88 
89  if (pool_is_free_index (vcm->tables, acl[ti]))
90  return VNET_API_ERROR_NO_SUCH_TABLE;
91 
93  (am->classify_table_index_by_sw_if_index[is_output][ti], sw_if_index,
94  ~0);
95 
96  /* Reject any DEL operation with wrong sw_if_index */
97  if (!is_add &&
98  (acl[ti] !=
99  am->classify_table_index_by_sw_if_index[is_output][ti]
100  [sw_if_index]))
101  {
103  ("Non-existent intf_idx=%d with table_index=%d for delete",
104  sw_if_index, acl[ti]);
105  return VNET_API_ERROR_NO_SUCH_TABLE;
106  }
107 
108  /* Return ok on ADD operaton if feature is already enabled */
109  if (is_add &&
110  am->classify_table_index_by_sw_if_index[is_output][ti][sw_if_index]
111  != ~0)
112  return 0;
113 
114  vnet_in_out_acl_ip_feature_enable (vm, am, sw_if_index, ti, is_add,
115  is_output);
116 
117  if (is_add)
119  acl[ti];
120  else
122  ~0;
123  }
124 
125  return 0;
126 }
127 
128 int
130  u32 ip4_table_index,
131  u32 ip6_table_index, u32 l2_table_index, u32 is_add)
132 {
133  return vnet_set_in_out_acl_intfc (vm, sw_if_index, ip4_table_index,
134  ip6_table_index, l2_table_index, is_add,
136 }
137 
138 int
140  u32 ip4_table_index,
141  u32 ip6_table_index, u32 l2_table_index,
142  u32 is_add)
143 {
144  return vnet_set_in_out_acl_intfc (vm, sw_if_index, ip4_table_index,
145  ip6_table_index, l2_table_index, is_add,
147 }
148 
149 static clib_error_t *
151  unformat_input_t * input, vlib_cli_command_t * cmd,
152  u32 is_output)
153 {
154  vnet_main_t *vnm = vnet_get_main ();
155  u32 sw_if_index = ~0;
156  u32 ip4_table_index = ~0;
157  u32 ip6_table_index = ~0;
158  u32 l2_table_index = ~0;
159  u32 is_add = 1;
160  u32 idx_cnt = 0;
161  int rv;
162 
164  {
165  if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
166  vnm, &sw_if_index))
167  ;
168  else if (unformat (input, "ip4-table %d", &ip4_table_index))
169  idx_cnt++;
170  else if (unformat (input, "ip6-table %d", &ip6_table_index))
171  idx_cnt++;
172  else if (unformat (input, "l2-table %d", &l2_table_index))
173  idx_cnt++;
174  else if (unformat (input, "del"))
175  is_add = 0;
176  else
177  break;
178  }
179 
180  if (sw_if_index == ~0)
181  return clib_error_return (0, "Interface must be specified.");
182 
183  if (!idx_cnt)
184  return clib_error_return (0, "Table index should be specified.");
185 
186  if (idx_cnt > 1)
187  return clib_error_return (0, "Only one table index per API is allowed.");
188 
189  rv = vnet_set_in_out_acl_intfc (vm, sw_if_index, ip4_table_index,
190  ip6_table_index, l2_table_index, is_add,
191  is_output);
192 
193  switch (rv)
194  {
195  case 0:
196  break;
197 
198  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
199  return clib_error_return (0, "No such interface");
200 
201  case VNET_API_ERROR_NO_SUCH_ENTRY:
202  return clib_error_return (0, "No such classifier table");
203  }
204  return 0;
205 }
206 
207 static clib_error_t *
209  unformat_input_t * input, vlib_cli_command_t * cmd)
210 {
211  return set_in_out_acl_command_fn (vm, input, cmd,
213 }
214 
215 static clib_error_t *
217  unformat_input_t * input, vlib_cli_command_t * cmd)
218 {
219  return set_in_out_acl_command_fn (vm, input, cmd,
221 }
222 
223 /*
224  * Configure interface to enable/disble input/output ACL features:
225  * intfc - interface name to be configured as input ACL
226  * Ip4-table <index> [del] - enable/disable IP4 input ACL
227  * Ip6-table <index> [del] - enable/disable IP6 input ACL
228  * l2-table <index> [del] - enable/disable Layer2 input ACL
229  *
230  * Note: Only one table index per API call is allowed.
231  *
232  */
233 /* *INDENT-OFF* */
234 VLIB_CLI_COMMAND (set_input_acl_command, static) = {
235  .path = "set interface input acl",
236  .short_help =
237  "set interface input acl intfc <int> [ip4-table <index>]\n"
238  " [ip6-table <index>] [l2-table <index>] [del]",
239  .function = set_input_acl_command_fn,
240 };
241 VLIB_CLI_COMMAND (set_output_acl_command, static) = {
242  .path = "set interface output acl",
243  .short_help =
244  "set interface output acl intfc <int> [ip4-table <index>]\n"
245  " [ip6-table <index>] [l2-table <index>] [del]",
246  .function = set_output_acl_command_fn,
247 };
248 /* *INDENT-ON* */
249 
250 clib_error_t *
252 {
254  clib_error_t *error = 0;
255 
256  if ((error = vlib_call_init_function (vm, ip_in_out_acl_init)))
257  return error;
258 
259  am->vlib_main = vm;
260  am->vnet_main = vnet_get_main ();
262 
263  return 0;
264 }
265 
267 
268 uword
269 unformat_acl_type (unformat_input_t * input, va_list * args)
270 {
271  u32 *acl_type = va_arg (*args, u32 *);
272  u32 tid = IN_OUT_ACL_N_TABLES;
273 
275  {
276  if (unformat (input, "ip4"))
277  tid = IN_OUT_ACL_TABLE_IP4;
278  else if (unformat (input, "ip6"))
279  tid = IN_OUT_ACL_TABLE_IP6;
280  else if (unformat (input, "l2"))
281  tid = IN_OUT_ACL_TABLE_L2;
282  else
283  break;
284  }
285 
286  *acl_type = tid;
287  return 1;
288 }
289 
290 u8 *
291 format_vnet_in_out_acl_info (u8 * s, va_list * va)
292 {
293  in_out_acl_main_t *am = va_arg (*va, in_out_acl_main_t *);
294  int sw_if_idx = va_arg (*va, int);
295  u32 tid = va_arg (*va, u32);
296 
297  if (tid == ~0)
298  {
299  s = format (s, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
300  "Interface name");
301  return s;
302  }
303 
304  s = format (s, "%10d%20d\t\t%U", sw_if_idx, tid,
305  format_vnet_sw_if_index_name, am->vnet_main, sw_if_idx);
306 
307  return s;
308 }
309 
310 static clib_error_t *
312  unformat_input_t * input,
313  vlib_cli_command_t * cmd, u32 is_output)
314 {
316  u32 type = IN_OUT_ACL_N_TABLES;
317  int i;
318  u32 *vec_tbl;
319 
321  {
322  if (unformat (input, "type %U", unformat_acl_type, &type))
323  ;
324  else
325  break;
326  }
327 
328  if (type == IN_OUT_ACL_N_TABLES)
329  return clib_error_return (0, is_output ? "Invalid output ACL table type."
330  : "Invalid input ACL table type.");
331 
332  vec_tbl = am->classify_table_index_by_sw_if_index[is_output][type];
333 
334  if (vec_len (vec_tbl))
335  vlib_cli_output (vm, "%U", format_vnet_in_out_acl_info, am, ~0 /* hdr */ ,
336  ~0);
337  else
338  vlib_cli_output (vm, is_output ? "No output ACL tables configured"
339  : "No input ACL tables configured");
340 
341  for (i = 0; i < vec_len (vec_tbl); i++)
342  {
343  if (vec_elt (vec_tbl, i) == ~0)
344  continue;
345 
347  am, i, vec_elt (vec_tbl, i));
348  }
349 
350  return 0;
351 }
352 
353 static clib_error_t *
355  unformat_input_t * input, vlib_cli_command_t * cmd)
356 {
357  return show_in_out_acl_command_fn (vm, input, cmd,
359 }
360 
361 static clib_error_t *
363  unformat_input_t * input, vlib_cli_command_t * cmd)
364 {
365  return show_in_out_acl_command_fn (vm, input, cmd,
367 }
368 
369 /* *INDENT-OFF* */
370 VLIB_CLI_COMMAND (show_inacl_command, static) = {
371  .path = "show inacl",
372  .short_help = "show inacl type [ip4|ip6|l2]",
373  .function = show_inacl_command_fn,
374 };
375 VLIB_CLI_COMMAND (show_outacl_command, static) = {
376  .path = "show outacl",
377  .short_help = "show outacl type [ip4|ip6|l2]",
378  .function = show_outacl_command_fn,
379 };
380 /* *INDENT-ON* */
381 
382 /*
383  * fd.io coding-style-patch-verification: ON
384  *
385  * Local Variables:
386  * eval: (c-set-style "gnu")
387  * End:
388  */
vnet_config_main_t config_main
Definition: feature.h:82
u32 sw_if_index
Definition: ipsec_gre.api:37
static clib_error_t * show_in_out_acl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, u32 is_output)
Definition: in_out_acl.c:311
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:168
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
u32 * classify_table_index_by_sw_if_index[IN_OUT_ACL_N_TABLE_GROUPS][IN_OUT_ACL_N_TABLES]
Definition: in_out_acl.h:50
clib_error_t * in_out_acl_init(vlib_main_t *vm)
Definition: in_out_acl.c:251
static clib_error_t * set_output_acl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: in_out_acl.c:216
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
vnet_main_t * vnet_main
Definition: in_out_acl.h:54
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
static clib_error_t * set_in_out_acl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, u32 is_output)
Definition: in_out_acl.c:150
#define clib_error_return(e, args...)
Definition: error.h:99
vnet_config_main_t * vnet_config_main[IN_OUT_ACL_N_TABLE_GROUPS][IN_OUT_ACL_N_TABLES]
Definition: in_out_acl.h:57
unsigned int u32
Definition: types.h:88
#define vlib_call_init_function(vm, x)
Definition: init.h:260
struct _unformat_input_t unformat_input_t
static clib_error_t * show_outacl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: in_out_acl.c:362
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: in_out_acl.c:129
void l2output_intf_bitmap_enable(u32 sw_if_index, l2output_feat_masks_t feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_output.c:626
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:312
#define clib_warning(format, args...)
Definition: error.h:59
u8 * format_vnet_in_out_acl_info(u8 *s, va_list *va)
Definition: in_out_acl.c:291
static clib_error_t * show_inacl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: in_out_acl.c:354
vlib_main_t * vlib_main
Definition: in_out_acl.h:53
static int vnet_in_out_acl_ip_feature_enable(vlib_main_t *vnm, in_out_acl_main_t *am, u32 sw_if_index, in_out_acl_table_id_t tid, int feature_enable, int is_output)
Definition: in_out_acl.c:24
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
in_out_acl_table_id_t
Definition: in_out_acl.h:29
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:67
u8 is_add
Definition: ipsec_gre.api:36
static clib_error_t * set_input_acl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: in_out_acl.c:208
u32 l2input_intf_bitmap_enable(u32 sw_if_index, l2input_feat_masks_t feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_input.c:536
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
#define vec_elt(v, i)
Get vector value at index i.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vnet_classify_main_t * vnet_classify_main
Definition: in_out_acl.h:55
int vnet_set_in_out_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, u32 is_output)
Definition: in_out_acl.c:70
u64 uword
Definition: types.h:112
static vnet_feature_config_main_t * vnet_get_feature_arc_config_main(u8 arc_index)
Definition: feature.h:223
in_out_acl_main_t in_out_acl_main
Definition: in_out_acl.c:21
uword unformat_acl_type(unformat_input_t *input, va_list *args)
Definition: in_out_acl.c:269
#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:486
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
static clib_error_t * ip_in_out_acl_init(vlib_main_t *vm)
int vnet_set_output_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: in_out_acl.c:139
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:274
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170