FD.io VPP  v17.07-30-g839fa73
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 *
20 cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
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  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 
103  ci = ccm->config_index_by_sw_if_index[sw_if_index];
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 
124  ccm->config_index_by_sw_if_index[sw_if_index] = ci;
125  }
126  return 0;
127 }
128 
130 
131 static clib_error_t *
133 {
134  cop_main_t * cm = &cop_main;
135  clib_error_t * error;
136 
137  if ((error = vlib_call_init_function (vm, ip4_whitelist_init)))
138  return error;
139 
140  if ((error = vlib_call_init_function (vm, ip6_whitelist_init)))
141  return error;
142 
143  cm->vlib_main = vm;
144  cm->vnet_main = vnet_get_main();
145 
146  return 0;
147 }
148 
150 
151 int cop_interface_enable_disable (u32 sw_if_index, int enable_disable)
152 {
153  cop_main_t * cm = &cop_main;
154  vnet_sw_interface_t * sw;
155  int rv;
156  u32 node_index = enable_disable ? cop_input_node.index : ~0;
157 
158  /* Not a physical port? */
159  sw = vnet_get_sw_interface (cm->vnet_main, sw_if_index);
161  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
162 
163  /*
164  * Redirect pkts from the driver to the cop node.
165  * Returns VNET_API_ERROR_UNIMPLEMENTED if the h/w driver
166  * doesn't implement the API.
167  *
168  * Node_index = ~0 => shut off redirection
169  */
170  rv = vnet_hw_interface_rx_redirect_to_node (cm->vnet_main, sw_if_index,
171  node_index);
172  return rv;
173 }
174 
175 static clib_error_t *
177  unformat_input_t * input,
178  vlib_cli_command_t * cmd)
179 {
180  cop_main_t * cm = &cop_main;
181  u32 sw_if_index = ~0;
182  int enable_disable = 1;
183 
184  int rv;
185 
186  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
187  if (unformat (input, "disable"))
188  enable_disable = 0;
189  else if (unformat (input, "%U", unformat_vnet_sw_interface,
190  cm->vnet_main, &sw_if_index))
191  ;
192  else
193  break;
194  }
195 
196  if (sw_if_index == ~0)
197  return clib_error_return (0, "Please specify an interface...");
198 
199  rv = cop_interface_enable_disable (sw_if_index, enable_disable);
200 
201  switch(rv) {
202  case 0:
203  break;
204 
205  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
206  return clib_error_return
207  (0, "Invalid interface, only works on physical ports");
208  break;
209 
210  case VNET_API_ERROR_UNIMPLEMENTED:
211  return clib_error_return (0, "Device driver doesn't support redirection");
212  break;
213 
214  default:
215  return clib_error_return (0, "cop_interface_enable_disable returned %d",
216  rv);
217  }
218  return 0;
219 }
220 
221 VLIB_CLI_COMMAND (cop_interface_command, static) = {
222  .path = "cop interface",
223  .short_help =
224  "cop interface <interface-name> [disable]",
225  .function = cop_enable_disable_command_fn,
226 };
227 
228 
230 {
231  cop_main_t * cm = &cop_main;
232  vlib_main_t * vm = cm->vlib_main;
233  ip4_main_t * im4 = &ip4_main;
234  ip6_main_t * im6 = &ip6_main;
235  int address_family;
236  int is_add;
237  cop_config_main_t * ccm;
238  u32 next_to_add_del = 0;
239  uword * p;
240  u32 fib_index = 0;
241  u32 ci;
242  cop_config_data_t _data, *data=&_data;
243 
244  /*
245  * Enable / disable whitelist processing on the specified interface
246  */
247 
248  for (address_family = VNET_COP_IP4; address_family < VNET_N_COPS;
249  address_family++)
250  {
251  ccm = &cm->cop_config_mains[address_family];
252 
253  switch(address_family)
254  {
255  case VNET_COP_IP4:
256  is_add = (a->ip4 != 0);
257  next_to_add_del = IP4_RX_COP_WHITELIST;
258  /* configured opaque data must match, or no supper */
259  p = hash_get (im4->fib_index_by_table_id, a->fib_id);
260  if (p)
261  fib_index = p[0];
262  else
263  {
264  if (is_add)
265  return VNET_API_ERROR_NO_SUCH_FIB;
266  else
267  continue;
268  }
269  break;
270 
271  case VNET_COP_IP6:
272  is_add = (a->ip6 != 0);
273  next_to_add_del = IP6_RX_COP_WHITELIST;
274  p = hash_get (im6->fib_index_by_table_id, a->fib_id);
275  if (p)
276  fib_index = p[0];
277  else
278  {
279  if (is_add)
280  return VNET_API_ERROR_NO_SUCH_FIB;
281  else
282  continue;
283  }
284  break;
285 
286  case VNET_COP_DEFAULT:
287  is_add = (a->default_cop != 0);
288  next_to_add_del = DEFAULT_RX_COP_WHITELIST;
289  break;
290 
291  default:
292  clib_warning ("BUG");
293  }
294 
296  data->fib_index = fib_index;
297 
298  if (is_add)
299  ci = vnet_config_add_feature (vm, &ccm->config_main,
300  ci,
301  next_to_add_del,
302  data, sizeof (*data));
303  else
304  ci = vnet_config_del_feature (vm, &ccm->config_main,
305  ci,
306  next_to_add_del,
307  data, sizeof (*data));
308 
310  }
311  return 0;
312 }
313 
314 static clib_error_t *
316  unformat_input_t * input,
317  vlib_cli_command_t * cmd)
318 {
319  cop_main_t * cm = &cop_main;
320  u32 sw_if_index = ~0;
321  u8 ip4 = 0;
322  u8 ip6 = 0;
323  u8 default_cop = 0;
324  u32 fib_id = 0;
325  int rv;
327 
328  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
329  if (unformat (input, "ip4"))
330  ip4 = 1;
331  else if (unformat (input, "ip6"))
332  ip6 = 1;
333  else if (unformat (input, "default"))
334  default_cop = 1;
335  else if (unformat (input, "%U", unformat_vnet_sw_interface,
336  cm->vnet_main, &sw_if_index))
337  ;
338  else if (unformat (input, "fib-id %d", &fib_id))
339  ;
340  else
341  break;
342  }
343 
344  if (sw_if_index == ~0)
345  return clib_error_return (0, "Please specify an interface...");
346 
347  a->sw_if_index = sw_if_index;
348  a->ip4 = ip4;
349  a->ip6 = ip6;
350  a->default_cop = default_cop;
351  a->fib_id = fib_id;
352 
354 
355  switch(rv) {
356  case 0:
357  break;
358 
359  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
360  return clib_error_return
361  (0, "Invalid interface, only works on physical ports");
362  break;
363 
364  case VNET_API_ERROR_NO_SUCH_FIB:
365  return clib_error_return
366  (0, "Invalid fib");
367  break;
368 
369  case VNET_API_ERROR_UNIMPLEMENTED:
370  return clib_error_return (0, "Device driver doesn't support redirection");
371  break;
372 
373  default:
374  return clib_error_return (0, "cop_whitelist_enable_disable returned %d",
375  rv);
376  }
377 
378  return 0;
379 }
380 
381 VLIB_CLI_COMMAND (cop_whitelist_command, static) = {
382  .path = "cop whitelist",
383  .short_help =
384  "cop whitelist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]",
386 };
387 
vmrglw vmrglh hi
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:161
a
Definition: bitmap.h:516
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:1121
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:299
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
u32 * node_index_by_feature_index
Definition: config.h:101
vnet_main_t * vnet_main
Definition: cop.h:70
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u32 * config_index_by_sw_if_index
Definition: cop.h:58
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:315
#define clib_error_return(e, args...)
Definition: error.h:99
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static clib_error_t * ip6_whitelist_init(vlib_main_t *vm)
static clib_error_t * cop_init(vlib_main_t *vm)
Definition: cop.c:132
#define hash_get(h, key)
Definition: hash.h:248
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:109
vlib_node_registration_t cop_input_node
(constructor) VLIB_REGISTER_NODE (cop_input_node)
Definition: node1.c:261
struct _unformat_input_t unformat_input_t
int cop_whitelist_enable_disable(cop_whitelist_enable_disable_args_t *a)
Definition: cop.c:229
vnet_device_class_t vnet_local_interface_device_class
uword * fib_index_by_table_id
Definition: ip6.h:173
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:143
#define clib_warning(format, args...)
Definition: error.h:59
int cop_interface_enable_disable(u32 sw_if_index, int enable_disable)
Definition: cop.c:151
#define ARRAY_LEN(x)
Definition: clib.h:59
cop_main_t cop_main
Definition: cop.c:17
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
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:176
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2926
IPv4 main type.
Definition: ip4.h:83
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:238
u64 uword
Definition: types.h:112
unsigned char u8
Definition: types.h:56
static clib_error_t * ip4_whitelist_init(vlib_main_t *vm)
vnet_sw_interface_type_t type
Definition: interface.h:555
vlib_main_t * vlib_main
Definition: cop.h:69
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
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:485
u32 fib_index
Definition: cop.h:62
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
vnet_config_main_t config_main
Definition: cop.h:57
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169