FD.io VPP  v16.06
Vector Packet Processing
input_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  input_acl_main_t *am,
24  u32 sw_if_index,
26  int feature_enable)
27 {
28 
29  if (tid == INPUT_ACL_TABLE_L2)
30  {
31  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ACL,
32  feature_enable);
33  }
34  else
35  { /* IP[46] */
36  ip_lookup_main_t * lm;
37  ip_config_main_t * ipcm;
38  u32 ftype;
39  u32 ci;
40 
41  if (tid == INPUT_ACL_TABLE_IP4)
42  {
43  lm = &ip4_main.lookup_main;
45  }
46  else
47  {
48  lm = &ip6_main.lookup_main;
50  }
51 
52  ipcm = &lm->rx_config_mains[VNET_UNICAST];
53 
54  ci = ipcm->config_index_by_sw_if_index[sw_if_index];
55  ci = ((feature_enable)
58  (vnm, &ipcm->config_main, ci, ftype,
59  /* config data */ 0,
60  /* # bytes of config data */ 0);
61 
62  ipcm->config_index_by_sw_if_index[sw_if_index] = ci;
63  am->vnet_config_main[tid] = &ipcm->config_main;
64  }
65 
66  return 0;
67 }
68 
69 int vnet_set_input_acl_intfc (vlib_main_t * vm, u32 sw_if_index,
70  u32 ip4_table_index,
71  u32 ip6_table_index,
72  u32 l2_table_index, u32 is_add)
73 {
76  u32 acl[INPUT_ACL_N_TABLES] = {ip4_table_index, ip6_table_index,
77  l2_table_index};
78  u32 ti;
79 
80  /* Assume that we've validated sw_if_index in the API layer */
81 
82  for (ti = 0; ti < INPUT_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[ti], sw_if_index, ~0);
92 
93  /* Reject any DEL operation with wrong sw_if_index */
94  if (!is_add &&
95  (acl[ti] != am->classify_table_index_by_sw_if_index[ti][sw_if_index]))
96  {
97  clib_warning ("Non-existent intf_idx=%d with table_index=%d for delete",
98  sw_if_index, acl[ti]);
99  return VNET_API_ERROR_NO_SUCH_TABLE;
100  }
101 
102  /* Return ok on ADD operaton if feature is already enabled */
103  if (is_add &&
104  am->classify_table_index_by_sw_if_index[ti][sw_if_index] != ~0)
105  return 0;
106 
107  vnet_inacl_ip_feature_enable (vm, am, sw_if_index, ti, is_add);
108 
109  if (is_add)
110  am->classify_table_index_by_sw_if_index[ti][sw_if_index] = acl[ti];
111  else
112  am->classify_table_index_by_sw_if_index[ti][sw_if_index] = ~0;
113  }
114 
115  return 0;
116 }
117 
118 static clib_error_t *
120  unformat_input_t * input,
121  vlib_cli_command_t * cmd)
122 {
123  vnet_main_t * vnm = vnet_get_main();
124  u32 sw_if_index = ~0;
125  u32 ip4_table_index = ~0;
126  u32 ip6_table_index = ~0;
127  u32 l2_table_index = ~0;
128  u32 is_add = 1;
129  u32 idx_cnt = 0;
130  int rv;
131 
133  {
134  if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
135  vnm, &sw_if_index))
136  ;
137  else if (unformat (input, "ip4-table %d", &ip4_table_index))
138  idx_cnt++;
139  else if (unformat (input, "ip6-table %d", &ip6_table_index))
140  idx_cnt++;
141  else if (unformat (input, "l2-table %d", &l2_table_index))
142  idx_cnt++;
143  else if (unformat (input, "del"))
144  is_add = 0;
145  else
146  break;
147  }
148 
149  if (sw_if_index == ~0)
150  return clib_error_return (0, "Interface must be specified.");
151 
152  if (!idx_cnt)
153  return clib_error_return (0, "Table index should be specified.");
154 
155  if (idx_cnt > 1)
156  return clib_error_return (0, "Only one table index per API is allowed.");
157 
158  rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
159  ip6_table_index, l2_table_index, is_add);
160 
161  switch (rv)
162  {
163  case 0:
164  break;
165 
166  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
167  return clib_error_return (0, "No such interface");
168 
169  case VNET_API_ERROR_NO_SUCH_ENTRY:
170  return clib_error_return (0, "No such classifier table");
171  }
172  return 0;
173 }
174 
175 /*
176  * Configure interface to enable/disble input ACL feature:
177  * intfc - interface name to be configured as input ACL
178  * Ip4-table <index> [del] - enable/disable IP4 input ACL
179  * Ip6-table <index> [del] - enable/disable IP6 input ACL
180  * l2-table <index> [del] - enable/disable Layer2 input ACL
181  *
182  * Note: Only one table index per API call is allowed.
183  *
184  */
185 VLIB_CLI_COMMAND (set_input_acl_command, static) = {
186  .path = "set interface input acl",
187  .short_help =
188  "set interface input acl intfc <int> [ip4-table <index>]\n"
189  " [ip6-table <index>] [l2-table <index>] [del]",
190  .function = set_input_acl_command_fn,
191 };
192 
194 {
196  clib_error_t * error = 0;
197 
198  if ((error = vlib_call_init_function (vm, ip_inacl_init)))
199  return error;
200 
201  am->vlib_main = vm;
202  am->vnet_main = vnet_get_main();
204 
205  return 0;
206 }
207 
209 
210 uword unformat_acl_type (unformat_input_t * input, va_list * args)
211 {
212  u32 * acl_type = va_arg (*args, u32 *);
213  u32 tid = INPUT_ACL_N_TABLES;
214 
215  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
216  if (unformat (input, "ip4"))
217  tid = INPUT_ACL_TABLE_IP4;
218  else if (unformat (input, "ip6"))
219  tid = INPUT_ACL_TABLE_IP6;
220  else if (unformat (input, "l2"))
221  tid = INPUT_ACL_TABLE_L2;
222  else
223  break;
224  }
225 
226  *acl_type = tid;
227  return 1;
228 }
229 
230 u8 * format_vnet_inacl_info (u8 * s, va_list * va)
231 {
232  input_acl_main_t * am = va_arg (*va, input_acl_main_t *);
233  int sw_if_idx = va_arg (*va, int);
234  u32 tid = va_arg (*va, u32);
235 
236  if (tid == ~0)
237  {
238  s = format (s, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
239  "Interface name");
240  return s;
241  }
242 
243  s = format (s, "%10d%20d\t\t%U", sw_if_idx, tid,
244  format_vnet_sw_if_index_name, am->vnet_main, sw_if_idx);
245 
246  return s;
247 }
248 
249 static clib_error_t *
251  unformat_input_t * input,
252  vlib_cli_command_t * cmd)
253 {
256  int i;
257  u32 * vec_tbl;
258 
260  {
261  if (unformat (input, "type %U", unformat_acl_type, &type))
262  ;
263  else
264  break;
265  }
266 
267  if (type == INPUT_ACL_N_TABLES)
268  return clib_error_return (0, "Invalid input ACL table type.");
269 
271 
272  if (vec_len(vec_tbl))
273  vlib_cli_output (vm, "%U", format_vnet_inacl_info, am, ~0 /* hdr */, ~0);
274  else
275  vlib_cli_output (vm, "No input ACL tables configured");
276 
277  for (i = 0; i < vec_len (vec_tbl); i++)
278  {
279  if (vec_elt(vec_tbl, i) == ~0)
280  continue;
281 
283  am, i, vec_elt(vec_tbl, i));
284  }
285 
286  return 0;
287 }
288 
289 VLIB_CLI_COMMAND (show_inacl_command, static) = {
290  .path = "show inacl",
291  .short_help = "show inacl type [ip4|ip6|l2]",
292  .function = show_inacl_command_fn,
293 };
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
u32 * config_index_by_sw_if_index
Definition: lookup.h:345
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
vnet_main_t * vnet_main
Definition: input_acl.h:42
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
u32 * classify_table_index_by_sw_if_index[INPUT_ACL_N_TABLES]
Definition: input_acl.h:38
static clib_error_t * set_input_acl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: input_acl.c:119
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
u32 vnet_config_del_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:284
ip_config_main_t rx_config_mains[VNET_N_CAST]
Definition: lookup.h:401
ip_lookup_main_t lookup_main
Definition: ip4.h:129
unformat_function_t unformat_vnet_sw_interface
format_function_t format_vnet_sw_if_index_name
vnet_classify_main_t * vnet_classify_main
Definition: input_acl.h:43
u8 * format_vnet_inacl_info(u8 *s, va_list *va)
Definition: input_acl.c:230
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
static int vnet_inacl_ip_feature_enable(vlib_main_t *vnm, input_acl_main_t *am, u32 sw_if_index, input_acl_table_id_t tid, int feature_enable)
Definition: input_acl.c:22
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
#define clib_warning(format, args...)
Definition: error.h:59
#define vlib_call_init_function(vm, x)
Definition: init.h:159
uword unformat_acl_type(unformat_input_t *input, va_list *args)
Definition: input_acl.c:210
vnet_config_main_t * vnet_config_main[INPUT_ACL_N_TABLES]
Definition: input_acl.h:44
vlib_main_t * vlib_main
Definition: input_acl.h:41
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
#define pool_is_free_index(P, I)
Definition: pool.h:197
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:50
input_acl_main_t input_acl_main
Definition: input_acl.c:19
input_acl_table_id_t
Definition: input_acl.h:23
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2490
ip_lookup_main_t lookup_main
Definition: ip6.h:135
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:233
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:21
u64 uword
Definition: types.h:112
#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)
Definition: l2_input.c:473
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static clib_error_t * ip_inacl_init(vlib_main_t *vm)
Definition: ip_input_acl.c:396
static clib_error_t * show_inacl_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: input_acl.c:250
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
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:69
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
#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:443
vnet_config_main_t config_main
Definition: lookup.h:343
clib_error_t * input_acl_init(vlib_main_t *vm)
Definition: input_acl.c:193