FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
l2_vtr.c
Go to the documentation of this file.
1 /*
2  * l2_vtr.c : layer 2 vlan tag rewrite configuration
3  *
4  * Copyright (c) 2013 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 <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vnet/ethernet/packet.h>
22 #include <vnet/l2/l2_input.h>
23 #include <vnet/l2/l2_output.h>
24 #include <vnet/l2/feat_bitmap.h>
25 #include <vnet/l2/l2_vtr.h>
26 #include <vnet/l2/l2_input_vtr.h>
27 #include <vnet/l2/l2_output.h>
28 
29 #include <vppinfra/error.h>
30 #include <vlib/cli.h>
31 
32 /**
33  * @file
34  * @brief Ethernet VLAN Tag Rewrite.
35  *
36  * VLAN tag rewrite provides the ability to change the VLAN tags on a packet.
37  * Existing tags can be popped, new tags can be pushed, and existing tags can
38  * be swapped with new tags. The rewrite feature is attached to a subinterface
39  * as input and output operations. The input operation is explicitly configured.
40  * The output operation is the symmetric opposite and is automatically derived
41  * from the input operation.
42  */
43 
44 /** Just a placeholder; ensures file is not eliminated by linker. */
47 {
48  return 0;
49 }
50 
52 
53 u32
55  vnet_main_t * vnet_main, u32 sw_if_index, u32 vtr_op,
56  u8 * b_dmac, u8 * b_smac,
57  u16 b_vlanid, u32 i_sid, u16 vlan_outer_tag)
58 {
59  u32 error = 0;
60  u32 enable = 0;
61 
62  l2_output_config_t *config = 0;
64  hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
65 
66  if (!hi)
67  {
68  error = VNET_API_ERROR_INVALID_INTERFACE;
69  goto done;
70  }
71 
72  // Config for this interface should be already initialized
73  ptr_config_t *in_config;
74  ptr_config_t *out_config;
75  config = vec_elt_at_index (l2output_main.configs, sw_if_index);
76  in_config = &(config->input_pbb_vtr);
77  out_config = &(config->output_pbb_vtr);
78 
79  in_config->pop_bytes = 0;
80  in_config->push_bytes = 0;
81  out_config->pop_bytes = 0;
82  out_config->push_bytes = 0;
83  enable = (vtr_op != L2_VTR_DISABLED);
84 
85  if (!enable)
86  goto done;
87 
88  if (vtr_op == L2_VTR_POP_2)
89  {
90  in_config->pop_bytes = sizeof (ethernet_pbb_header_packed_t);
91  }
92  else if (vtr_op == L2_VTR_PUSH_2)
93  {
94  clib_memcpy (in_config->macs_tags.b_dst_address, b_dmac,
95  sizeof (in_config->macs_tags.b_dst_address));
96  clib_memcpy (in_config->macs_tags.b_src_address, b_smac,
97  sizeof (in_config->macs_tags.b_src_address));
98  in_config->macs_tags.b_type =
99  clib_net_to_host_u16 (ETHERNET_TYPE_DOT1AD);
100  in_config->macs_tags.priority_dei_id =
101  clib_net_to_host_u16 (b_vlanid & 0xFFF);
102  in_config->macs_tags.i_type =
103  clib_net_to_host_u16 (ETHERNET_TYPE_DOT1AH);
105  clib_net_to_host_u32 (i_sid & 0xFFFFF);
106  in_config->push_bytes = sizeof (ethernet_pbb_header_packed_t);
107  }
108  else if (vtr_op == L2_VTR_TRANSLATE_2_2)
109  {
110  /* TODO after PoC */
111  }
112 
113  /*
114  * Construct the output tag-rewrite config
115  *
116  * The push/pop values are always reversed
117  */
118  out_config->raw_data = in_config->raw_data;
119  out_config->pop_bytes = in_config->push_bytes;
120  out_config->push_bytes = in_config->pop_bytes;
121 
122 done:
123  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VTR, enable);
124  if (config)
125  config->out_vtr_flag = (u8) enable;
126 
127  /* output vtr enable is checked explicitly in l2_output */
128  return error;
129 }
130 
131 /**
132  * Configure vtag tag rewrite on the given interface.
133  * Return 1 if there is an error, 0 if ok
134  */
135 u32
136 l2vtr_configure (vlib_main_t * vlib_main, vnet_main_t * vnet_main, u32 sw_if_index, u32 vtr_op, u32 push_dot1q, /* ethertype of first pushed tag is dot1q/dot1ad */
137  u32 vtr_tag1, /* first pushed tag */
138  u32 vtr_tag2) /* second pushed tag */
139 {
142  u32 hw_no_tags;
143  u32 error = 0;
144  l2_output_config_t *config;
145  vtr_config_t *in_config;
146  vtr_config_t *out_config;
147  u32 enable;
148  u32 push_inner_et;
149  u32 push_outer_et;
150  u32 cfg_tags;
151 
152  hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
153  if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
154  {
155  error = VNET_API_ERROR_INVALID_INTERFACE; /* non-ethernet interface */
156  goto done;
157  }
158 
159  /* Init the config for this interface */
160  vec_validate (l2output_main.configs, sw_if_index);
161  config = vec_elt_at_index (l2output_main.configs, sw_if_index);
162  in_config = &(config->input_vtr);
163  out_config = &(config->output_vtr);
164  in_config->raw_tags = 0;
165  out_config->raw_tags = 0;
166 
167  /* Get the configured tags for the interface */
168  si = vnet_get_sw_interface (vnet_main, sw_if_index);
169  hw_no_tags = (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE);
170 
171  /* Construct the input tag-rewrite config */
172 
173  push_outer_et =
174  clib_net_to_host_u16 (push_dot1q ? ETHERNET_TYPE_VLAN :
175  ETHERNET_TYPE_DOT1AD);
176  push_inner_et = clib_net_to_host_u16 (ETHERNET_TYPE_VLAN);
177  vtr_tag1 = clib_net_to_host_u16 (vtr_tag1);
178  vtr_tag2 = clib_net_to_host_u16 (vtr_tag2);
179 
180  /* Determine number of vlan tags with explictly configured values */
181  cfg_tags = 0;
182  if (hw_no_tags || si->sub.eth.flags.no_tags)
183  {
184  cfg_tags = 0;
185  }
186  else if (si->sub.eth.flags.one_tag)
187  {
188  cfg_tags = 1;
189  if (si->sub.eth.flags.outer_vlan_id_any)
190  {
191  cfg_tags = 0;
192  }
193  }
194  else if (si->sub.eth.flags.two_tags)
195  {
196  cfg_tags = 2;
197  if (si->sub.eth.flags.inner_vlan_id_any)
198  {
199  cfg_tags = 1;
200  }
201  if (si->sub.eth.flags.outer_vlan_id_any)
202  {
203  cfg_tags = 0;
204  }
205  }
206 
207  switch (vtr_op)
208  {
209  case L2_VTR_DISABLED:
210  in_config->push_and_pop_bytes = 0;
211  break;
212 
213  case L2_VTR_POP_1:
214  if (cfg_tags < 1)
215  {
216  /* Need one or two tags */
217  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT;
218  goto done;
219  }
220  in_config->pop_bytes = 4;
221  in_config->push_bytes = 0;
222  break;
223 
224  case L2_VTR_POP_2:
225  if (cfg_tags < 2)
226  {
227  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT; /* Need two tags */
228  goto done;
229  }
230  in_config->pop_bytes = 8;
231  in_config->push_bytes = 0;
232 
233  out_config->push_bytes = in_config->pop_bytes;
234  out_config->pop_bytes = in_config->push_bytes;
235  break;
236 
237  case L2_VTR_PUSH_1:
238  in_config->pop_bytes = 0;
239  in_config->push_bytes = 4;
240  in_config->tags[1].priority_cfi_and_id = vtr_tag1;
241  in_config->tags[1].type = push_outer_et;
242  break;
243 
244  case L2_VTR_PUSH_2:
245  in_config->pop_bytes = 0;
246  in_config->push_bytes = 8;
247  in_config->tags[0].priority_cfi_and_id = vtr_tag1;
248  in_config->tags[0].type = push_outer_et;
249  in_config->tags[1].priority_cfi_and_id = vtr_tag2;
250  in_config->tags[1].type = push_inner_et;
251  break;
252 
254  if (cfg_tags < 1)
255  {
256  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT; /* Need one or two tags */
257  goto done;
258  }
259  in_config->pop_bytes = 4;
260  in_config->push_bytes = 4;
261  in_config->tags[1].priority_cfi_and_id = vtr_tag1;
262  in_config->tags[1].type = push_outer_et;
263  break;
264 
266  if (cfg_tags < 1)
267  {
268  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT; /* Need one or two tags */
269  goto done;
270  }
271  in_config->pop_bytes = 4;
272  in_config->push_bytes = 8;
273  in_config->tags[0].priority_cfi_and_id = vtr_tag1;
274  in_config->tags[0].type = push_outer_et;
275  in_config->tags[1].priority_cfi_and_id = vtr_tag2;
276  in_config->tags[1].type = push_inner_et;
277  break;
278 
280  if (cfg_tags < 2)
281  {
282  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT; /* Need two tags */
283  goto done;
284  }
285  in_config->pop_bytes = 8;
286  in_config->push_bytes = 4;
287  in_config->tags[1].priority_cfi_and_id = vtr_tag1;
288  in_config->tags[1].type = push_outer_et;
289  break;
290 
292  if (cfg_tags < 2)
293  {
294  error = VNET_API_ERROR_INVALID_VLAN_TAG_COUNT; /* Need two tags */
295  goto done;
296  }
297  in_config->pop_bytes = 8;
298  in_config->push_bytes = 8;
299  in_config->tags[0].priority_cfi_and_id = vtr_tag1;
300  in_config->tags[0].type = push_outer_et;
301  in_config->tags[1].priority_cfi_and_id = vtr_tag2;
302  in_config->tags[1].type = push_inner_et;
303  break;
304  }
305 
306  /*
307  * Construct the output tag-rewrite config
308  *
309  * The push/pop values are always reversed
310  */
311  out_config->push_bytes = in_config->pop_bytes;
312  out_config->pop_bytes = in_config->push_bytes;
313 
314  /* Any pushed tags are derived from the subinterface config */
315  push_outer_et =
316  clib_net_to_host_u16 (si->sub.eth.flags.dot1ad ? ETHERNET_TYPE_DOT1AD :
317  ETHERNET_TYPE_VLAN);
318  push_inner_et = clib_net_to_host_u16 (ETHERNET_TYPE_VLAN);
319  vtr_tag1 = clib_net_to_host_u16 (si->sub.eth.outer_vlan_id);
320  vtr_tag2 = clib_net_to_host_u16 (si->sub.eth.inner_vlan_id);
321 
322  if (out_config->push_bytes == 4)
323  {
324  out_config->tags[1].priority_cfi_and_id = vtr_tag1;
325  out_config->tags[1].type = push_outer_et;
326  }
327  else if (out_config->push_bytes == 8)
328  {
329  out_config->tags[0].priority_cfi_and_id = vtr_tag1;
330  out_config->tags[0].type = push_outer_et;
331  out_config->tags[1].priority_cfi_and_id = vtr_tag2;
332  out_config->tags[1].type = push_inner_et;
333  }
334 
335  /* set the interface enable flags */
336  enable = (vtr_op != L2_VTR_DISABLED);
337  config->out_vtr_flag = (u8) enable;
338  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VTR, enable);
339  /* output vtr enable is checked explicitly in l2_output */
340 
341 done:
342  return error;
343 }
344 
345 /**
346  * Get vtag tag rewrite on the given interface.
347  * Return 1 if there is an error, 0 if ok
348  */
349 u32
350 l2vtr_get (vlib_main_t * vlib_main, vnet_main_t * vnet_main, u32 sw_if_index, u32 * vtr_op, u32 * push_dot1q, /* ethertype of first pushed tag is dot1q/dot1ad */
351  u32 * vtr_tag1, /* first pushed tag */
352  u32 * vtr_tag2) /* second pushed tag */
353 {
355  u32 error = 0;
356  vtr_config_t *in_config;
357 
358  if (!vtr_op || !push_dot1q || !vtr_tag1 || !vtr_tag2)
359  {
360  clib_warning ("invalid arguments");
361  error = VNET_API_ERROR_INVALID_ARGUMENT;
362  goto done;
363  }
364 
365  *vtr_op = L2_VTR_DISABLED;
366  *vtr_tag1 = 0;
367  *vtr_tag2 = 0;
368  *push_dot1q = 0;
369 
370  hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
371  if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
372  {
373  /* non-ethernet interface */
374  goto done;
375  }
376 
377  if (sw_if_index >= vec_len (l2output_main.configs))
378  {
379  /* no specific config (return disabled) */
380  goto done;
381  }
382 
383  /* Get the config for this interface */
384  in_config =
385  &(vec_elt_at_index (l2output_main.configs, sw_if_index)->input_vtr);
386 
387  /* DISABLED */
388  if (in_config->push_and_pop_bytes == 0)
389  {
390  goto done;
391  }
392 
393  /* find out vtr_op */
394  switch (in_config->pop_bytes)
395  {
396  case 0:
397  switch (in_config->push_bytes)
398  {
399  case 0:
400  /* DISABLED */
401  goto done;
402  case 4:
403  *vtr_op = L2_VTR_PUSH_1;
404  *vtr_tag1 =
405  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
406  *push_dot1q =
407  (ETHERNET_TYPE_VLAN ==
408  clib_host_to_net_u16 (in_config->tags[1].type));
409  break;
410  case 8:
411  *vtr_op = L2_VTR_PUSH_2;
412  *vtr_tag1 =
413  clib_host_to_net_u16 (in_config->tags[0].priority_cfi_and_id);
414  *vtr_tag2 =
415  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
416  *push_dot1q =
417  (ETHERNET_TYPE_VLAN ==
418  clib_host_to_net_u16 (in_config->tags[0].type));
419  break;
420  default:
421  clib_warning ("invalid push_bytes count: %d",
422  in_config->push_bytes);
423  error = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
424  goto done;
425  }
426  break;
427 
428  case 4:
429  switch (in_config->push_bytes)
430  {
431  case 0:
432  *vtr_op = L2_VTR_POP_1;
433  break;
434  case 4:
435  *vtr_op = L2_VTR_TRANSLATE_1_1;
436  *vtr_tag1 =
437  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
438  *push_dot1q =
439  (ETHERNET_TYPE_VLAN ==
440  clib_host_to_net_u16 (in_config->tags[1].type));
441  break;
442  case 8:
443  *vtr_op = L2_VTR_TRANSLATE_1_2;
444  *vtr_tag1 =
445  clib_host_to_net_u16 (in_config->tags[0].priority_cfi_and_id);
446  *vtr_tag2 =
447  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
448  *push_dot1q =
449  (ETHERNET_TYPE_VLAN ==
450  clib_host_to_net_u16 (in_config->tags[0].type));
451  break;
452  default:
453  clib_warning ("invalid push_bytes count: %d",
454  in_config->push_bytes);
455  error = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
456  goto done;
457  }
458  break;
459 
460  case 8:
461  switch (in_config->push_bytes)
462  {
463  case 0:
464  *vtr_op = L2_VTR_POP_2;
465  break;
466  case 4:
467  *vtr_op = L2_VTR_TRANSLATE_2_1;
468  *vtr_tag1 =
469  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
470  *push_dot1q =
471  (ETHERNET_TYPE_VLAN ==
472  clib_host_to_net_u16 (in_config->tags[1].type));
473  break;
474  case 8:
475  *vtr_op = L2_VTR_TRANSLATE_2_2;
476  *vtr_tag1 =
477  clib_host_to_net_u16 (in_config->tags[0].priority_cfi_and_id);
478  *vtr_tag2 =
479  clib_host_to_net_u16 (in_config->tags[1].priority_cfi_and_id);
480  *push_dot1q =
481  (ETHERNET_TYPE_VLAN ==
482  clib_host_to_net_u16 (in_config->tags[0].type));
483  break;
484  default:
485  clib_warning ("invalid push_bytes count: %d",
486  in_config->push_bytes);
487  error = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
488  goto done;
489  }
490  break;
491 
492  default:
493  clib_warning ("invalid pop_bytes count: %d", in_config->pop_bytes);
494  error = VNET_API_ERROR_UNEXPECTED_INTF_STATE;
495  goto done;
496  }
497 
498 done:
499  return error;
500 }
501 
502 /**
503  * Set subinterface vtr enable/disable.
504  * The CLI format is:
505  * set interface l2 tag-rewrite <interface> [disable | pop 1 | pop 2 | push {dot1q|dot1ad} <tag> [<tag>]]
506  *
507  * "push" can also be replaced by "translate-{1|2}-{1|2}"
508  */
509 static clib_error_t *
511  unformat_input_t * input, vlib_cli_command_t * cmd)
512 {
513  vnet_main_t *vnm = vnet_get_main ();
514  clib_error_t *error = 0;
515  u32 sw_if_index;
516  u32 vtr_op;
517  u32 push_dot1q = 0;
518  u32 tag1 = 0, tag2 = 0;
519 
520  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
521  {
522  error = clib_error_return (0, "unknown interface `%U'",
523  format_unformat_error, input);
524  goto done;
525  }
526 
527  vtr_op = L2_VTR_DISABLED;
528 
529  if (unformat (input, "disable"))
530  {
531  vtr_op = L2_VTR_DISABLED;
532  }
533  else if (unformat (input, "pop 1"))
534  {
535  vtr_op = L2_VTR_POP_1;
536  }
537  else if (unformat (input, "pop 2"))
538  {
539  vtr_op = L2_VTR_POP_2;
540 
541  }
542  else if (unformat (input, "push dot1q %d %d", &tag1, &tag2))
543  {
544  vtr_op = L2_VTR_PUSH_2;
545  push_dot1q = 1;
546  }
547  else if (unformat (input, "push dot1ad %d %d", &tag1, &tag2))
548  {
549  vtr_op = L2_VTR_PUSH_2;
550 
551  }
552  else if (unformat (input, "push dot1q %d", &tag1))
553  {
554  vtr_op = L2_VTR_PUSH_1;
555  push_dot1q = 1;
556  }
557  else if (unformat (input, "push dot1ad %d", &tag1))
558  {
559  vtr_op = L2_VTR_PUSH_1;
560 
561  }
562  else if (unformat (input, "translate 1-1 dot1q %d", &tag1))
563  {
564  vtr_op = L2_VTR_TRANSLATE_1_1;
565  push_dot1q = 1;
566  }
567  else if (unformat (input, "translate 1-1 dot1ad %d", &tag1))
568  {
569  vtr_op = L2_VTR_TRANSLATE_1_1;
570 
571  }
572  else if (unformat (input, "translate 2-1 dot1q %d", &tag1))
573  {
574  vtr_op = L2_VTR_TRANSLATE_2_1;
575  push_dot1q = 1;
576  }
577  else if (unformat (input, "translate 2-1 dot1ad %d", &tag1))
578  {
579  vtr_op = L2_VTR_TRANSLATE_2_1;
580 
581  }
582  else if (unformat (input, "translate 2-2 dot1q %d %d", &tag1, &tag2))
583  {
584  vtr_op = L2_VTR_TRANSLATE_2_2;
585  push_dot1q = 1;
586  }
587  else if (unformat (input, "translate 2-2 dot1ad %d %d", &tag1, &tag2))
588  {
589  vtr_op = L2_VTR_TRANSLATE_2_2;
590 
591  }
592  else if (unformat (input, "translate 1-2 dot1q %d %d", &tag1, &tag2))
593  {
594  vtr_op = L2_VTR_TRANSLATE_1_2;
595  push_dot1q = 1;
596  }
597  else if (unformat (input, "translate 1-2 dot1ad %d %d", &tag1, &tag2))
598  {
599  vtr_op = L2_VTR_TRANSLATE_1_2;
600 
601  }
602  else
603  {
604  error =
606  "expecting [disable | pop 1 | pop 2 | push {dot1q|dot1ah} <tag> [<tag>]\n"
607  " | translate {1|2}-{1|2} {dot1q|dot1ah} <tag> [<tag>]] but got `%U'",
608  format_unformat_error, input);
609  goto done;
610  }
611 
612  if (l2vtr_configure (vm, vnm, sw_if_index, vtr_op, push_dot1q, tag1, tag2))
613  {
614  error =
616  "vlan tag rewrite is not compatible with interface");
617  goto done;
618  }
619 
620 done:
621  return error;
622 }
623 
624 /*?
625  * VLAN tag rewrite provides the ability to change the VLAN tags on a packet.
626  * Existing tags can be popped, new tags can be pushed, and existing tags can
627  * be swapped with new tags. The rewrite feature is attached to a subinterface
628  * as input and output operations. The input operation is explicitly configured.
629  * The output operation is the symmetric opposite and is automatically derived
630  * from the input operation.
631  *
632  * <b>POP:</b> For pop operations, the subinterface encapsulation (the vlan
633  * tags specified when it was created) must have at least the number of popped
634  * tags. e.g. the \"pop 2\" operation would be rejected on a single-vlan interface.
635  * The output tag-rewrite operation for pops is to push the specified number of
636  * vlan tags onto the packet. The pushed tag values are the ones in the
637  * subinterface encapsulation.
638  *
639  * <b>PUSH:</b> For push operations, the ethertype is also specified. The
640  * output tag-rewrite operation for pushes is to pop the same number of tags
641  * off the packet. If the packet doesn't have enough tags it is dropped.
642  *
643  *
644  * @cliexpar
645  * @parblock
646  * By default a subinterface has no tag-rewrite. To return a subinterface to
647  * this state use:
648  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 disable}
649  *
650  * To pop vlan tags off packets received from a subinterface, use:
651  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 pop 1}
652  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 pop 2}
653  *
654  * To push one or two vlan tags onto packets received from an interface, use:
655  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 push dot1q 100}
656  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 push dot1ad 100 150}
657  *
658  * Tags can also be translated, which is basically a combination of a pop and push.
659  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 translate 1-1 dot1ad 100}
660  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 translate 2-2 dot1ad 100 150}
661  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 translate 1-2 dot1q 100}
662  * @cliexcmd{set interface l2 tag-rewrite GigabitEthernet0/8/0.200 translate 2-1 dot1q 100 150}
663  *
664  * To display the VLAN Tag settings, show the associate bridge-domain:
665  * @cliexstart{show bridge-domain 200 detail}
666  * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
667  * 200 1 on on on on off N/A
668  *
669  * Interface Index SHG BVI VLAN-Tag-Rewrite
670  * GigabitEthernet0/8/0.200 5 0 - trans-1-1 dot1ad 100
671  * GigabitEthernet0/9/0.200 4 0 - none
672  * GigabitEthernet0/a/0.200 6 0 - none
673  * @cliexend
674  * @endparblock
675 ?*/
676 /* *INDENT-OFF* */
677 VLIB_CLI_COMMAND (int_l2_vtr_cli, static) = {
678  .path = "set interface l2 tag-rewrite",
679  .short_help = "set interface l2 tag-rewrite <interface> [disable | pop {1|2} | push {dot1q|dot1ad} <tag> <tag>]",
680  .function = int_l2_vtr,
681 };
682 /* *INDENT-ON* */
683 
684 /**
685  * Set subinterface pbb vtr enable/disable.
686  * The CLI format is:
687  * set interface l2 pbb-tag-rewrite <interface> [disable | pop | push | translate_pbb_stag <outer_tag> dmac <address> smac <address> s_id <nn> [b_vlanid <nn>]]
688  */
689 static clib_error_t *
691  unformat_input_t * input, vlib_cli_command_t * cmd)
692 {
693  vnet_main_t *vnm = vnet_get_main ();
694  clib_error_t *error = 0;
695  u32 sw_if_index, tmp;
696  u32 vtr_op = L2_VTR_DISABLED;
697  u32 outer_tag = 0;
698  u8 dmac[6];
699  u8 smac[6];
700  u8 dmac_set = 0, smac_set = 0;
701  u16 b_vlanid = 0;
702  u32 s_id = ~0;
703 
705  {
706  if (unformat_user
707  (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
708  ;
709  else if (unformat (input, "disable"))
710  vtr_op = L2_VTR_DISABLED;
711  else if (vtr_op == L2_VTR_DISABLED && unformat (input, "pop"))
712  vtr_op = L2_VTR_POP_2;
713  else if (vtr_op == L2_VTR_DISABLED && unformat (input, "push"))
714  vtr_op = L2_VTR_PUSH_2;
715  else if (vtr_op == L2_VTR_DISABLED
716  && unformat (input, "translate_pbb_stag %d", &outer_tag))
717  vtr_op = L2_VTR_TRANSLATE_2_1;
718  else if (unformat (input, "dmac %U", unformat_ethernet_address, dmac))
719  dmac_set = 1;
720  else if (unformat (input, "smac %U", unformat_ethernet_address, smac))
721  smac_set = 1;
722  else if (unformat (input, "b_vlanid %d", &tmp))
723  b_vlanid = tmp;
724  else if (unformat (input, "s_id %d", &s_id))
725  ;
726  else
727  {
728  error = clib_error_return (0,
729  "expecting [disable | pop | push | translate_pbb_stag <outer_tag>\n"
730  "dmac <address> smac <address> s_id <nn> [b_vlanid <nn>]]");
731  goto done;
732  }
733  }
734 
735  if ((vtr_op == L2_VTR_PUSH_2 || vtr_op == L2_VTR_TRANSLATE_2_1)
736  && (!dmac_set || !smac_set || s_id == ~0))
737  {
738  error = clib_error_return (0,
739  "expecting dmac <address> smac <address> s_id <nn> [b_vlanid <nn>]");
740  goto done;
741  }
742 
743  if (l2pbb_configure
744  (vm, vnm, sw_if_index, vtr_op, dmac, smac, b_vlanid, s_id, outer_tag))
745  {
746  error =
748  "pbb tag rewrite is not compatible with interface");
749  goto done;
750  }
751 
752 done:
753  return error;
754 }
755 
756 /* *INDENT-OFF* */
757 VLIB_CLI_COMMAND (int_l2_pbb_vtr_cli, static) = {
758  .path = "set interface l2 pbb-tag-rewrite",
759  .short_help = "set interface l2 pbb-tag-rewrite <interface> [disable | pop | push | translate_pbb_stag <outer_tag> dmac <address> smac <address> s_id <nn> [b_vlanid <nn>]]",
760  .function = int_l2_pbb_vtr,
761 };
762 /* *INDENT-ON* */
763 
764 /*
765  * fd.io coding-style-patch-verification: ON
766  *
767  * Local Variables:
768  * eval: (c-set-style "gnu")
769  * End:
770  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
vmrglw vmrglh hi
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
u8 push_bytes
Definition: l2_vtr.h:61
u32 l2vtr_configure(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 vtr_op, u32 push_dot1q, u32 vtr_tag1, u32 vtr_tag2)
Configure vtag tag rewrite on the given interface.
Definition: l2_vtr.c:136
clib_error_t * l2_vtr_init(vlib_main_t *vm)
Just a placeholder; ensures file is not eliminated by linker.
Definition: l2_vtr.c:46
struct ptr_config_t::@206::@210 raw_data
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 pop_bytes
Definition: l2_vtr.h:62
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
u16 push_and_pop_bytes
Definition: l2_vtr.h:64
Per-interface vlan tag rewrite configuration There will be one instance of this struct for each sw_if...
Definition: l2_vtr.h:45
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
struct vnet_sub_interface_t::@154::@155::@157 flags
ptr_config_t output_pbb_vtr
Definition: l2_output.h:41
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#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 vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:1599
u8 push_bytes
Definition: l2_vtr.h:191
vnet_sub_interface_t sub
Definition: interface.h:558
vtr_config_t input_vtr
Definition: l2_output.h:38
vnet_main_t vnet_main
Definition: misc.c:43
l2output_main_t l2output_main
Definition: l2_output.c:43
vnet_hw_interface_class_t ethernet_hw_interface_class
u32 l2pbb_configure(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 vtr_op, u8 *b_dmac, u8 *b_smac, u16 b_vlanid, u32 i_sid, u16 vlan_outer_tag)
Definition: l2_vtr.c:54
#define clib_memcpy(a, b, c)
Definition: string.h:69
u8 pop_bytes
Definition: l2_vtr.h:192
vtr_config_t output_vtr
Definition: l2_output.h:39
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:245
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u64 raw_tags
Definition: l2_vtr.h:54
static clib_error_t * int_l2_vtr(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface vtr enable/disable.
Definition: l2_vtr.c:510
u32 l2input_intf_bitmap_enable(u32 sw_if_index, u32 feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_input.c:468
unsigned short u16
Definition: types.h:57
ptr_config_t input_pbb_vtr
Definition: l2_output.h:40
ethernet_vlan_header_tv_t tags[2]
Definition: l2_vtr.h:53
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
struct vnet_sub_interface_t::@154 eth
l2_output_config_t * configs
Definition: l2_output.h:84
ethernet_pbb_header_t macs_tags
Definition: l2_vtr.h:178
u32 l2vtr_get(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 *vtr_op, u32 *push_dot1q, u32 *vtr_tag1, u32 *vtr_tag2)
Get vtag tag rewrite on the given interface.
Definition: l2_vtr.c:350
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
vnet_sw_interface_type_t type
Definition: interface.h:523
static clib_error_t * int_l2_pbb_vtr(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface pbb vtr enable/disable.
Definition: l2_vtr.c:690
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
u32 priority_dei_uca_res_sid
Definition: packet.h:120