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