FD.io VPP  v20.05.1-6-gf53edbc3b
Vector Packet Processing
cop.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 #include <vnet/cop/cop.h>
16 
18 
19 static clib_error_t *
21 {
22  cop_main_t * cm = &cop_main;
23  cop_config_data_t _data, *data = &_data;
24  vlib_main_t * vm = cm->vlib_main;
25  vnet_hw_interface_t * hi = vnet_get_sup_hw_interface (vnm, sw_if_index);;
26  cop_config_main_t * ccm;
27  int address_family;
28  u32 ci, default_next;
29 
30  clib_memset (data, 0, sizeof(*data));
31 
32  /*
33  * Ignore local interface, pg interfaces. $$$ need a #define for the
34  * first "real" interface. The answer is 5 at the moment.
35  */
37  return 0;
38 
39  for (address_family = VNET_COP_IP4; address_family < VNET_N_COPS;
40  address_family++)
41  {
42  ccm = &cm->cop_config_mains[address_family];
43 
44  /*
45  * Once-only code to initialize the per-address-family
46  * cop feature subgraphs.
47  * Since the (single) start-node, cop-input, must be able
48  * to push pkts into three separate subgraphs, we
49  * use a unified cop_feature_type_t enumeration.
50  */
51 
53  {
54  switch (address_family)
55  {
56  case VNET_COP_IP4:
57  {
58  static char * start_nodes[] = { "cop-input" };
59  static char * feature_nodes[] = {
60  [IP4_RX_COP_WHITELIST] = "ip4-cop-whitelist",
61  [IP4_RX_COP_INPUT] = "ip4-input",
62  };
63 
64  vnet_config_init (vm, &ccm->config_main,
65  start_nodes, ARRAY_LEN(start_nodes),
66  feature_nodes, ARRAY_LEN(feature_nodes));
67  }
68  break;
69  case VNET_COP_IP6:
70  {
71  static char * start_nodes[] = { "cop-input" };
72  static char * feature_nodes[] = {
73  [IP6_RX_COP_WHITELIST] = "ip6-cop-whitelist",
74  [IP6_RX_COP_INPUT] = "ip6-input",
75  };
76  vnet_config_init (vm, &ccm->config_main,
77  start_nodes, ARRAY_LEN(start_nodes),
78  feature_nodes, ARRAY_LEN(feature_nodes));
79  }
80  break;
81 
82  case VNET_COP_DEFAULT:
83  {
84  static char * start_nodes[] = { "cop-input" };
85  static char * feature_nodes[] = {
86  [DEFAULT_RX_COP_WHITELIST] = "default-cop-whitelist",
87  [DEFAULT_RX_COP_INPUT] = "ethernet-input",
88  };
89  vnet_config_init (vm, &ccm->config_main,
90  start_nodes, ARRAY_LEN(start_nodes),
91  feature_nodes, ARRAY_LEN(feature_nodes));
92  }
93  break;
94 
95  default:
96  clib_warning ("bug");
97  break;
98  }
99  }
101  ~0);
102 
104 
105  /* Create a sensible initial config: send pkts to xxx-input */
106  if (address_family == VNET_COP_IP4)
107  default_next = IP4_RX_COP_INPUT;
108  else if (address_family == VNET_COP_IP6)
109  default_next = IP6_RX_COP_INPUT;
110  else
111  default_next = DEFAULT_RX_COP_INPUT;
112 
113  if (is_add)
114  ci = vnet_config_add_feature (vm, &ccm->config_main,
115  ci,
116  default_next,
117  data, sizeof(*data));
118  else
119  ci = vnet_config_del_feature (vm, &ccm->config_main,
120  ci,
121  default_next,
122  data, sizeof(*data));
123 
125  }
126  return 0;
127 }
128 
130 
131 static clib_error_t *
133 {
134  cop_main_t * cm = &cop_main;
135 
136  cm->vlib_main = vm;
137  cm->vnet_main = vnet_get_main();
138 
139  return 0;
140 }
141 
142 /* *INDENT-OFF* */
144 {
145  .runs_after = VLIB_INITS ("ip4_whitelist_init", "ip6_whitelist_init"),
146 };
147 /* *INDENT-ON* */
148 
150 {
151  cop_main_t * cm = &cop_main;
152  vnet_sw_interface_t * sw;
153  int rv;
154  u32 node_index = enable_disable ? cop_input_node.index : ~0;
155 
156  /* Not a physical port? */
157  sw = vnet_get_sw_interface (cm->vnet_main, sw_if_index);
159  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
160 
161  /*
162  * Redirect pkts from the driver to the cop node.
163  * Returns VNET_API_ERROR_UNIMPLEMENTED if the h/w driver
164  * doesn't implement the API.
165  *
166  * Node_index = ~0 => shut off redirection
167  */
168  rv = vnet_hw_interface_rx_redirect_to_node (cm->vnet_main, sw_if_index,
169  node_index);
170  return rv;
171 }
172 
173 static clib_error_t *
175  unformat_input_t * input,
176  vlib_cli_command_t * cmd)
177 {
178  cop_main_t * cm = &cop_main;
179  u32 sw_if_index = ~0;
180  int enable_disable = 1;
181 
182  int rv;
183 
184  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
185  if (unformat (input, "disable"))
186  enable_disable = 0;
187  else if (unformat (input, "%U", unformat_vnet_sw_interface,
188  cm->vnet_main, &sw_if_index))
189  ;
190  else
191  break;
192  }
193 
194  if (sw_if_index == ~0)
195  return clib_error_return (0, "Please specify an interface...");
196 
197  rv = cop_interface_enable_disable (sw_if_index, enable_disable);
198 
199  switch(rv) {
200  case 0:
201  break;
202 
203  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
204  return clib_error_return
205  (0, "Invalid interface, only works on physical ports");
206  break;
207 
208  case VNET_API_ERROR_UNIMPLEMENTED:
209  return clib_error_return (0, "Device driver doesn't support redirection");
210  break;
211 
212  default:
213  return clib_error_return (0, "cop_interface_enable_disable returned %d",
214  rv);
215  }
216  return 0;
217 }
218 
219 VLIB_CLI_COMMAND (cop_interface_command, static) = {
220  .path = "cop interface",
221  .short_help =
222  "cop interface <interface-name> [disable]",
223  .function = cop_enable_disable_command_fn,
224 };
225 
226 
228 {
229  cop_main_t * cm = &cop_main;
230  vlib_main_t * vm = cm->vlib_main;
231  ip4_main_t * im4 = &ip4_main;
232  ip6_main_t * im6 = &ip6_main;
233  int address_family;
234  int is_add;
235  cop_config_main_t * ccm;
236  u32 next_to_add_del = 0;
237  uword * p;
238  u32 fib_index = 0;
239  u32 ci;
240  cop_config_data_t _data, *data=&_data;
241 
242  /*
243  * Enable / disable whitelist processing on the specified interface
244  */
245 
246  for (address_family = VNET_COP_IP4; address_family < VNET_N_COPS;
247  address_family++)
248  {
249  ccm = &cm->cop_config_mains[address_family];
250 
251  switch(address_family)
252  {
253  case VNET_COP_IP4:
254  is_add = (a->ip4 != 0);
255  next_to_add_del = IP4_RX_COP_WHITELIST;
256  /* configured opaque data must match, or no supper */
257  p = hash_get (im4->fib_index_by_table_id, a->fib_id);
258  if (p)
259  fib_index = p[0];
260  else
261  {
262  if (is_add)
263  return VNET_API_ERROR_NO_SUCH_FIB;
264  else
265  continue;
266  }
267  break;
268 
269  case VNET_COP_IP6:
270  is_add = (a->ip6 != 0);
271  next_to_add_del = IP6_RX_COP_WHITELIST;
272  p = hash_get (im6->fib_index_by_table_id, a->fib_id);
273  if (p)
274  fib_index = p[0];
275  else
276  {
277  if (is_add)
278  return VNET_API_ERROR_NO_SUCH_FIB;
279  else
280  continue;
281  }
282  break;
283 
284  case VNET_COP_DEFAULT:
285  is_add = (a->default_cop != 0);
286  next_to_add_del = DEFAULT_RX_COP_WHITELIST;
287  break;
288 
289  default:
290  clib_warning ("BUG");
291  }
292 
294  data->fib_index = fib_index;
295 
296  if (is_add)
297  ci = vnet_config_add_feature (vm, &ccm->config_main,
298  ci,
299  next_to_add_del,
300  data, sizeof (*data));
301  else
302  ci = vnet_config_del_feature (vm, &ccm->config_main,
303  ci,
304  next_to_add_del,
305  data, sizeof (*data));
306 
308  }
309  return 0;
310 }
311 
312 static clib_error_t *
314  unformat_input_t * input,
315  vlib_cli_command_t * cmd)
316 {
317  cop_main_t * cm = &cop_main;
318  u32 sw_if_index = ~0;
319  u8 ip4 = 0;
320  u8 ip6 = 0;
321  u8 default_cop = 0;
322  u32 fib_id = 0;
323  int rv;
325 
326  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
327  if (unformat (input, "ip4"))
328  ip4 = 1;
329  else if (unformat (input, "ip6"))
330  ip6 = 1;
331  else if (unformat (input, "default"))
332  default_cop = 1;
333  else if (unformat (input, "%U", unformat_vnet_sw_interface,
334  cm->vnet_main, &sw_if_index))
335  ;
336  else if (unformat (input, "fib-id %d", &fib_id))
337  ;
338  else
339  break;
340  }
341 
342  if (sw_if_index == ~0)
343  return clib_error_return (0, "Please specify an interface...");
344 
346  a->ip4 = ip4;
347  a->ip6 = ip6;
348  a->default_cop = default_cop;
349  a->fib_id = fib_id;
350 
352 
353  switch(rv) {
354  case 0:
355  break;
356 
357  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
358  return clib_error_return
359  (0, "Invalid interface, only works on physical ports");
360  break;
361 
362  case VNET_API_ERROR_NO_SUCH_FIB:
363  return clib_error_return
364  (0, "Invalid fib");
365  break;
366 
367  case VNET_API_ERROR_UNIMPLEMENTED:
368  return clib_error_return (0, "Device driver doesn't support redirection");
369  break;
370 
371  default:
372  return clib_error_return (0, "cop_whitelist_enable_disable returned %d",
373  rv);
374  }
375 
376  return 0;
377 }
378 
379 VLIB_CLI_COMMAND (cop_whitelist_command, static) = {
380  .path = "cop whitelist",
381  .short_help =
382  "cop whitelist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]",
384 };
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
a
Definition: bitmap.h:538
cop_config_main_t cop_config_mains[VNET_N_COPS]
Definition: cop.h:66
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1205
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
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:363
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
unsigned char u8
Definition: types.h:56
u32 * node_index_by_feature_index
Definition: config.h:102
vnet_main_t * vnet_main
Definition: cop.h:70
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
u32 * config_index_by_sw_if_index
Definition: cop.h:58
vl_api_ip6_address_t ip6
Definition: one.api:424
static clib_error_t * cop_whitelist_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cop.c:313
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static clib_error_t * cop_init(vlib_main_t *vm)
Definition: cop.c:132
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
#define hash_get(h, key)
Definition: hash.h:249
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:132
vlib_node_registration_t cop_input_node
(constructor) VLIB_REGISTER_NODE (cop_input_node)
Definition: node1.c:258
struct _unformat_input_t unformat_input_t
address_family
Definition: ip_types.api:21
vl_api_ip4_address_t ip4
Definition: one.api:376
int cop_whitelist_enable_disable(cop_whitelist_enable_disable_args_t *a)
Definition: cop.c:227
ip6_main_t ip6_main
Definition: ip6_forward.c:2784
vnet_device_class_t vnet_local_interface_device_class
vlib_main_t * vm
Definition: in2out_ed.c:1599
uword * fib_index_by_table_id
Definition: ip6.h:206
static clib_error_t * cop_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: cop.c:20
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
#define clib_warning(format, args...)
Definition: error.h:59
int cop_interface_enable_disable(u32 sw_if_index, int enable_disable)
Definition: cop.c:149
#define ARRAY_LEN(x)
Definition: clib.h:66
cop_main_t cop_main
Definition: cop.c:17
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static clib_error_t * cop_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cop.c:174
u8 data[128]
Definition: ipsec_types.api:89
IPv4 main type.
Definition: ip4.h:106
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:299
vl_api_ip4_address_t hi
Definition: arp.api:37
u64 uword
Definition: types.h:112
vnet_sw_interface_type_t type
Definition: interface.h:722
vlib_main_t * vlib_main
Definition: cop.h:69
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(cop_sw_interface_add_del)
Definition: cop.h:65
#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:554
#define VLIB_INITS(...)
Definition: init.h:344
u32 fib_index
Definition: cop.h:62
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vnet_config_main_t config_main
Definition: cop.h:57
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171