FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
interface.c
Go to the documentation of this file.
1 /*
2  * interface.c: mpls interfaces
3  *
4  * Copyright (c) 2012 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/mpls/mpls.h>
21 #include <vnet/fib/ip4_fib.h>
22 #include <vnet/adj/adj_midchain.h>
23 #include <vnet/dpo/classify_dpo.h>
24 
25 /* manually added to the interface output node */
26 #define MPLS_ETH_OUTPUT_NEXT_OUTPUT 1
27 
28 static uword
30  vlib_node_runtime_t * node,
31  vlib_frame_t * frame)
32 {
33  mpls_main_t * gm = &mpls_main;
34  vnet_main_t * vnm = gm->vnet_main;
35  u32 next_index;
36  u32 * from, * to_next, n_left_from, n_left_to_next;
37 
38  /* Vector of buffer / pkt indices we're supposed to process */
39  from = vlib_frame_vector_args (frame);
40 
41  /* Number of buffers / pkts */
42  n_left_from = frame->n_vectors;
43 
44  /* Speculatively send the first buffer to the last disposition we used */
45  next_index = node->cached_next_index;
46 
47  while (n_left_from > 0)
48  {
49  /* set up to enqueue to our disposition with index = next_index */
50  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
51 
52  /*
53  * As long as we have enough pkts left to process two pkts
54  * and prefetch two pkts...
55  */
56  while (n_left_from >= 4 && n_left_to_next >= 2)
57  {
58  vlib_buffer_t * b0, * b1;
59  u32 bi0, next0, bi1, next1;
60  mpls_eth_tunnel_t * t0, * t1;
61  u32 sw_if_index0, sw_if_index1;
62  vnet_hw_interface_t * hi0, * hi1;
63  u8 * dst0, * dst1;
64 
65  /* Prefetch the next iteration */
66  {
67  vlib_buffer_t * p2, * p3;
68 
69  p2 = vlib_get_buffer (vm, from[2]);
70  p3 = vlib_get_buffer (vm, from[3]);
71 
72  vlib_prefetch_buffer_header (p2, LOAD);
73  vlib_prefetch_buffer_header (p3, LOAD);
74 
75  /*
76  * Prefetch packet data. We expect to overwrite
77  * the inbound L2 header with an ip header and a
78  * gre header. Might want to prefetch the last line
79  * of rewrite space as well; need profile data
80  */
83  }
84 
85  /* Pick up the next two buffer indices */
86  bi0 = from[0];
87  bi1 = from[1];
88 
89  /* Speculatively enqueue them where we sent the last buffer */
90  to_next[0] = bi0;
91  to_next[1] = bi1;
92  from += 2;
93  to_next += 2;
94  n_left_to_next -= 2;
95  n_left_from -= 2;
96 
97  b0 = vlib_get_buffer (vm, bi0);
98  b1 = vlib_get_buffer (vm, bi1);
99 
100  sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
101  sw_if_index1 = vnet_buffer(b1)->sw_if_index [VLIB_TX];
102 
103  /* get h/w intfcs */
104  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
105  hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1);
106 
107  /* hw_instance = tunnel pool index */
108  t0 = pool_elt_at_index (gm->eth_tunnels, hi0->hw_instance);
109  t1 = pool_elt_at_index (gm->eth_tunnels, hi1->hw_instance);
110 
111  /* Apply rewrite - $$$$$ fixme don't use memcpy */
114 
115  dst0 = vlib_buffer_get_current (b0);
116  dst1 = vlib_buffer_get_current (b1);
117 
118  clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
119  clib_memcpy (dst1, t1->rewrite_data, vec_len(t1->rewrite_data));
120 
121  /* Fix TX fib indices */
122  vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->tx_sw_if_index;
123  vnet_buffer(b1)->sw_if_index [VLIB_TX] = t1->tx_sw_if_index;
124 
125  /* mpls-post-rewrite takes it from here... */
128 
130  {
131  mpls_eth_tx_trace_t *tr = vlib_add_trace (vm, node,
132  b0, sizeof (*tr));
133  tr->lookup_miss = 0;
134  tr->tunnel_id = t0 - gm->eth_tunnels;
135  tr->tx_sw_if_index = t0->tx_sw_if_index;
136  tr->mpls_encap_index = t0->encap_index;
137  tr->length = b0->current_length;
138  hi0 = vnet_get_sup_hw_interface (vnm, t0->tx_sw_if_index);
139  clib_memcpy (tr->dst, hi0->hw_address, sizeof (tr->dst));
140  }
142  {
143  mpls_eth_tx_trace_t *tr = vlib_add_trace (vm, node,
144  b1, sizeof (*tr));
145  tr->lookup_miss = 0;
146  tr->tunnel_id = t1 - gm->eth_tunnels;
147  tr->tx_sw_if_index = t1->tx_sw_if_index;
148  tr->mpls_encap_index = t1->encap_index;
149  tr->length = b1->current_length;
150  hi1 = vnet_get_sup_hw_interface (vnm, t1->tx_sw_if_index);
151  clib_memcpy (tr->dst, hi1->hw_address, sizeof (tr->dst));
152  }
153 
154  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
155  to_next, n_left_to_next,
156  bi0, bi1, next0, next1);
157  }
158  while (n_left_from > 0 && n_left_to_next > 0)
159  {
160  vlib_buffer_t * b0;
161  u32 bi0, next0;
162  mpls_eth_tunnel_t * t0;
163  u32 sw_if_index0;
164  vnet_hw_interface_t * hi0;
165  u8 * dst0;
166 
167  bi0 = from[0];
168  to_next[0] = bi0;
169  from += 1;
170  to_next += 1;
171  n_left_from -= 1;
172  n_left_to_next -= 1;
173 
174  b0 = vlib_get_buffer (vm, bi0);
175 
176  sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
177 
178  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
179 
180  t0 = pool_elt_at_index (gm->eth_tunnels, hi0->hw_instance);
181 
182  /* Apply rewrite - $$$$$ fixme don't use memcpy */
184 
185  dst0 = vlib_buffer_get_current (b0);
186 
187  clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
188 
189  /* Fix the TX interface */
190  vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->tx_sw_if_index;
191 
192  /* Send the packet */
194 
196  {
197  mpls_eth_tx_trace_t *tr = vlib_add_trace (vm, node,
198  b0, sizeof (*tr));
199  tr->lookup_miss = 0;
200  tr->tunnel_id = t0 - gm->eth_tunnels;
201  tr->tx_sw_if_index = t0->tx_sw_if_index;
202  tr->mpls_encap_index = t0->encap_index;
203  tr->length = b0->current_length;
204  hi0 = vnet_get_sup_hw_interface (vnm, t0->tx_sw_if_index);
205  clib_memcpy (tr->dst, hi0->hw_address, sizeof (tr->dst));
206  }
207 
208  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
209  to_next, n_left_to_next,
210  bi0, next0);
211  }
212 
213  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
214  }
215 
217  MPLS_ERROR_PKTS_ENCAP, frame->n_vectors);
218 
219  return frame->n_vectors;
220 }
221 
222 static u8 * format_mpls_eth_tunnel_name (u8 * s, va_list * args)
223 {
224  u32 dev_instance = va_arg (*args, u32);
225  return format (s, "mpls-eth%d", dev_instance);
226 }
227 
228 static u8 * format_mpls_eth_device (u8 * s, va_list * args)
229 {
230  u32 dev_instance = va_arg (*args, u32);
231  CLIB_UNUSED (int verbose) = va_arg (*args, int);
232 
233  s = format (s, "MPLS-ETH tunnel: id %d\n", dev_instance);
234  return s;
235 }
236 
237 VNET_DEVICE_CLASS (mpls_eth_device_class) = {
238  .name = "MPLS-ETH tunnel device",
239  .format_device_name = format_mpls_eth_tunnel_name,
240  .format_device = format_mpls_eth_device,
241  .format_tx_trace = format_mpls_eth_tx_trace,
242  .tx_function = mpls_eth_interface_tx,
243  .no_flatten_output_chains = 1,
244 #ifdef SOON
245  .clear counter = 0;
246  .admin_up_down_function = 0;
247 #endif
248 };
249 
250 VLIB_DEVICE_TX_FUNCTION_MULTIARCH (mpls_eth_device_class,
252 
253 VNET_HW_INTERFACE_CLASS (mpls_eth_hw_interface_class) = {
254  .name = "MPLS-ETH",
255  .format_header = format_mpls_eth_header_with_length,
256 #if 0
257  .unformat_header = unformat_mpls_eth_header,
258 #endif
259  .build_rewrite = default_build_rewrite,
261 };
262 
263 u8
265 {
266  mpls_main_t * mm = &mpls_main;
267 
268  if (vec_len(mm->mpls_enabled_by_sw_if_index) < sw_if_index)
269  return (0);
270 
271  return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
272 }
273 
274 void
276  u32 sw_if_index,
277  u8 is_enable)
278 {
279  vlib_main_t * vm = vlib_get_main();
281  vnet_config_main_t * vcm = &cm->config_main;
282  u32 lookup_feature_index;
283  fib_node_index_t lfib_index;
284  u32 ci;
285 
287 
288  /*
289  * enable/disable only on the 1<->0 transition
290  */
291  if (is_enable)
292  {
293  if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
294  return;
295 
299  mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
300  }
301  else
302  {
303  ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
304  if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
305  return;
306 
309  }
310 
312  ci = cm->config_index_by_sw_if_index[sw_if_index];
313 
314  lookup_feature_index = mm->mpls_rx_feature_lookup;
315 
316  if (is_enable)
317  ci = vnet_config_add_feature (vm, vcm,
318  ci,
319  lookup_feature_index,
320  /* config data */ 0,
321  /* # bytes of config data */ 0);
322  else
323  ci = vnet_config_del_feature (vm, vcm, ci,
324  lookup_feature_index,
325  /* config data */ 0,
326  /* # bytes of config data */ 0);
327 
328  cm->config_index_by_sw_if_index[sw_if_index] = ci;
329 }
330 
331 u8 * format_mpls_encap_index (u8 * s, va_list * args)
332 {
333  mpls_main_t * mm = va_arg (*args, mpls_main_t *);
334  u32 entry_index = va_arg (*args, u32);
335  mpls_encap_t * e;
336  int i;
337 
338  e = pool_elt_at_index (mm->encaps, entry_index);
339 
340  for (i = 0; i < vec_len (e->labels); i++)
341  s = format
342  (s, "%d ", vnet_mpls_uc_get_label(clib_net_to_host_u32
343  (e->labels[i].label_exp_s_ttl)));
344 
345  return s;
346 }
347 
348 u8 * format_mpls_ethernet_tunnel (u8 * s, va_list * args)
349 {
350  mpls_eth_tunnel_t * t = va_arg (*args, mpls_eth_tunnel_t *);
351  mpls_main_t * mm = &mpls_main;
352 
353  s = format (s, "[%d]: dst %U, adj %U/%d, labels %U\n",
354  t - mm->eth_tunnels,
357  t->mask_width,
359 
360 
361  s = format (s, " tx on %U, rx fib index %d",
363  t->inner_fib_index);
364 
365  return s;
366 }
367 
368 static clib_error_t *
370  unformat_input_t * input,
371  vlib_cli_command_t * cmd)
372 {
373  mpls_main_t * mm = &mpls_main;
374  mpls_eth_tunnel_t * et;
375 
376  if (pool_elts (mm->eth_tunnels))
377  {
378  vlib_cli_output (vm, "MPLS-Ethernet tunnels");
379  pool_foreach (et, mm->eth_tunnels,
380  ({
381  vlib_cli_output (vm, "%U", format_mpls_ethernet_tunnel, et);
382  }));
383  }
384  else
385  vlib_cli_output (vm, "No MPLS-Ethernet tunnels");
386 
387  return 0;
388 }
389 
390 VLIB_CLI_COMMAND (show_mpls_tunnel_command, static) = {
391  .path = "show mpls tunnel",
392  .short_help = "show mpls tunnel",
393  .function = show_mpls_tunnel_command_fn,
394 };
395 
396 
397 /* force inclusion from application's main.c */
399 {
400  clib_error_t * error;
401 
403  return error;
404 
405  return 0;
406 }
408 
409 
411 {
412  u8 * rewrite_data = 0;
413  mpls_encap_t * e;
415  int i;
416 
417  /* look up the encap label stack using the RX FIB and adjacency address*/
419  t->intfc_address.as_u32);
420 
421  if (e == 0)
422  {
423  clib_warning ("no label for inner fib index %d, dst %U",
425  &t->intfc_address);
426  return 0;
427  }
428 
429  vec_validate (rewrite_data,
430  sizeof (mpls_unicast_header_t) * vec_len(e->labels) -1);
431 
432  /* Copy the encap label stack */
433  lp0 = (mpls_unicast_header_t *) rewrite_data;
434 
435  for (i = 0; i < vec_len(e->labels); i++)
436  lp0[i] = e->labels[i];
437 
438  return (rewrite_data);
439 }
440 
442  ip4_address_t *intfc,
443  u32 mask_width,
444  u32 inner_fib_id,
445  u32 tx_sw_if_index,
446  u32 * tunnel_sw_if_index,
447  u8 l2_only,
448  u8 is_add)
449 {
450  ip4_main_t * im = &ip4_main;
451  ip_lookup_main_t * lm = &im->lookup_main;
452  mpls_main_t * mm = &mpls_main;
453  vnet_main_t * vnm = vnet_get_main();
454  mpls_eth_tunnel_t *tp;
455  u32 inner_fib_index = 0;
456  ip_adjacency_t adj;
457  u32 adj_index;
458  u8 * rewrite_data;
459  int found_tunnel = 0;
460  mpls_encap_t * e = 0;
461  u32 hw_if_index = ~0;
463  u32 slot;
464  u32 dummy;
465 
466  if (tunnel_sw_if_index == 0)
467  tunnel_sw_if_index = &dummy;
468 
469  *tunnel_sw_if_index = ~0;
470 
471  if (inner_fib_id != (u32)~0)
472  {
473  uword * p;
474 
475  p = hash_get (im->fib_index_by_table_id, inner_fib_id);
476  if (! p)
477  return VNET_API_ERROR_NO_SUCH_FIB;
478  inner_fib_index = p[0];
479  }
480 
481  /* suppress duplicate mpls interface generation. */
482  pool_foreach (tp, mm->eth_tunnels,
483  ({
484  /*
485  * If we have a tunnel which matches (src, dst, intfc/mask)
486  * AND the expected route is in the FIB, it's a dup
487  */
488  if (!memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
489  && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
490  && tp->inner_fib_index == inner_fib_index
491  && FIB_NODE_INDEX_INVALID != tp->fei)
492  {
493  found_tunnel = 1;
494 
495  if (is_add)
496  {
497  if (l2_only)
498  return 1;
499  else
500  {
501  e = mpls_encap_by_fib_and_dest (mm, inner_fib_index,
502  intfc->as_u32);
503  if (e == 0)
504  return VNET_API_ERROR_NO_SUCH_LABEL;
505 
506  goto reinstall_it;
507  }
508  }
509  else
510  {
511  /* Delete */
512  goto add_del_route;
513  }
514 
515  }
516  }));
517 
518  /* Delete, and we can't find the tunnel */
519  if (is_add == 0 && found_tunnel == 0)
520  return VNET_API_ERROR_NO_SUCH_ENTRY;
521 
522  e = mpls_encap_by_fib_and_dest (mm, inner_fib_index, intfc->as_u32);
523  if (e == 0)
524  return VNET_API_ERROR_NO_SUCH_LABEL;
525 
526  pool_get(mm->eth_tunnels, tp);
527  memset (tp, 0, sizeof (*tp));
528 
529  if (vec_len (mm->free_eth_sw_if_indices) > 0)
530  {
531  hw_if_index =
532  mm->free_eth_sw_if_indices[vec_len(mm->free_eth_sw_if_indices)-1];
533  _vec_len (mm->free_eth_sw_if_indices) -= 1;
534  hi = vnet_get_hw_interface (vnm, hw_if_index);
535  hi->dev_instance = tp - mm->eth_tunnels;
536  hi->hw_instance = tp - mm->eth_tunnels;
537  }
538  else
539  {
540  hw_if_index = vnet_register_interface
541  (vnm, mpls_eth_device_class.index, tp - mm->eth_tunnels,
542  mpls_eth_hw_interface_class.index,
543  tp - mm->eth_tunnels);
544  hi = vnet_get_hw_interface (vnm, hw_if_index);
545 
546  /* ... to make the IP and L2 x-connect cases identical */
548  (vnm->vlib_main, hi->tx_node_index,
549  "interface-output", MPLS_ETH_OUTPUT_NEXT_OUTPUT);
550 
552  }
553 
554  *tunnel_sw_if_index = hi->sw_if_index;
555  vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
557 
558  tp->hw_if_index = hw_if_index;
559 
560  reinstall_it:
561  clib_memcpy(tp->tunnel_dst, dst, sizeof (tp->tunnel_dst));
562  tp->intfc_address.as_u32 = intfc->as_u32;
563  tp->mask_width = mask_width;
564  tp->inner_fib_index = inner_fib_index;
565  tp->encap_index = e - mm->encaps;
566  tp->tx_sw_if_index = tx_sw_if_index;
567  tp->l2_only = l2_only;
568 
569  /* Create the adjacency and add to v4 fib */
570  memset(&adj, 0, sizeof (adj));
571  adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
572 
573  rewrite_data = mpls_ethernet_rewrite (mm, tp);
574  if (rewrite_data == 0)
575  {
576  if (*tunnel_sw_if_index != ~0)
577  {
578  hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
579  vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
580  0 /* admin down */);
581  vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
582  }
583 
584  pool_put (mm->eth_tunnels, tp);
585  return VNET_API_ERROR_NO_SUCH_LABEL;
586  }
587 
589  (vnm,
591  tx_sw_if_index,
592  ip4_rewrite_node.index,
593  tp->tunnel_dst,
594  &adj.rewrite_header,
595  sizeof (adj.rewrite_data));
596 
597  /*
598  * Prepend the (0,1,2) VLAN tag ethernet header
599  * we just built to the mpls header stack
600  */
601  vec_insert (rewrite_data, adj.rewrite_header.data_bytes, 0);
602  clib_memcpy(rewrite_data,
603  vnet_rewrite_get_data_internal(&adj.rewrite_header,
604  sizeof (adj.rewrite_data)),
605  adj.rewrite_header.data_bytes);
606 
607  vnet_rewrite_set_data_internal (&adj.rewrite_header,
608  sizeof(adj.rewrite_data),
609  rewrite_data,
610  vec_len(rewrite_data));
611 
612  vec_free (tp->rewrite_data);
613 
614  tp->rewrite_data = rewrite_data;
615 
616  if (!l2_only)
617  ip_add_adjacency (lm, &adj, 1 /* one adj */,
618  &adj_index);
619 
620  add_del_route:
621 
622  if (!l2_only)
623  {
624  const fib_prefix_t pfx = {
625  .fp_addr = {
626  .ip4 = tp->intfc_address,
627  },
628  .fp_len = tp->mask_width,
629  .fp_proto = FIB_PROTOCOL_IP4,
630  };
631  if (is_add)
632  tp->fei = fib_table_entry_special_add(tp->inner_fib_index,
633  &pfx,
636  adj_index);
637  else
638  {
639  fib_table_entry_delete(tp->inner_fib_index, &pfx, FIB_SOURCE_API);
640  tp->fei = FIB_NODE_INDEX_INVALID;
641  }
642  }
643  if (is_add == 0 && found_tunnel)
644  {
645  hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
646  vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
647  0 /* admin down */);
648  vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
649  vec_free (tp->rewrite_data);
650  pool_put (mm->eth_tunnels, tp);
651  }
652 
653  return 0;
654 }
655 
656 static clib_error_t *
658  unformat_input_t * input,
659  vlib_cli_command_t * cmd)
660 {
661  unformat_input_t _line_input, * line_input = &_line_input;
662  vnet_main_t * vnm = vnet_get_main();
663  ip4_address_t intfc;
664  int adj_set = 0;
665  u8 dst[6];
666  int dst_set = 0, intfc_set = 0;
667  u32 mask_width;
668  u32 inner_fib_id = (u32)~0;
669  int rv;
670  u8 is_del = 0;
671  u8 l2_only = 0;
672  u32 tx_sw_if_index;
673  u32 sw_if_index = ~0;
674 
675  /* Get a line of input. */
676  if (! unformat_user (input, unformat_line_input, line_input))
677  return 0;
678 
679  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
680  {
681  if (unformat (line_input, "dst %U",
683  dst_set = 1;
684  else if (unformat (line_input, "adj %U/%d",
685  unformat_ip4_address, &intfc, &mask_width))
686  adj_set = 1;
687  else if (unformat (line_input, "tx-intfc %U",
688  unformat_vnet_sw_interface, vnm, &tx_sw_if_index))
689  intfc_set = 1;
690  else if (unformat (line_input, "fib-id %d", &inner_fib_id))
691  ;
692  else if (unformat (line_input, "l2-only"))
693  l2_only = 1;
694  else if (unformat (line_input, "del"))
695  is_del = 1;
696  else
697  return clib_error_return (0, "unknown input '%U'",
698  format_unformat_error, line_input);
699  }
700 
701  if (!intfc_set)
702  return clib_error_return (0, "missing tx-intfc");
703 
704  if (!dst_set)
705  return clib_error_return (0, "missing: dst <ethernet-address>");
706 
707  if (!adj_set)
708  return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
709 
710 
711  rv = vnet_mpls_ethernet_add_del_tunnel (dst, &intfc, mask_width,
712  inner_fib_id, tx_sw_if_index,
713  &sw_if_index,
714  l2_only, !is_del);
715 
716  switch (rv)
717  {
718  case 0:
719  if (!is_del)
720  vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index);
721  break;
722  case VNET_API_ERROR_NO_SUCH_FIB:
723  return clib_error_return (0, "rx fib ID %d doesn't exist\n",
724  inner_fib_id);
725 
726  case VNET_API_ERROR_NO_SUCH_ENTRY:
727  return clib_error_return (0, "tunnel not found\n");
728 
729  case VNET_API_ERROR_NO_SUCH_LABEL:
730  /*
731  * This happens when there's no MPLS label for the dst address
732  * no need for two error messages.
733  */
734  return clib_error_return (0, "no label for %U in fib %d",
735  format_ip4_address, &intfc, inner_fib_id);
736  break;
737 
738  default:
739  return clib_error_return (0, "vnet_mpls_ethernet_add_del_tunnel returned %d", rv);
740  break;
741  }
742  return 0;
743 }
744 
745 
746 VLIB_CLI_COMMAND (create_mpls_ethernet_tunnel_command, static) = {
747  .path = "create mpls ethernet tunnel",
748  .short_help =
749  "create mpls ethernet tunnel [del] dst <mac-addr> intfc <addr>/<mw>",
751 };
752 
753 
755  mpls_encap_t * e,
756  u32 policy_tunnel_index)
757 {
758  mpls_eth_tunnel_t * t;
759  ip_adjacency_t adj;
760  u8 * rewrite_data = 0;
761  u8 * label_start;
763  int i;
764 
765  if (pool_is_free_index (mm->eth_tunnels, policy_tunnel_index))
766  return VNET_API_ERROR_NO_SUCH_ENTRY;
767 
768  t = pool_elt_at_index (mm->eth_tunnels, policy_tunnel_index);
769 
770  memset (&adj, 0, sizeof (adj));
771 
772  /* Build L2 encap */
774  (mm->vnet_main,
776  t->tx_sw_if_index,
778  t->tunnel_dst,
779  &adj.rewrite_header,
780  sizeof (adj.rewrite_data));
781 
782  vec_validate (rewrite_data, adj.rewrite_header.data_bytes -1);
783 
784  clib_memcpy(rewrite_data,
785  vnet_rewrite_get_data_internal(&adj.rewrite_header,
786  sizeof (adj.rewrite_data)),
787  adj.rewrite_header.data_bytes);
788 
789  /* Append the label stack */
790 
791  vec_add2 (rewrite_data, label_start, vec_len(e->labels) * sizeof (u32));
792 
793  lp = (mpls_unicast_header_t *) label_start;
794 
795  for (i = 0; i < vec_len(e->labels); i++)
796  lp[i] = e->labels[i];
797 
798  /* Remember the rewrite data */
799  e->rewrite = rewrite_data;
800  e->output_next_index = adj.rewrite_header.next_index;
801 
802  return 0;
803 }
804 
806  ip4_address_t *intfc,
807  u32 mask_width,
808  u32 inner_fib_id,
809  u32 tx_sw_if_index,
810  u32 * tunnel_sw_if_index,
811  u32 classify_table_index,
812  u32 * new_tunnel_index,
813  u8 l2_only,
814  u8 is_add)
815 {
816  ip4_main_t * im = &ip4_main;
817  mpls_main_t * mm = &mpls_main;
818  vnet_main_t * vnm = vnet_get_main();
819  mpls_eth_tunnel_t *tp;
820  u32 inner_fib_index = 0;
821  int found_tunnel = 0;
822  mpls_encap_t * e = 0;
823  u32 hw_if_index = ~0;
825  u32 slot;
826  u32 dummy;
827 
828  if (tunnel_sw_if_index == 0)
829  tunnel_sw_if_index = &dummy;
830 
831  *tunnel_sw_if_index = ~0;
832 
833  if (inner_fib_id != (u32)~0)
834  {
835  uword * p;
836 
837  p = hash_get (im->fib_index_by_table_id, inner_fib_id);
838  if (! p)
839  return VNET_API_ERROR_NO_SUCH_FIB;
840  inner_fib_index = p[0];
841  }
842 
843  /* suppress duplicate mpls interface generation. */
844  pool_foreach (tp, mm->eth_tunnels,
845  ({
846  /*
847  * If we have a tunnel which matches (src, dst, intfc/mask)
848  * AND the expected route is in the FIB, it's a dup
849  */
850  if (!memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
851  && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
852  && tp->inner_fib_index == inner_fib_index
853  && FIB_NODE_INDEX_INVALID != tp->fei)
854  {
855  found_tunnel = 1;
856 
857  if (is_add)
858  {
859  if (l2_only)
860  return 1;
861  else
862  {
863  goto reinstall_it;
864  }
865  }
866  else
867  {
868  /* Delete */
869  goto add_del_route;
870  }
871 
872  }
873  }));
874 
875  /* Delete, and we can't find the tunnel */
876  if (is_add == 0 && found_tunnel == 0)
877  return VNET_API_ERROR_NO_SUCH_ENTRY;
878 
879  pool_get(mm->eth_tunnels, tp);
880  memset (tp, 0, sizeof (*tp));
881 
882  if (vec_len (mm->free_eth_sw_if_indices) > 0)
883  {
884  hw_if_index =
885  mm->free_eth_sw_if_indices[vec_len(mm->free_eth_sw_if_indices)-1];
886  _vec_len (mm->free_eth_sw_if_indices) -= 1;
887  hi = vnet_get_hw_interface (vnm, hw_if_index);
888  hi->dev_instance = tp - mm->eth_tunnels;
889  hi->hw_instance = tp - mm->eth_tunnels;
890  }
891  else
892  {
893  hw_if_index = vnet_register_interface
894  (vnm, mpls_eth_device_class.index, tp - mm->eth_tunnels,
895  mpls_eth_hw_interface_class.index,
896  tp - mm->eth_tunnels);
897  hi = vnet_get_hw_interface (vnm, hw_if_index);
898 
899  /* ... to make the IP and L2 x-connect cases identical */
901  (vnm->vlib_main, hi->tx_node_index,
902  "interface-output", MPLS_ETH_OUTPUT_NEXT_OUTPUT);
903 
905  }
906 
907  *tunnel_sw_if_index = hi->sw_if_index;
908  vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
910 
911  tp->hw_if_index = hw_if_index;
912 
913  reinstall_it:
914  clib_memcpy(tp->tunnel_dst, dst, sizeof (tp->tunnel_dst));
915  tp->intfc_address.as_u32 = intfc->as_u32;
916  tp->mask_width = mask_width;
917  tp->inner_fib_index = inner_fib_index;
918  tp->encap_index = e - mm->encaps;
919  tp->tx_sw_if_index = tx_sw_if_index;
920  tp->l2_only = l2_only;
921  tp->fei = FIB_NODE_INDEX_INVALID;
922 
923  if (new_tunnel_index)
924  *new_tunnel_index = tp - mm->eth_tunnels;
925 
926  add_del_route:
927 
928  if (!l2_only)
929  {
930  const fib_prefix_t pfx = {
931  .fp_addr = {
932  .ip4 = tp->intfc_address,
933  },
934  .fp_len = tp->mask_width,
935  .fp_proto = FIB_PROTOCOL_IP4,
936  };
937  dpo_id_t dpo = DPO_INVALID;
938 
939  if (is_add)
940  {
941  dpo_set(&dpo,
942  DPO_CLASSIFY,
945  classify_table_index));
946 
947  tp->fei = fib_table_entry_special_dpo_add(tp->inner_fib_index,
948  &pfx,
951  &dpo);
952  dpo_reset(&dpo);
953  }
954  else
955  {
956  fib_table_entry_delete(tp->inner_fib_index, &pfx, FIB_SOURCE_API);
957  tp->fei = FIB_NODE_INDEX_INVALID;
958  }
959  }
960  if (is_add == 0 && found_tunnel)
961  {
962  hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
963  vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
964  0 /* admin down */);
965  vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
966  pool_put (mm->eth_tunnels, tp);
967  }
968 
969  return 0;
970 }
971 
972 static clib_error_t *
974  unformat_input_t * input,
975  vlib_cli_command_t * cmd)
976 {
977  unformat_input_t _line_input, * line_input = &_line_input;
978  vnet_main_t * vnm = vnet_get_main();
979  ip4_address_t intfc;
980  int adj_set = 0;
981  u8 dst[6];
982  int dst_set = 0, intfc_set = 0;
983  u32 mask_width;
984  u32 inner_fib_id = (u32)~0;
985  u32 classify_table_index = (u32)~0;
986  u32 new_tunnel_index;
987  int rv;
988  u8 is_del = 0;
989  u8 l2_only = 0;
990  u32 tx_sw_if_index;
991 
992  /* Get a line of input. */
993  if (! unformat_user (input, unformat_line_input, line_input))
994  return 0;
995 
996  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
997  {
998  if (unformat (line_input, "dst %U",
1000  dst_set = 1;
1001  else if (unformat (line_input, "adj %U/%d",
1002  unformat_ip4_address, &intfc, &mask_width))
1003  adj_set = 1;
1004  else if (unformat (line_input, "tx-intfc %U",
1005  unformat_vnet_sw_interface, vnm, &tx_sw_if_index))
1006  intfc_set = 1;
1007  else if (unformat (line_input, "classify-table-index %d",
1008  &classify_table_index))
1009  ;
1010  else if (unformat (line_input, "fib-id %d", &inner_fib_id))
1011  ;
1012  else if (unformat (line_input, "l2-only"))
1013  l2_only = 1;
1014  else if (unformat (line_input, "del"))
1015  is_del = 1;
1016  else
1017  return clib_error_return (0, "unknown input '%U'",
1018  format_unformat_error, line_input);
1019  }
1020 
1021  if (classify_table_index == ~0)
1022  return clib_error_return (0, "missing classify_table_index");
1023 
1024  if (!intfc_set)
1025  return clib_error_return (0, "missing tx-intfc");
1026 
1027  if (!dst_set)
1028  return clib_error_return (0, "missing: dst <ethernet-address>");
1029 
1030  if (!adj_set)
1031  return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
1032 
1033 
1034  rv = vnet_mpls_ethernet_add_del_policy_tunnel (dst, &intfc, mask_width,
1035  inner_fib_id, tx_sw_if_index,
1036  0 /* tunnel sw_if_index */,
1037  classify_table_index,
1038  &new_tunnel_index,
1039  l2_only, !is_del);
1040  switch (rv)
1041  {
1042  case 0:
1043  if (!is_del)
1044  vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), new_tunnel_index);
1045  break;
1046  case VNET_API_ERROR_NO_SUCH_FIB:
1047  return clib_error_return (0, "rx fib ID %d doesn't exist\n",
1048  inner_fib_id);
1049 
1050  case VNET_API_ERROR_NO_SUCH_ENTRY:
1051  return clib_error_return (0, "tunnel not found\n");
1052 
1053  case VNET_API_ERROR_NO_SUCH_LABEL:
1054  /*
1055  * This happens when there's no MPLS label for the dst address
1056  * no need for two error messages.
1057  */
1058  return clib_error_return (0, "no label for %U in fib %d",
1059  format_ip4_address, &intfc, inner_fib_id);
1060  break;
1061 
1062  default:
1063  return clib_error_return (0, "vnet_mpls_ethernet_add_del_policy_tunnel returned %d", rv);
1064  break;
1065  }
1066 
1067  return 0;
1068 }
1069 
1070 VLIB_CLI_COMMAND (create_mpls_ethernet_policy_tunnel_command, static) = {
1071  .path = "create mpls ethernet policy tunnel",
1072  .short_help =
1073  "create mpls ethernet policy tunnel [del] dst <mac-addr> intfc <addr>/<mw>\n"
1074  " classify-table-index <nn>",
1076 };
1077 
1078 static clib_error_t *
1080  unformat_input_t * input,
1081  vlib_cli_command_t * cmd)
1082 {
1083  vnet_main_t * vnm = vnet_get_main();
1084  clib_error_t * error = 0;
1085  u32 sw_if_index, enable;
1086 
1087  sw_if_index = ~0;
1088 
1089  if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1090  {
1091  error = clib_error_return (0, "unknown interface `%U'",
1092  format_unformat_error, input);
1093  goto done;
1094  }
1095 
1096  if (unformat (input, "enable"))
1097  enable = 1;
1098  else if (unformat (input, "disable"))
1099  enable = 0;
1100  else
1101  {
1102  error = clib_error_return (0, "expected 'enable' or 'disable'",
1103  format_unformat_error, input);
1104  goto done;
1105  }
1106 
1107  mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable);
1108 
1109  done:
1110  return error;
1111 }
1112 
1113 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = {
1114  .path = "set interface mpls",
1115  .function = mpls_interface_enable_disable,
1116  .short_help = "Enable/Disable an interface for MPLS forwarding",
1117 };
vnet_config_main_t config_main
Definition: feature.h:55
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
vmrglw vmrglh hi
static uword mpls_eth_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: interface.c:29
void mpls_sw_interface_enable_disable(mpls_main_t *mm, u32 sw_if_index, u8 is_enable)
Definition: interface.c:275
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static clib_error_t * mpls_interface_enable_disable(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1079
u8 tunnel_dst[6]
Definition: mpls.h:38
u32 mask_width
Definition: mpls.h:42
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
format_function_t format_mpls_eth_header_with_length
Definition: mpls.h:160
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
IP unicast adjacency.
Definition: lookup.h:174
u32 * fib_index_by_sw_if_index
Definition: mpls.h:89
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:300
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
static clib_error_t * mpls_policy_encap_init(vlib_main_t *vm)
Definition: policy_encap.c:160
void vnet_rewrite_for_sw_interface(vnet_main_t *vnm, vnet_link_t link_type, u32 sw_if_index, u32 node_index, void *dst_address, vnet_rewrite_header_t *rw, u32 max_rewrite_bytes)
Deprecated.
Definition: rewrite.c:207
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:521
u8 mpls_sw_interface_is_enabled(u32 sw_if_index)
Definition: interface.c:264
ip_lookup_main_t lookup_main
Definition: ip4.h:96
unformat_function_t unformat_vnet_sw_interface
ip_adjacency_t * ip_add_adjacency(ip_lookup_main_t *lm, ip_adjacency_t *copy_adj, u32 n_adj, u32 *adj_index_return)
Definition: adj.c:426
int vnet_mpls_ethernet_add_del_policy_tunnel(u8 *dst, ip4_address_t *intfc, u32 mask_width, u32 inner_fib_id, u32 tx_sw_if_index, u32 *tunnel_sw_if_index, u32 classify_table_index, u32 *new_tunnel_index, u8 l2_only, u8 is_add)
Definition: interface.c:805
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
format_function_t format_ip4_address
Definition: format.h:78
format_function_t format_vnet_sw_if_index_name
vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]
Definition: mpls.h:98
static clib_error_t * create_mpls_ethernet_policy_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:973
static clib_error_t * show_mpls_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:369
u8 * mpls_enabled_by_sw_if_index
Definition: mpls.h:124
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u8 * format_mpls_eth_tx_trace(u8 *s, va_list *args)
Definition: mpls.c:124
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:190
Aggregrate type for a prefix.
Definition: fib_types.h:149
#define clib_warning(format, args...)
Definition: error.h:59
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
int vnet_mpls_policy_tunnel_add_rewrite(mpls_main_t *mm, mpls_encap_t *e, u32 policy_tunnel_index)
Definition: interface.c:754
#define vlib_call_init_function(vm, x)
Definition: init.h:161
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:660
static clib_error_t * create_mpls_ethernet_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:657
Definition: fib_entry.h:215
unformat_function_t unformat_ip4_address
Definition: format.h:75
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
void fib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: fib_table.c:1033
ip4_address_t intfc_address
Definition: mpls.h:39
#define hash_get(h, key)
Definition: hash.h:248
Definition: fib_entry.h:219
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header...
Definition: vec.h:646
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, adj_index_t adj_index)
Add a &#39;special&#39; entry to the FIB that links to the adj passed A special entry is an entry that the FI...
Definition: fib_table.c:369
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:111
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
vlib_node_registration_t mpls_policy_encap_node
(constructor) VLIB_REGISTER_NODE (mpls_policy_encap_node)
Definition: policy_encap.c:136
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:172
#define MPLS_ETH_OUTPUT_NEXT_OUTPUT
Definition: interface.c:26
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
vlib_node_registration_t mpls_input_node
(constructor) VLIB_REGISTER_NODE (mpls_input_node)
Definition: node.c:168
int vnet_mpls_ethernet_add_del_tunnel(u8 *dst, ip4_address_t *intfc, u32 mask_width, u32 inner_fib_id, u32 tx_sw_if_index, u32 *tunnel_sw_if_index, u8 l2_only, u8 is_add)
Definition: interface.c:441
static void * vnet_rewrite_get_data_internal(vnet_rewrite_header_t *rw, int max_size)
Definition: rewrite.h:121
#define PREDICT_FALSE(x)
Definition: clib.h:97
static u32 vnet_mpls_uc_get_label(mpls_label_t label_exp_s_ttl)
Definition: packet.h:77
vnet_main_t * vnet_main
Definition: mpls.h:128
u32 tx_sw_if_index
Definition: mpls.h:40
static u8 * format_mpls_eth_device(u8 *s, va_list *args)
Definition: interface.c:228
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
u32 output_next_index
Definition: mpls.h:54
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1113
VNET_HW_INTERFACE_CLASS(ethernet_hw_interface_class)
u8 * rewrite
Definition: mpls.h:53
u16 n_vectors
Definition: node.h:344
mpls_main_t mpls_main
Definition: mpls.c:25
vlib_node_registration_t ip4_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_node)
Definition: ip4_forward.c:2657
static u8 * format_mpls_eth_tunnel_name(u8 *s, va_list *args)
Definition: interface.c:222
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:793
#define MPLS_FIB_DEFAULT_TABLE_ID
Definition: mpls.h:57
static void vnet_rewrite_set_data_internal(vnet_rewrite_header_t *rw, int max_size, void *data, int data_bytes)
Definition: rewrite.h:102
#define clib_memcpy(a, b, c)
Definition: string.h:64
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:203
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
u8 * rewrite_data
Definition: mpls.h:45
mpls_eth_tunnel_t * eth_tunnels
Definition: mpls.h:106
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:134
u8 * default_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Return a complete, zero-length (aka dummy) rewrite.
Definition: interface.c:1350
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u32 mpls_encap_index
Definition: mpls.h:257
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:288
u16 cached_next_index
Definition: node.h:463
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:490
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:245
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:333
IPv4 main type.
Definition: ip4.h:95
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:949
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:239
From the control plane API.
Definition: fib_entry.h:57
u8 * format_mpls_encap_index(u8 *s, va_list *args)
Definition: interface.c:331
mpls_encap_t * mpls_encap_by_fib_and_dest(mpls_main_t *mm, u32 rx_fib, u32 dst_address)
Definition: mpls.c:180
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
Definition: defs.h:47
i64 word
Definition: types.h:111
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static u8 * mpls_ethernet_rewrite(mpls_main_t *mm, mpls_eth_tunnel_t *t)
Definition: interface.c:410
VLIB_DEVICE_TX_FUNCTION_MULTIARCH(mpls_eth_device_class, mpls_eth_interface_tx)
Definition: interface.c:250
u32 inner_fib_index
Definition: mpls.h:41
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
#define DPO_INVALID
An initialiser for DPos declared on the stack.
Definition: dpo.h:164
a point 2 point interface
Definition: interface.h:246
u32 encap_index
Definition: mpls.h:43
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:166
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1060
u8 data[0]
Packet data.
Definition: buffer.h:154
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:82
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:171
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:530
#define clib_error_return(e, args...)
Definition: error.h:111
VNET_DEVICE_CLASS(ethernet_simulated_device_class)
struct _unformat_input_t unformat_input_t
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:213
#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:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
u32 tx_sw_if_index
Definition: mpls.h:254
unformat_function_t unformat_line_input
Definition: format.h:281
u8 * format_mpls_ethernet_tunnel(u8 *s, va_list *args)
Definition: interface.c:348
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
u32 mpls_rx_feature_lookup
Definition: mpls.h:101
mpls_unicast_header_t * labels
Definition: mpls.h:51
mpls_encap_t * encaps
Definition: mpls.h:110
clib_error_t * mpls_interface_init(vlib_main_t *vm)
Definition: interface.c:398
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109