FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
adl.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016,2020 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/ethernet/ethernet.h>
16 #include <vnet/plugin/plugin.h>
17 #include <vpp/app/version.h>
18 #include <plugins/adl/adl.h>
19 
21 
22 static clib_error_t *
24 {
26  adl_config_data_t _data, *data = &_data;
27  vlib_main_t *vm = am->vlib_main;
29  adl_config_main_t *acm;
30  int address_family;
31  u32 ci, default_next;
32 
33  clib_memset (data, 0, sizeof (*data));
34 
35  /*
36  * Ignore local interface, pg interfaces. $$$ need a #define for the
37  * first "real" interface. The answer is 5 at the moment.
38  */
39  if (hi->dev_class_index == vnet_local_interface_device_class.index)
40  return 0;
41 
44  {
45  acm = &am->adl_config_mains[address_family];
46 
47  /*
48  * Once-only code to initialize the per-address-family
49  * adl feature subgraphs.
50  * Since the (single) start-node, adl-input, must be able
51  * to push pkts into three separate subgraphs, we
52  * use a unified adl_feature_type_t enumeration.
53  */
54 
56  {
57  switch (address_family)
58  {
59  case VNET_ADL_IP4:
60  {
61  static char *start_nodes[] = { "adl-input" };
62  static char *feature_nodes[] = {
63  [IP4_RX_ADL_ALLOWLIST] = "ip4-adl-allowlist",
64  [IP4_RX_ADL_INPUT] = "ip4-input",
65  };
66 
68  start_nodes, ARRAY_LEN (start_nodes),
69  feature_nodes, ARRAY_LEN (feature_nodes));
70  }
71  break;
72  case VNET_ADL_IP6:
73  {
74  static char *start_nodes[] = { "adl-input" };
75  static char *feature_nodes[] = {
76  [IP6_RX_ADL_ALLOWLIST] = "ip6-adl-allowlist",
77  [IP6_RX_ADL_INPUT] = "ip6-input",
78  };
80  start_nodes, ARRAY_LEN (start_nodes),
81  feature_nodes, ARRAY_LEN (feature_nodes));
82  }
83  break;
84 
85  case VNET_ADL_DEFAULT:
86  {
87  static char *start_nodes[] = { "adl-input" };
88  static char *feature_nodes[] = {
89  [DEFAULT_RX_ADL_ALLOWLIST] = "default-adl-allowlist",
90  [DEFAULT_RX_ADL_INPUT] = "ethernet-input",
91  };
93  start_nodes, ARRAY_LEN (start_nodes),
94  feature_nodes, ARRAY_LEN (feature_nodes));
95  }
96  break;
97 
98  default:
99  clib_warning ("bug");
100  break;
101  }
102  }
104  ~0);
105 
107 
108  /* Create a sensible initial config: send pkts to xxx-input */
110  default_next = IP4_RX_ADL_INPUT;
111  else if (address_family == VNET_ADL_IP6)
112  default_next = IP6_RX_ADL_INPUT;
113  else
114  default_next = DEFAULT_RX_ADL_INPUT;
115 
116  if (is_add)
118  ci, default_next, data, sizeof (*data));
119  else
120  {
121  /* If the feature was actually configured */
122  if (ci != ~0)
123  {
125  ci, default_next, data,
126  sizeof (*data));
127  }
128  }
129 
131  }
132  return 0;
133 }
134 
136 
137 static clib_error_t *
139 {
140  adl_main_t *cm = &adl_main;
141 
142  cm->vlib_main = vm;
143  cm->vnet_main = vnet_get_main ();
144 
145  /*
146  * Setup the packet generator so we can inject ethernet
147  * frames into this node
148  */
150  return 0;
151 }
152 
153 /* *INDENT-OFF* */
155 {
156  .runs_after = VLIB_INITS ("ip4_allowlist_init", "ip6_allowlist_init"),
157 };
158 /* *INDENT-ON* */
159 
160 /* *INDENT-OFF* */
161 VNET_FEATURE_INIT (adl, static) =
162 {
163  .arc_name = "device-input",
164  .node_name = "adl-input",
165  .runs_before = VNET_FEATURES ("ethernet-input"),
166 };
167 /* *INDENT-ON */
168 
170 {
171  /*
172  * Redirect pkts from the driver to the adl node.
173  */
174  vnet_feature_enable_disable ("device-input", "adl-input",
175  sw_if_index, enable_disable, 0, 0);
176  return 0;
177 }
178 
179 static clib_error_t *
181  unformat_input_t * input,
182  vlib_cli_command_t * cmd)
183 {
184  adl_main_t * cm = &adl_main;
185  u32 sw_if_index = ~0;
186  int enable_disable = 1;
187 
188  int rv;
189 
190  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
191  if (unformat (input, "disable"))
192  enable_disable = 0;
193  else if (unformat (input, "%U", unformat_vnet_sw_interface,
194  cm->vnet_main, &sw_if_index))
195  ;
196  else
197  break;
198  }
199 
200  if (sw_if_index == ~0)
201  return clib_error_return (0, "Please specify an interface...");
202 
203  rv = adl_interface_enable_disable (sw_if_index, enable_disable);
204 
205  switch(rv) {
206  case 0:
207  break;
208 
209  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
210  return clib_error_return
211  (0, "Invalid interface, only works on physical ports");
212  break;
213 
214  case VNET_API_ERROR_UNIMPLEMENTED:
215  return clib_error_return (0, "Device driver doesn't support redirection");
216  break;
217 
218  default:
219  return clib_error_return (0, "adl_interface_enable_disable returned %d",
220  rv);
221  }
222  return 0;
223 }
224 
226  .path = "adl interface",
227  .short_help =
228  "adl interface <interface-name> [disable]",
229  .function = adl_enable_disable_command_fn,
230 };
231 
232 
234 {
235  adl_main_t * cm = &adl_main;
236  vlib_main_t * vm = cm->vlib_main;
237  ip4_main_t * im4 = &ip4_main;
238  ip6_main_t * im6 = &ip6_main;
239  int address_family;
240  int is_add;
241  adl_config_main_t * acm;
242  u32 next_to_add_del = 0;
243  uword * p;
244  u32 fib_index = 0;
245  u32 ci;
246  adl_config_data_t _data, *data=&_data;
247 
248  /*
249  * Enable / disable allowlist processing on the specified interface
250  */
251 
253  address_family++)
254  {
255  acm = &cm->adl_config_mains[address_family];
256 
257  switch(address_family)
258  {
259  case VNET_ADL_IP4:
260  is_add = (a->ip4 != 0);
261  next_to_add_del = IP4_RX_ADL_ALLOWLIST;
262  /* configured opaque data must match, or no supper */
263  p = hash_get (im4->fib_index_by_table_id, a->fib_id);
264  if (p)
265  fib_index = p[0];
266  else
267  {
268  if (is_add)
269  return VNET_API_ERROR_NO_SUCH_FIB;
270  else
271  continue;
272  }
273  break;
274 
275  case VNET_ADL_IP6:
276  is_add = (a->ip6 != 0);
277  next_to_add_del = IP6_RX_ADL_ALLOWLIST;
278  p = hash_get (im6->fib_index_by_table_id, a->fib_id);
279  if (p)
280  fib_index = p[0];
281  else
282  {
283  if (is_add)
284  return VNET_API_ERROR_NO_SUCH_FIB;
285  else
286  continue;
287  }
288  break;
289 
290  case VNET_ADL_DEFAULT:
291  is_add = (a->default_adl != 0);
292  next_to_add_del = DEFAULT_RX_ADL_ALLOWLIST;
293  break;
294 
295  default:
296  clib_warning ("BUG");
297  }
298 
299  ci = acm->config_index_by_sw_if_index[a->sw_if_index];
300  data->fib_index = fib_index;
301 
302  if (is_add)
304  ci,
305  next_to_add_del,
306  data, sizeof (*data));
307  else
308  {
309  /* If the feature was actually configured... */
310  if (ci != ~0)
311  {
312  /* delete it */
314  ci,
315  next_to_add_del,
316  data, sizeof (*data));
317  }
318  }
319 
320  acm->config_index_by_sw_if_index[a->sw_if_index] = ci;
321  }
322  return 0;
323 }
324 
325 static clib_error_t *
327  unformat_input_t * input,
328  vlib_cli_command_t * cmd)
329 {
330  adl_main_t * cm = &adl_main;
331  u32 sw_if_index = ~0;
332  u8 ip4 = 0;
333  u8 ip6 = 0;
334  u8 default_adl = 0;
335  u32 fib_id = 0;
336  int rv;
338 
339  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
340  if (unformat (input, "ip4"))
341  ip4 = 1;
342  else if (unformat (input, "ip6"))
343  ip6 = 1;
344  else if (unformat (input, "default"))
345  default_adl = 1;
346  else if (unformat (input, "%U", unformat_vnet_sw_interface,
347  cm->vnet_main, &sw_if_index))
348  ;
349  else if (unformat (input, "fib-id %d", &fib_id))
350  ;
351  else
352  break;
353  }
354 
355  if (sw_if_index == ~0)
356  return clib_error_return (0, "Please specify an interface...");
357 
358  a->sw_if_index = sw_if_index;
359  a->ip4 = ip4;
360  a->ip6 = ip6;
361  a->default_adl = default_adl;
362  a->fib_id = fib_id;
363 
365 
366  switch(rv) {
367  case 0:
368  break;
369 
370  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
371  return clib_error_return
372  (0, "Invalid interface, only works on physical ports");
373  break;
374 
375  case VNET_API_ERROR_NO_SUCH_FIB:
376  return clib_error_return
377  (0, "Invalid fib");
378  break;
379 
380  case VNET_API_ERROR_UNIMPLEMENTED:
381  return clib_error_return (0, "Device driver doesn't support redirection");
382  break;
383 
384  default:
385  return clib_error_return (0, "adl_allowlist_enable_disable returned %d",
386  rv);
387  }
388 
389  return 0;
390 }
391 
392 /* *INDENT-OFF* */
394 {
395  .path = "adl allowlist",
396  .short_help =
397  "adl allowlist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]",
399 };
400 /* *INDENT-ON* */
401 
402 /* *INDENT-OFF* */
404 {
405  .version = VPP_BUILD_VER,
406  .description = "Allow/deny list plugin",
407 };
408 /* *INDENT-ON* */
409 
410 
411 /*
412  * fd.io coding-style-patch-verification: ON
413  *
414  * Local Variables:
415  * eval: (c-set-style "gnu")
416  * End:
417  */
adl_config_main_t::config_index_by_sw_if_index
u32 * config_index_by_sw_if_index
Definition: adl.h:57
VNET_ADL_IP4
@ VNET_ADL_IP4
Definition: adl.h:32
adl_allowlist_enable_disable_command_fn
static clib_error_t * adl_allowlist_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adl.c:326
adl_input_node
vlib_node_registration_t adl_input_node
(constructor) VLIB_REGISTER_NODE (adl_input_node)
Definition: node.c:258
adl_sw_interface_add_del
static clib_error_t * adl_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: adl.c:23
DEFAULT_RX_ADL_ALLOWLIST
@ DEFAULT_RX_ADL_ALLOWLIST
Definition: adl.h:42
vnet_config_main_t::node_index_by_feature_index
u32 * node_index_by_feature_index
Definition: config.h:102
vnet_config_add_feature
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:307
address_family
address_family
Definition: ip_types.api:21
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
ip4_main
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
ethernet_setup_node
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:408
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_cli_command_t::path
char * path
Definition: cli.h:96
DEFAULT_RX_ADL_INPUT
@ DEFAULT_RX_ADL_INPUT
Definition: adl.h:47
am
app_main_t * am
Definition: application.c:489
ip4_main_t::fib_index_by_table_id
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:133
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
unformat_input_t
struct _unformat_input_t unformat_input_t
ethernet.h
adl_main_t
Definition: adl.h:64
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vnet_config_init
void vnet_config_init(vlib_main_t *vm, vnet_config_main_t *cm, char *start_node_names[], int n_start_node_names, char *feature_node_names[], int n_feature_node_names)
Definition: config.c:168
IP4_RX_ADL_ALLOWLIST
@ IP4_RX_ADL_ALLOWLIST
Definition: adl.h:40
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
VNET_ADL_IP6
@ VNET_ADL_IP6
Definition: adl.h:33
adl_allowlist_command
static vlib_cli_command_t adl_allowlist_command
(constructor) VLIB_CLI_COMMAND (adl_allowlist_command)
Definition: adl.c:393
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
uword
u64 uword
Definition: types.h:112
VNET_SW_INTERFACE_ADD_DEL_FUNCTION
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(adl_sw_interface_add_del)
hash_get
#define hash_get(h, key)
Definition: hash.h:249
vnet_local_interface_device_class
vnet_device_class_t vnet_local_interface_device_class
adl_config_main_t
Definition: adl.h:55
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:591
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
adl_allowlist_enable_disable
int adl_allowlist_enable_disable(adl_allowlist_enable_disable_args_t *a)
Definition: adl.c:233
adl_interface_enable_disable
int adl_interface_enable_disable(u32 sw_if_index, int enable_disable)
Definition: adl.c:169
plugin.h
ip6_main
ip6_main_t ip6_main
Definition: ip6_forward.c:2787
data
u8 data[128]
Definition: ipsec_types.api:92
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
adl_config_data_t
Definition: adl.h:60
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:459
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
u32
unsigned int u32
Definition: types.h:88
IP6_RX_ADL_ALLOWLIST
@ IP6_RX_ADL_ALLOWLIST
Definition: adl.h:41
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
vnet_get_sup_hw_interface
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:92
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
VNET_FEATURE_INIT
VNET_FEATURE_INIT(adl, static)
adl_init
static clib_error_t * adl_init(vlib_main_t *vm)
Definition: adl.c:138
adl_allowlist_enable_disable_args_t
Definition: adl.h:80
VNET_N_ADLS
@ VNET_N_ADLS
Definition: adl.h:35
ip6_main_t
Definition: ip6.h:110
vnet_feature_enable_disable
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: pnat_test_stubs.h:50
VNET_ADL_DEFAULT
@ VNET_ADL_DEFAULT
Definition: adl.h:34
VLIB_PLUGIN_REGISTER
VLIB_PLUGIN_REGISTER()
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
VLIB_INITS
#define VLIB_INITS(...)
Definition: init.h:352
vnet_config_del_feature
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:376
VNET_FEATURES
#define VNET_FEATURES(...)
Definition: feature.h:470
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
a
a
Definition: bitmap.h:544
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
IP4_RX_ADL_INPUT
@ IP4_RX_ADL_INPUT
Definition: adl.h:45
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
rv
int __clib_unused rv
Definition: application.c:491
vlib_cli_command_t
Definition: cli.h:92
adl_main
adl_main_t adl_main
Definition: adl.c:20
ip4_main_t
IPv4 main type.
Definition: ip4.h:107
adl_enable_disable_command_fn
static clib_error_t * adl_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adl.c:180
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
adl_interface_command
static vlib_cli_command_t adl_interface_command
(constructor) VLIB_CLI_COMMAND (adl_interface_command)
Definition: adl.c:225
adl_config_main_t::config_main
vnet_config_main_t config_main
Definition: adl.h:56
IP6_RX_ADL_INPUT
@ IP6_RX_ADL_INPUT
Definition: adl.h:46
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
adl.h
ip6_main_t::fib_index_by_table_id
uword * fib_index_by_table_id
Definition: ip6.h:137