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