LCOV - code coverage report
Current view: top level - vnet/dpo - mpls_label_dpo.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 436 449 97.1 %
Date: 2023-07-05 22:20:52 Functions: 98 138 71.0 %

          Line data    Source code
       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             : 
      16             : #include <vnet/ip/ip.h>
      17             : #include <vnet/dpo/mpls_label_dpo.h>
      18             : #include <vnet/mpls/mpls.h>
      19             : #include <vnet/dpo/drop_dpo.h>
      20             : 
      21             : // clang-format off
      22             : 
      23             : #ifndef CLIB_MARCH_VARIANT
      24             : /*
      25             :  * pool of all MPLS Label DPOs
      26             :  */
      27             : mpls_label_dpo_t *mpls_label_dpo_pool;
      28             : 
      29             : /**
      30             :  * Strings for the flags
      31             :  */
      32             : const char* mpls_label_dpo_attr_names[] = MPLS_LABEL_DPO_ATTR_NAMES;
      33             : 
      34             : /**
      35             :  * registered DPO types for each of the label sub-types. And there's a
      36             :  * subtype for each of the flag combinations.
      37             :  */
      38             : static dpo_type_t mpls_label_dpo_types[1 << MPLS_LABEL_DPO_ATTR_MAX];
      39             : 
      40             : static mpls_label_dpo_t *
      41        1783 : mpls_label_dpo_alloc (void)
      42             : {
      43             :     mpls_label_dpo_t *mld;
      44             :     vlib_main_t *vm;
      45             :     u8 did_barrier_sync;
      46             : 
      47        1783 :     dpo_pool_barrier_sync (vm, mpls_label_dpo_pool, did_barrier_sync);
      48        1783 :     pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
      49        1783 :     dpo_pool_barrier_release (vm, did_barrier_sync);
      50             : 
      51        1783 :     clib_memset(mld, 0, sizeof(*mld));
      52             : 
      53        1783 :     dpo_reset(&mld->mld_dpo);
      54             : 
      55        1783 :     return (mld);
      56             : }
      57             : 
      58             : static index_t
      59        1783 : mpls_label_dpo_get_index (mpls_label_dpo_t *mld)
      60             : {
      61        1783 :     return (mld - mpls_label_dpo_pool);
      62             : }
      63             : 
      64             : void
      65        1769 : mpls_label_dpo_create (fib_mpls_label_t *label_stack,
      66             :                        mpls_eos_bit_t eos,
      67             :                        dpo_proto_t payload_proto,
      68             :                        mpls_label_dpo_flags_t flags,
      69             :                        const dpo_id_t *parent,
      70             :                        dpo_id_t *dpo)
      71             : {
      72             :     mpls_label_dpo_t *mld;
      73             :     dpo_type_t dtype;
      74             :     u32 ii;
      75             : 
      76        1769 :     if ((DPO_PROTO_IP4 != payload_proto) &&
      77             :         (DPO_PROTO_IP6 != payload_proto))
      78             :     {
      79             :         /*
      80             :          * remove unsupported configuration
      81             :          */
      82         595 :         flags &= ~MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR;
      83             :     }
      84             : 
      85        1769 :     mld = mpls_label_dpo_alloc();
      86        1769 :     mld->mld_flags = flags;
      87        1769 :     dtype = mpls_label_dpo_types[flags];
      88             : 
      89        1769 :     if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
      90             :     {
      91           0 :         clib_warning("Label stack size exceeded");
      92           0 :         dpo_stack(dtype,
      93           0 :                   mld->mld_payload_proto,
      94             :                   &mld->mld_dpo,
      95             :                   drop_dpo_get(DPO_PROTO_MPLS));
      96             :     }
      97             :     else
      98             :     {
      99        1769 :         mld->mld_n_labels = vec_len(label_stack);
     100        1769 :         mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
     101        1769 :         mld->mld_payload_proto = payload_proto;
     102             : 
     103             :         /*
     104             :          * construct label rewrite headers for each value passed.
     105             :          * get the header in network byte order since we will paint it
     106             :          * on a packet in the data-plane
     107             :          */
     108        2126 :         for (ii = 0; ii < mld->mld_n_labels-1; ii++)
     109             :         {
     110         357 :             vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
     111         357 :                                    label_stack[ii].fml_value);
     112         357 :             vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
     113         357 :                                  label_stack[ii].fml_exp);
     114         357 :             vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl,
     115             :                                MPLS_NON_EOS);
     116         357 :             if (0 != label_stack[ii].fml_ttl)
     117             :             {
     118         338 :                 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
     119         338 :                                      label_stack[ii].fml_ttl);
     120             :             }
     121             :             else
     122             :             {
     123          19 :                 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
     124             :                                      MPLS_LABEL_DEFAULT_TTL);
     125             :             }
     126         357 :             mld->mld_hdr[ii].label_exp_s_ttl =
     127         357 :                 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
     128             :         }
     129             : 
     130             :         /*
     131             :          * the inner most label
     132             :          */
     133        1769 :         ii = mld->mld_n_labels-1;
     134             : 
     135        1769 :         vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
     136        1769 :                                label_stack[ii].fml_value);
     137        1769 :         vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
     138        1769 :                              label_stack[ii].fml_exp);
     139        1769 :         vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
     140        1769 :         if (0 != label_stack[ii].fml_ttl)
     141             :         {
     142        1677 :             vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
     143        1677 :                                  label_stack[ii].fml_ttl);
     144             :         }
     145             :         else
     146             :         {
     147          92 :             vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
     148             :                                  MPLS_LABEL_DEFAULT_TTL);
     149             :         }
     150        1769 :         mld->mld_hdr[ii].label_exp_s_ttl =
     151        1769 :             clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
     152             : 
     153             :         /*
     154             :          * pipe/uniform mode is only supported for the bottom of stack label
     155             :          */
     156        1769 :         if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
     157             :         {
     158         341 :             mld->mld_flags |= MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
     159             :         }
     160             :         else
     161             :         {
     162        1428 :             mld->mld_flags &= ~MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
     163             :         }
     164        1769 :         dtype = mpls_label_dpo_types[mld->mld_flags];
     165             : 
     166             :         /*
     167             :          * stack this label object on its parent.
     168             :          */
     169        1769 :         dpo_stack(dtype,
     170        1769 :                   mld->mld_payload_proto,
     171             :                   &mld->mld_dpo,
     172             :                   parent);
     173             :     }
     174             : 
     175        1769 :     dpo_set(dpo,
     176             :             dtype,
     177        1769 :             mld->mld_payload_proto,
     178             :             mpls_label_dpo_get_index(mld));
     179        1769 : }
     180             : 
     181             : u8*
     182        1207 : format_mpls_label_dpo_flags (u8 *s, va_list *args)
     183             : {
     184        1207 :     mpls_label_dpo_flags_t flags = va_arg (*args, int);
     185             :     mpls_label_dpo_attr_t attr;
     186             : 
     187        3621 :     FOR_EACH_MPLS_LABEL_DPO_ATTR(attr)
     188             :     {
     189        2414 :         if ((1 << attr) & flags)
     190             :         {
     191         352 :             s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
     192             :         }
     193             :     }
     194             : 
     195        1207 :     return (s);
     196             : }
     197             : 
     198             : u8*
     199        2235 : format_mpls_label_dpo (u8 *s, va_list *args)
     200             : {
     201        2235 :     index_t index = va_arg (*args, index_t);
     202        2235 :     u32 indent = va_arg (*args, u32);
     203             :     mpls_unicast_header_t hdr;
     204             :     mpls_label_dpo_t *mld;
     205             :     u32 ii;
     206             : 
     207        2235 :     if (pool_is_free_index(mpls_label_dpo_pool, index))
     208             :     {
     209             :         /*
     210             :          * the packet trace can be printed after the DPO has been deleted
     211             :          */
     212        1028 :         return (format(s, "mpls-label[???,%d]:", index));
     213             :     }
     214             : 
     215        1207 :     mld = mpls_label_dpo_get(index);
     216        1207 :     s = format(s, "mpls-label[%U@%d]:",
     217             :                format_mpls_label_dpo_flags,
     218        1207 :                (int) mld->mld_flags, index);
     219             : 
     220        3415 :     for (ii = 0; ii < mld->mld_n_labels; ii++)
     221             :     {
     222        2208 :         hdr.label_exp_s_ttl =
     223        2208 :             clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
     224        2208 :         s = format(s, "%U", format_mpls_header, hdr);
     225             :     }
     226             : 
     227        1207 :     s = format(s, "\n%U", format_white_space, indent);
     228        1207 :     s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
     229             : 
     230        1207 :     return (s);
     231             : }
     232             : 
     233             : static void
     234        5451 : mpls_label_dpo_lock (dpo_id_t *dpo)
     235             : {
     236             :     mpls_label_dpo_t *mld;
     237             : 
     238        5451 :     mld = mpls_label_dpo_get(dpo->dpoi_index);
     239             : 
     240        5451 :     mld->mld_locks++;
     241        5451 : }
     242             : 
     243             : static void
     244        5451 : mpls_label_dpo_unlock (dpo_id_t *dpo)
     245             : {
     246             :     mpls_label_dpo_t *mld;
     247             : 
     248        5451 :     mld = mpls_label_dpo_get(dpo->dpoi_index);
     249             : 
     250        5451 :     mld->mld_locks--;
     251             : 
     252        5451 :     if (0 == mld->mld_locks)
     253             :     {
     254        1783 :         dpo_reset(&mld->mld_dpo);
     255        1783 :         pool_put(mpls_label_dpo_pool, mld);
     256             :     }
     257        5451 : }
     258             : #endif /* CLIB_MARCH_VARIANT */
     259             : 
     260             : /**
     261             :  * @brief A struct to hold tracing information for the MPLS label imposition
     262             :  * node.
     263             :  */
     264             : typedef struct mpls_label_imposition_trace_t_
     265             : {
     266             :     /**
     267             :      * The MPLS header imposed
     268             :      */
     269             :     mpls_unicast_header_t hdr;
     270             : 
     271             :     /**
     272             :      * TTL imposed - only valid for uniform LSPs
     273             :      */
     274             :     u8 ttl;
     275             : 
     276             :     /**
     277             :      * TTL imposed - only valid for uniform LSPs
     278             :      */
     279             :     u8 exp;
     280             : } mpls_label_imposition_trace_t;
     281             : 
     282             : always_inline mpls_unicast_header_t *
     283       19908 : mpls_label_paint (vlib_buffer_t * b0,
     284             :                   mpls_label_dpo_t *mld0)
     285             : {
     286             :     mpls_unicast_header_t *hdr0;
     287             : 
     288       19908 :     vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
     289             : 
     290       19908 :     hdr0 = vlib_buffer_get_current(b0);
     291             : 
     292       19908 :     if (1 == mld0->mld_n_labels)
     293             :     {
     294             :         /* optimise for the common case of one label */
     295       13930 :         *hdr0 = mld0->mld_hdr[0];
     296             :     }
     297             :     else
     298             :     {
     299        5978 :         clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
     300        5978 :         hdr0 = hdr0 + (mld0->mld_n_labels - 1);
     301             :     }
     302             : 
     303       19908 :     return (hdr0);
     304             : }
     305             : 
     306             : /**
     307             :  * Paint on an MPLS label and fixup the TTL
     308             :  */
     309             : always_inline mpls_unicast_header_t *
     310        5024 : mpls_label_paint_w_ttl (vlib_buffer_t * b0,
     311             :                         mpls_label_dpo_t *mld0,
     312             :                         u8 ttl0)
     313             : {
     314             :     mpls_unicast_header_t *hdr0;
     315             : 
     316        5024 :     hdr0 = mpls_label_paint(b0, mld0);
     317             : 
     318             :     /* fixup the TTL for the inner most label */
     319        5024 :     ((char*)hdr0)[3] = ttl0;
     320             : 
     321        5024 :     return (hdr0);
     322             : }
     323             : 
     324             : /**
     325             :  * Paint on an MPLS label and fixup the TTL and EXP bits.
     326             :  */
     327             : always_inline mpls_unicast_header_t *
     328        4510 : mpls_label_paint_w_ttl_exp (vlib_buffer_t * b0,
     329             :                             mpls_label_dpo_t *mld0,
     330             :                             u8 ttl0,
     331             :                             u8 exp0)
     332             : {
     333             :     mpls_unicast_header_t *hdr0;
     334             : 
     335        4510 :     hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
     336             : 
     337             :     /* fixup the EXP for the inner most label */
     338        4510 :     ((char*)hdr0)[2] |= (exp0 << 1);
     339             : 
     340        4510 :     return (hdr0);
     341             : }
     342             : 
     343             : /**
     344             :  * Paint on an MPLS label and fixup the TTL and EXP bits
     345             :  * When the EXP bits are *already* bit shift to the correct place in
     346             :  * in the 2nd byte (i.e. they were read from another label)
     347             :  */
     348             : always_inline mpls_unicast_header_t *
     349         514 : mpls_label_paint_w_ttl_mpls_exp (vlib_buffer_t * b0,
     350             :                                  mpls_label_dpo_t *mld0,
     351             :                                  u8 ttl0,
     352             :                                  u8 exp0)
     353             : {
     354             :     mpls_unicast_header_t *hdr0;
     355             : 
     356         514 :     hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
     357             : 
     358             :     /* fixup the EXP for the inner most label */
     359         514 :     ((char*)hdr0)[2] |= exp0;
     360             : 
     361         514 :     return (hdr0);
     362             : }
     363             : 
     364             : always_inline uword
     365         171 : mpls_label_imposition_inline (vlib_main_t * vm,
     366             :                               vlib_node_runtime_t * node,
     367             :                               vlib_frame_t * from_frame,
     368             :                               const dpo_proto_t dproto,
     369             :                               const mpls_label_dpo_flags_t flags)
     370             : {
     371             :     u32 n_left_from, next_index, * from, * to_next;
     372             : 
     373         171 :     from = vlib_frame_vector_args (from_frame);
     374         171 :     n_left_from = from_frame->n_vectors;
     375             : 
     376         171 :     next_index = node->cached_next_index;
     377             : 
     378         342 :     while (n_left_from > 0)
     379             :     {
     380             :         u32 n_left_to_next;
     381             : 
     382         171 :         vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
     383             : 
     384        5017 :         while (n_left_from >= 8 && n_left_to_next >= 4)
     385             :         {
     386             :             u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
     387             :             mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
     388             :             mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
     389             :             vlib_buffer_t * b0, *b1, * b2, *b3;
     390             :             u32 next0, next1, next2, next3;
     391             :             u8 ttl0, ttl1, ttl2, ttl3;
     392             :             u8 exp0, exp1, exp2, exp3;
     393             : 
     394        4846 :             bi0 = to_next[0] = from[0];
     395        4846 :             bi1 = to_next[1] = from[1];
     396        4846 :             bi2 = to_next[2] = from[2];
     397        4846 :             bi3 = to_next[3] = from[3];
     398             : 
     399             :             /* Prefetch next iteration. */
     400             :             {
     401             :                 vlib_buffer_t * p2, * p3, *p4, *p5;
     402             : 
     403        4846 :                 p2 = vlib_get_buffer (vm, from[2]);
     404        4846 :                 p3 = vlib_get_buffer (vm, from[3]);
     405        4846 :                 p4 = vlib_get_buffer (vm, from[4]);
     406        4846 :                 p5 = vlib_get_buffer (vm, from[5]);
     407             : 
     408        4846 :                 vlib_prefetch_buffer_header (p2, STORE);
     409        4846 :                 vlib_prefetch_buffer_header (p3, STORE);
     410        4846 :                 vlib_prefetch_buffer_header (p4, STORE);
     411        4846 :                 vlib_prefetch_buffer_header (p5, STORE);
     412             : 
     413        4846 :                 CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
     414        4846 :                 CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
     415        4846 :                 CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
     416        4846 :                 CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
     417             :             }
     418             : 
     419        4846 :             from += 4;
     420        4846 :             to_next += 4;
     421        4846 :             n_left_from -= 4;
     422        4846 :             n_left_to_next -= 4;
     423             : 
     424        4846 :             b0 = vlib_get_buffer (vm, bi0);
     425        4846 :             b1 = vlib_get_buffer (vm, bi1);
     426        4846 :             b2 = vlib_get_buffer (vm, bi2);
     427        4846 :             b3 = vlib_get_buffer (vm, bi3);
     428             : 
     429             :             /* dst lookup was done by ip4 lookup */
     430        4846 :             mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
     431        4846 :             mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
     432        4846 :             mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
     433        4846 :             mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
     434        4846 :             mld0 = mpls_label_dpo_get(mldi0);
     435        4846 :             mld1 = mpls_label_dpo_get(mldi1);
     436        4846 :             mld2 = mpls_label_dpo_get(mldi2);
     437        4846 :             mld3 = mpls_label_dpo_get(mldi3);
     438             : 
     439        4846 :             if (DPO_PROTO_MPLS != dproto)
     440             :             {
     441             :                 /*
     442             :                  * These are the non-MPLS payload imposition cases.
     443             :                  * Save the l3 offset
     444             :                  */
     445        2317 :                 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
     446        2317 :                 vnet_buffer (b1)->l3_hdr_offset = b1->current_data;
     447        2317 :                 vnet_buffer (b2)->l3_hdr_offset = b2->current_data;
     448        2317 :                 vnet_buffer (b3)->l3_hdr_offset = b3->current_data;
     449             : 
     450        2317 :                 if (DPO_PROTO_IP4 == dproto)
     451             :                 {
     452        2039 :                     ip4_header_t * ip0 = vlib_buffer_get_current(b0);
     453        2039 :                     ip4_header_t * ip1 = vlib_buffer_get_current(b1);
     454        2039 :                     ip4_header_t * ip2 = vlib_buffer_get_current(b2);
     455        2039 :                     ip4_header_t * ip3 = vlib_buffer_get_current(b3);
     456             : 
     457        2039 :                     if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
     458             :                     {
     459             :                         /*
     460             :                          * decrement the TTL on ingress to the LSP
     461             :                          */
     462             :                         u32 checksum0;
     463             :                         u32 checksum1;
     464             :                         u32 checksum2;
     465             :                         u32 checksum3;
     466             : 
     467        1472 :                         checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
     468        1472 :                         checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
     469        1472 :                         checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
     470        1472 :                         checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
     471             : 
     472        1472 :                         checksum0 += checksum0 >= 0xffff;
     473        1472 :                         checksum1 += checksum1 >= 0xffff;
     474        1472 :                         checksum2 += checksum2 >= 0xffff;
     475        1472 :                         checksum3 += checksum3 >= 0xffff;
     476             : 
     477        1472 :                         ip0->checksum = checksum0;
     478        1472 :                         ip1->checksum = checksum1;
     479        1472 :                         ip2->checksum = checksum2;
     480        1472 :                         ip3->checksum = checksum3;
     481             : 
     482        1472 :                         ip0->ttl -= 1;
     483        1472 :                         ip1->ttl -= 1;
     484        1472 :                         ip2->ttl -= 1;
     485        1472 :                         ip3->ttl -= 1;
     486             :                     }
     487             : 
     488        2039 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     489             :                     {
     490         126 :                         ttl1 = ip1->ttl;
     491         126 :                         ttl0 = ip0->ttl;
     492         126 :                         ttl3 = ip3->ttl;
     493         126 :                         ttl2 = ip2->ttl;
     494             :                         /* by default copy the 3 most significant bits */
     495         126 :                         exp0 = ip_dscp_to_mpls_exp(ip0->tos);
     496         126 :                         exp1 = ip_dscp_to_mpls_exp(ip1->tos);
     497         126 :                         exp2 = ip_dscp_to_mpls_exp(ip2->tos);
     498         126 :                         exp3 = ip_dscp_to_mpls_exp(ip3->tos);
     499             :                     }
     500             : 
     501             :                     /* save the payload proto information in mpls opaque */
     502        2039 :                     vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
     503        2039 :                     vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
     504        2039 :                     vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
     505        2039 :                     vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
     506             :                 }
     507         278 :                 else if (DPO_PROTO_IP6 == dproto)
     508             :                 {
     509             :                     /*
     510             :                      * decrement the TTL on ingress to the LSP
     511             :                      */
     512         233 :                     ip6_header_t * ip0 = vlib_buffer_get_current(b0);
     513         233 :                     ip6_header_t * ip1 = vlib_buffer_get_current(b1);
     514         233 :                     ip6_header_t * ip2 = vlib_buffer_get_current(b2);
     515         233 :                     ip6_header_t * ip3 = vlib_buffer_get_current(b3);
     516             : 
     517         233 :                     if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
     518             :                     {
     519         233 :                         ip0->hop_limit -= 1;
     520         233 :                         ip1->hop_limit -= 1;
     521         233 :                         ip2->hop_limit -= 1;
     522         233 :                         ip3->hop_limit -= 1;
     523             :                     }
     524         233 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     525             :                     {
     526          63 :                         ttl0 = ip0->hop_limit;
     527          63 :                         ttl1 = ip1->hop_limit;
     528          63 :                         ttl2 = ip2->hop_limit;
     529          63 :                         ttl3 = ip3->hop_limit;
     530             :                         /* by default copy the 3 most significant bits */
     531          63 :                         exp0 = ip_dscp_to_mpls_exp(
     532          63 :                             ip6_traffic_class_network_order(ip0));
     533          63 :                         exp1 = ip_dscp_to_mpls_exp(
     534          63 :                             ip6_traffic_class_network_order(ip1));
     535          63 :                         exp2 = ip_dscp_to_mpls_exp(
     536          63 :                             ip6_traffic_class_network_order(ip2));
     537          63 :                         exp3 = ip_dscp_to_mpls_exp(
     538          63 :                             ip6_traffic_class_network_order(ip3));
     539             :                     }
     540             : 
     541             :                     /* save the payload proto information in mpls opaque */
     542         233 :                     vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
     543         233 :                     vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
     544         233 :                     vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
     545         233 :                     vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
     546             :                 }
     547             :                 else
     548             :                 {
     549             :                     /*
     550             :                      * nothing to change in the ethernet header
     551             :                      */
     552          45 :                     ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
     553          45 :                     exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
     554             :                 }
     555             :                 /*
     556             :                  * These are the non-MPLS payload imposition cases.
     557             :                  * Based on the LSP mode either, for uniform, copy down the TTL
     558             :                  * and EXP from the payload or, for pipe mode, slap on the value
     559             :                  * requested from config
     560             :                  */
     561        2317 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     562             :                 {
     563         204 :                     hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
     564         204 :                     hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
     565         204 :                     hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
     566         204 :                     hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
     567             :                 }
     568             :                 else
     569             :                 {
     570        2113 :                     hdr0 = mpls_label_paint(b0, mld0);
     571        2113 :                     hdr1 = mpls_label_paint(b1, mld1);
     572        2113 :                     hdr2 = mpls_label_paint(b2, mld2);
     573        2113 :                     hdr3 = mpls_label_paint(b3, mld3);
     574             :                 }
     575             :             }
     576             :             else
     577             :             {
     578             :                 /*
     579             :                  * else, the packet to be encapped is an MPLS packet
     580             :                  * there are two cases to consider:
     581             :                  *  1 - this is an MPLS label swap at an LSP midpoint.
     582             :                  *      recognisable because mpls.first = 1. In this case the
     583             :                  *      TTL must be set to the current value -1.
     584             :                  *  2 - The MPLS packet is recursing (or being injected into)
     585             :                  *      this LSP, in which case the pipe/uniform rules apply
     586             :                  *
     587             :                  */
     588        2529 :                 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
     589             :                 {
     590             :                     /*
     591             :                      * The first label to be imposed on the packet. this is a
     592             :                      * label swap.in which case we stashed the TTL and EXP bits
     593             :                      * in the packet in the lookup node
     594             :                      */
     595         894 :                     ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
     596             : 
     597         894 :                     ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
     598         894 :                     exp0 = vnet_buffer(b0)->mpls.exp;
     599         894 :                     hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
     600             :                 }
     601             :                 else
     602             :                 {
     603             :                     /*
     604             :                      * not the first label. implying we are recusring down a
     605             :                      * chain of output labels. Each layer is considered a new
     606             :                      * LSP - hence the TTL/EXP are pipe/uniform handled
     607             :                      */
     608        1635 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     609             :                     {
     610         126 :                         hdr0 = vlib_buffer_get_current(b0);
     611         126 :                         ttl0 = ((u8*)hdr0)[3];
     612         126 :                         exp0 = ((u8*)hdr0)[2] & 0xe;
     613         126 :                         hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
     614             :                     }
     615             :                     else
     616             :                     {
     617        1509 :                         hdr0 = mpls_label_paint(b0, mld0);
     618             :                     }
     619             :                 }
     620        2529 :                 if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
     621             :                 {
     622         894 :                     ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
     623             : 
     624         894 :                     ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
     625         894 :                     exp1 = vnet_buffer(b1)->mpls.exp;
     626         894 :                     hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
     627             :                 }
     628             :                 else
     629             :                 {
     630        1635 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     631             :                     {
     632         126 :                         hdr1 = vlib_buffer_get_current(b1);
     633         126 :                         ttl1 = ((u8*)hdr1)[3];
     634         126 :                         exp1 = ((u8*)hdr1)[2] & 0xe;
     635         126 :                         hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
     636             :                     }
     637             :                     else
     638             :                     {
     639        1509 :                         hdr1 = mpls_label_paint(b1, mld1);
     640             :                     }
     641             :                 }
     642        2529 :                 if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
     643             :                 {
     644         894 :                     ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
     645             : 
     646         894 :                     ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
     647         894 :                     exp2 = vnet_buffer(b2)->mpls.exp;
     648         894 :                     hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
     649             :                 }
     650             :                 else
     651             :                 {
     652        1635 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     653             :                     {
     654         126 :                         hdr2 = vlib_buffer_get_current(b2);
     655         126 :                         ttl2 = ((u8*)hdr2)[3];
     656         126 :                         exp2 = ((u8*)hdr2)[2] & 0xe;
     657         126 :                         hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
     658             :                     }
     659             :                     else
     660             :                     {
     661        1509 :                         hdr2 = mpls_label_paint(b2, mld2);
     662             :                     }
     663             :                 }
     664        2529 :                 if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
     665             :                 {
     666         894 :                     ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
     667             : 
     668         894 :                     ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
     669         894 :                     exp3 = vnet_buffer(b3)->mpls.exp;
     670         894 :                     hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
     671             :                 }
     672             :                 else
     673             :                 {
     674        1635 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     675             :                     {
     676         126 :                         hdr3 = vlib_buffer_get_current(b3);
     677         126 :                         ttl3 = ((u8*)hdr3)[3];
     678         126 :                         exp3 = ((u8*)hdr3)[2] & 0xe;
     679         126 :                         hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
     680             :                     }
     681             :                     else
     682             :                     {
     683        1509 :                         hdr3 = mpls_label_paint(b3, mld3);
     684             :                     }
     685             :                 }
     686             : 
     687        2529 :                 vnet_buffer(b0)->mpls.first = 0;
     688        2529 :                 vnet_buffer(b1)->mpls.first = 0;
     689        2529 :                 vnet_buffer(b2)->mpls.first = 0;
     690        2529 :                 vnet_buffer(b3)->mpls.first = 0;
     691             :             }
     692             : 
     693        4846 :             next0 = mld0->mld_dpo.dpoi_next_node;
     694        4846 :             next1 = mld1->mld_dpo.dpoi_next_node;
     695        4846 :             next2 = mld2->mld_dpo.dpoi_next_node;
     696        4846 :             next3 = mld3->mld_dpo.dpoi_next_node;
     697             : 
     698        4846 :             vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
     699        4846 :             vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
     700        4846 :             vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
     701        4846 :             vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
     702             : 
     703        4846 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     704             :             {
     705             :                 mpls_label_imposition_trace_t *tr =
     706        4846 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
     707        4846 :                 tr->hdr = *hdr0;
     708        4846 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     709             :                 {
     710         393 :                     tr->ttl = ttl0;
     711         393 :                     tr->exp = exp0;
     712             :                 }
     713             :                 else
     714             :                 {
     715        4453 :                     tr->ttl = tr->exp = 0;
     716             :                 }
     717             :             }
     718        4846 :             if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
     719             :             {
     720             :                 mpls_label_imposition_trace_t *tr =
     721        4846 :                     vlib_add_trace (vm, node, b1, sizeof (*tr));
     722        4846 :                 tr->hdr = *hdr1;
     723        4846 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     724             :                 {
     725         393 :                     tr->ttl = ttl1;
     726         393 :                     tr->exp = exp1;
     727             :                 }
     728             :                 else
     729             :                 {
     730        4453 :                     tr->ttl = tr->exp = 0;
     731             :                 }
     732             :             }
     733        4846 :             if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
     734             :             {
     735             :                 mpls_label_imposition_trace_t *tr =
     736        4846 :                     vlib_add_trace (vm, node, b2, sizeof (*tr));
     737        4846 :                 tr->hdr = *hdr2;
     738        4846 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     739             :                 {
     740         393 :                     tr->ttl = ttl2;
     741         393 :                     tr->exp = exp2;
     742             :                 }
     743             :                 else
     744             :                 {
     745        4453 :                     tr->ttl = tr->exp = 0;
     746             :                 }
     747             :             }
     748        4846 :             if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
     749             :             {
     750             :                 mpls_label_imposition_trace_t *tr =
     751        4846 :                     vlib_add_trace (vm, node, b3, sizeof (*tr));
     752        4846 :                 tr->hdr = *hdr3;
     753        4846 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     754             :                 {
     755         393 :                     tr->ttl = ttl3;
     756         393 :                     tr->exp = exp3;
     757             :                 }
     758             :                 else
     759             :                 {
     760        4453 :                     tr->ttl = tr->exp = 0;
     761             :                 }
     762             :             }
     763             : 
     764        4846 :             vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
     765             :                                             n_left_to_next,
     766             :                                             bi0, bi1, bi2, bi3,
     767             :                                             next0, next1, next2, next3);
     768             :         }
     769             : 
     770         695 :         while (n_left_from > 0 && n_left_to_next > 0)
     771             :         {
     772             :             mpls_unicast_header_t *hdr0;
     773             :             mpls_label_dpo_t *mld0;
     774             :             vlib_buffer_t * b0;
     775             :             u32 bi0, mldi0;
     776             :             u8 ttl0, exp0;
     777             :             u32 next0;
     778             : 
     779         524 :             bi0 = from[0];
     780         524 :             to_next[0] = bi0;
     781         524 :             from += 1;
     782         524 :             to_next += 1;
     783         524 :             n_left_from -= 1;
     784         524 :             n_left_to_next -= 1;
     785             : 
     786         524 :             b0 = vlib_get_buffer (vm, bi0);
     787             : 
     788             :             /* dst lookup was done by ip4 lookup */
     789         524 :             mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
     790         524 :             mld0 = mpls_label_dpo_get(mldi0);
     791             : 
     792         524 :             if (DPO_PROTO_MPLS != dproto)
     793             :             {
     794         274 :                 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
     795             : 
     796         274 :                 if (DPO_PROTO_IP4 == dproto)
     797             :                 {
     798             :                     /*
     799             :                      * decrement the TTL on ingress to the LSP
     800             :                      */
     801         216 :                     ip4_header_t * ip0 = vlib_buffer_get_current(b0);
     802         216 :                     if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
     803             :                     {
     804             :                         u32 checksum0;
     805             : 
     806         171 :                         checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
     807         171 :                         checksum0 += checksum0 >= 0xffff;
     808             : 
     809         171 :                         ip0->checksum = checksum0;
     810         171 :                         ip0->ttl -= 1;
     811             :                     }
     812         216 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     813             :                     {
     814          10 :                         ttl0 = ip0->ttl;
     815          10 :                         exp0 = ip_dscp_to_mpls_exp(ip0->tos);
     816             :                     }
     817             : 
     818             :                     /* save the payload proto information in mpls opaque */
     819         216 :                     vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
     820             :                 }
     821          58 :                 else if (DPO_PROTO_IP6 == dproto)
     822             :                 {
     823             :                     /*
     824             :                      * decrement the TTL on ingress to the LSP
     825             :                      */
     826          32 :                     ip6_header_t * ip0 = vlib_buffer_get_current(b0);
     827             : 
     828          32 :                     if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
     829             :                     {
     830          32 :                         ip0->hop_limit -= 1;
     831             :                     }
     832          32 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     833             :                     {
     834           5 :                         ttl0 = ip0->hop_limit;
     835           5 :                         exp0 = ip_dscp_to_mpls_exp(
     836           5 :                             ip6_traffic_class_network_order(ip0));
     837             :                     }
     838             : 
     839             :                     /* save the payload proto information in mpls opaque */
     840          32 :                     vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
     841             :                 }
     842             :                 else
     843             :                 {
     844             :                     /*
     845             :                      * nothing to change in the ethernet header
     846             :                      */
     847          26 :                     ttl0 = MPLS_LABEL_DEFAULT_TTL;
     848          26 :                     exp0 = MPLS_LABEL_DEFAULT_EXP;
     849             :                 }
     850             : 
     851             :                 /*
     852             :                  * These are the non-MPLS payload imposition cases.
     853             :                  * Based on the LSP mode either, for uniform, copy down the TTL
     854             :                  * from the payload or, for pipe mode, slap on the value
     855             :                  * requested from config
     856             :                  */
     857         274 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     858             :                 {
     859          23 :                     hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
     860             :                 }
     861             :                 else
     862             :                 {
     863         251 :                     hdr0 = mpls_label_paint(b0, mld0);
     864             :                 }
     865             :             }
     866             :             else
     867             :             {
     868         250 :                 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
     869             :                 {
     870          95 :                     ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
     871             : 
     872          95 :                     ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
     873          95 :                     exp0 = vnet_buffer(b0)->mpls.exp;
     874          95 :                     hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
     875             :                 }
     876             :                 else
     877             :                 {
     878         155 :                     if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     879             :                     {
     880          10 :                         hdr0 = vlib_buffer_get_current(b0);
     881          10 :                         ttl0 = ((u8*)hdr0)[3];
     882          10 :                         exp0 = ((u8*)hdr0)[2] & 0xe;
     883          10 :                         hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
     884             :                     }
     885             :                     else
     886             :                     {
     887         145 :                         hdr0 = mpls_label_paint(b0, mld0);
     888             :                     }
     889             :                 }
     890             : 
     891         250 :                 vnet_buffer(b0)->mpls.first = 0;
     892             :             }
     893             : 
     894         524 :             next0 = mld0->mld_dpo.dpoi_next_node;
     895         524 :             vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
     896             : 
     897         524 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     898             :             {
     899             :                 mpls_label_imposition_trace_t *tr =
     900         524 :                     vlib_add_trace (vm, node, b0, sizeof (*tr));
     901         524 :                 tr->hdr = *hdr0;
     902         524 :                 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
     903             :                 {
     904          38 :                     tr->ttl = ttl0;
     905          38 :                     tr->exp = exp0;
     906             :                 }
     907             :                 else
     908             :                 {
     909         486 :                     tr->ttl = tr->exp = 0;
     910             :                 }
     911             :            }
     912             : 
     913         524 :             vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
     914             :                                             n_left_to_next, bi0, next0);
     915             :         }
     916         171 :         vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     917             :     }
     918         171 :     return from_frame->n_vectors;
     919             : }
     920             : 
     921             : static u8 *
     922       10574 : format_mpls_label_imposition_trace (u8 * s, va_list * args)
     923             : {
     924       10574 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     925       10574 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     926             :     mpls_label_imposition_trace_t * t;
     927             :     mpls_unicast_header_t hdr;
     928             :     u32 indent;
     929             : 
     930       10574 :     t = va_arg (*args, mpls_label_imposition_trace_t *);
     931       10574 :     indent = format_get_indent (s);
     932       10574 :     hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
     933             : 
     934       10574 :     s = format (s, "%Umpls-header:%U",
     935             :                 format_white_space, indent,
     936             :                 format_mpls_header, hdr);
     937       10574 :     return (s);
     938             : }
     939             : 
     940        2315 : VLIB_NODE_FN (mpls_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
     941             :                                  vlib_node_runtime_t * node,
     942             :                                  vlib_frame_t * frame)
     943             : {
     944          79 :     return (mpls_label_imposition_inline(vm, node, frame,
     945             :                                          DPO_PROTO_MPLS,
     946             :                                          MPLS_LABEL_DPO_FLAG_NONE));
     947             : }
     948             : 
     949      178120 : VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
     950             :     .name = "mpls-label-imposition-pipe",
     951             :     .vector_size = sizeof (u32),
     952             : 
     953             :     .format_trace = format_mpls_label_imposition_trace,
     954             :     .n_next_nodes = 1,
     955             :     .next_nodes = {
     956             :         [0] = "mpls-drop",
     957             :     }
     958             : };
     959             : 
     960        2288 : VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
     961             :                                 vlib_node_runtime_t * node,
     962             :                                 vlib_frame_t * frame)
     963             : {
     964          52 :     return (mpls_label_imposition_inline(vm, node, frame,
     965             :                                          DPO_PROTO_IP4,
     966             :                                          MPLS_LABEL_DPO_FLAG_NONE));
     967             : }
     968             : 
     969      178120 : VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node) = {
     970             :     .name = "ip4-mpls-label-imposition-pipe",
     971             :     .vector_size = sizeof (u32),
     972             : 
     973             :     .format_trace = format_mpls_label_imposition_trace,
     974             :     .n_next_nodes = 1,
     975             :     .next_nodes = {
     976             :         [0] = "ip4-drop",
     977             :     }
     978             : };
     979             : 
     980        2245 : VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
     981             :                                 vlib_node_runtime_t * node,
     982             :                                 vlib_frame_t * frame)
     983             : {
     984           9 :     return (mpls_label_imposition_inline(vm, node, frame,
     985             :                                          DPO_PROTO_IP6,
     986             :                                          MPLS_LABEL_DPO_FLAG_NONE));
     987             : }
     988             : 
     989      178120 : VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
     990             :     .name = "ip6-mpls-label-imposition-pipe",
     991             :     .vector_size = sizeof (u32),
     992             : 
     993             :     .format_trace = format_mpls_label_imposition_trace,
     994             :     .n_next_nodes = 1,
     995             :     .next_nodes = {
     996             :         [0] = "ip6-drop",
     997             :     }
     998             : };
     999             : 
    1000        2240 : VLIB_NODE_FN (ethernet_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
    1001             :                                      vlib_node_runtime_t * node,
    1002             :                                      vlib_frame_t * frame)
    1003             : {
    1004           4 :     return (mpls_label_imposition_inline(vm, node, frame,
    1005             :                                          DPO_PROTO_ETHERNET,
    1006             :                                          MPLS_LABEL_DPO_FLAG_NONE));
    1007             : }
    1008             : 
    1009      178120 : VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
    1010             :     .name = "ethernet-mpls-label-imposition-pipe",
    1011             :     .vector_size = sizeof (u32),
    1012             : 
    1013             :     .format_trace = format_mpls_label_imposition_trace,
    1014             :     .n_next_nodes = 1,
    1015             :     .next_nodes = {
    1016             :         [0] = "error-drop",
    1017             :     }
    1018             : };
    1019             : 
    1020        2242 : VLIB_NODE_FN (mpls_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
    1021             :                                     vlib_node_runtime_t * node,
    1022             :                                     vlib_frame_t * frame)
    1023             : {
    1024           6 :     return (mpls_label_imposition_inline(vm, node, frame,
    1025             :                                          DPO_PROTO_MPLS,
    1026             :                                          MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
    1027             : }
    1028             : 
    1029      178120 : VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
    1030             :     .name = "mpls-label-imposition-uniform",
    1031             :     .vector_size = sizeof (u32),
    1032             : 
    1033             :     .format_trace = format_mpls_label_imposition_trace,
    1034             :     .n_next_nodes = 1,
    1035             :     .next_nodes = {
    1036             :         [0] = "mpls-drop",
    1037             :     }
    1038             : };
    1039             : 
    1040        2238 : VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
    1041             :                                    vlib_node_runtime_t * node,
    1042             :                                    vlib_frame_t * frame)
    1043             : {
    1044           2 :     return (mpls_label_imposition_inline(vm, node, frame,
    1045             :                                          DPO_PROTO_IP4,
    1046             :                                          MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
    1047             : }
    1048             : 
    1049      178120 : VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
    1050             :     .name = "ip4-mpls-label-imposition-uniform",
    1051             :     .vector_size = sizeof (u32),
    1052             : 
    1053             :     .format_trace = format_mpls_label_imposition_trace,
    1054             :     .n_next_nodes = 1,
    1055             :     .next_nodes = {
    1056             :         [0] = "ip4-drop",
    1057             :     }
    1058             : };
    1059             : 
    1060        2238 : VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
    1061             :                                    vlib_node_runtime_t * node,
    1062             :                                    vlib_frame_t * frame)
    1063             : {
    1064           2 :     return (mpls_label_imposition_inline(vm, node, frame,
    1065             :                                          DPO_PROTO_IP6,
    1066             :                                          MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
    1067             : }
    1068             : 
    1069      178120 : VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
    1070             :     .name = "ip6-mpls-label-imposition-uniform",
    1071             :     .vector_size = sizeof (u32),
    1072             : 
    1073             :     .format_trace = format_mpls_label_imposition_trace,
    1074             :     .n_next_nodes = 1,
    1075             :     .next_nodes = {
    1076             :         [0] = "ip6-drop",
    1077             :     }
    1078             : };
    1079             : 
    1080        2238 : VLIB_NODE_FN (ethernet_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
    1081             :                                         vlib_node_runtime_t * node,
    1082             :                                         vlib_frame_t * frame)
    1083             : {
    1084           2 :     return (mpls_label_imposition_inline(vm, node, frame,
    1085             :                                          DPO_PROTO_ETHERNET,
    1086             :                                          MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
    1087             : }
    1088             : 
    1089      178120 : VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
    1090             :     .name = "ethernet-mpls-label-imposition-uniform",
    1091             :     .vector_size = sizeof (u32),
    1092             : 
    1093             :     .format_trace = format_mpls_label_imposition_trace,
    1094             :     .n_next_nodes = 1,
    1095             :     .next_nodes = {
    1096             :         [0] = "error-drop",
    1097             :     }
    1098             : };
    1099             : 
    1100             : 
    1101        2249 : VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
    1102             :                                                vlib_node_runtime_t * node,
    1103             :                                                vlib_frame_t * frame)
    1104             : {
    1105          13 :     return (mpls_label_imposition_inline(vm, node, frame,
    1106             :                                          DPO_PROTO_IP4,
    1107             :                                          MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
    1108             : }
    1109             : 
    1110      178120 : VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
    1111             :     .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
    1112             :     .vector_size = sizeof (u32),
    1113             : 
    1114             :     .format_trace = format_mpls_label_imposition_trace,
    1115             :     .n_next_nodes = 1,
    1116             :     .next_nodes = {
    1117             :         [0] = "ip4-drop",
    1118             :     }
    1119             : };
    1120             : 
    1121        2236 : VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
    1122             :                                                vlib_node_runtime_t * node,
    1123             :                                                vlib_frame_t * frame)
    1124             : {
    1125           0 :     return (mpls_label_imposition_inline(vm, node, frame,
    1126             :                                          DPO_PROTO_IP6,
    1127             :                                          MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
    1128             : }
    1129             : 
    1130      178120 : VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
    1131             :     .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
    1132             :     .vector_size = sizeof (u32),
    1133             : 
    1134             :     .format_trace = format_mpls_label_imposition_trace,
    1135             :     .n_next_nodes = 1,
    1136             :     .next_nodes = {
    1137             :         [0] = "ip6-drop",
    1138             :     }
    1139             : };
    1140             : 
    1141        2238 : VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
    1142             :                                                   vlib_node_runtime_t * node,
    1143             :                                                   vlib_frame_t * frame)
    1144             : {
    1145           2 :     return (mpls_label_imposition_inline(vm, node, frame,
    1146             :                                          DPO_PROTO_IP4,
    1147             :                                          (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
    1148             :                                           MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
    1149             : }
    1150             : 
    1151      178120 : VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
    1152             :     .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
    1153             :     .vector_size = sizeof (u32),
    1154             : 
    1155             :     .format_trace = format_mpls_label_imposition_trace,
    1156             :     .n_next_nodes = 1,
    1157             :     .next_nodes = {
    1158             :         [0] = "ip4-drop",
    1159             :     }
    1160             : };
    1161             : 
    1162        2236 : VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
    1163             :                                                   vlib_node_runtime_t * node,
    1164             :                                                   vlib_frame_t * frame)
    1165             : {
    1166           0 :     return (mpls_label_imposition_inline(vm, node, frame,
    1167             :                                          DPO_PROTO_IP6,
    1168             :                                          (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
    1169             :                                           MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
    1170             : }
    1171             : 
    1172      178120 : VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
    1173             :     .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
    1174             :     .vector_size = sizeof (u32),
    1175             : 
    1176             :     .format_trace = format_mpls_label_imposition_trace,
    1177             :     .n_next_nodes = 1,
    1178             :     .next_nodes = {
    1179             :         [0] = "ip6-drop",
    1180             :     }
    1181             : };
    1182             : 
    1183             : 
    1184             : #ifndef CLIB_MARCH_VARIANT
    1185             : static void
    1186           0 : mpls_label_dpo_mem_show (void)
    1187             : {
    1188           0 :     fib_show_memory_usage("MPLS label",
    1189           0 :                           pool_elts(mpls_label_dpo_pool),
    1190           0 :                           pool_len(mpls_label_dpo_pool),
    1191             :                           sizeof(mpls_label_dpo_t));
    1192           0 : }
    1193             : 
    1194             : /**
    1195             :  * Interpose a label DPO. used in the FIB unit tests
    1196             :  */
    1197             : static void
    1198          14 : mpls_label_interpose (const dpo_id_t *original,
    1199             :                       const dpo_id_t *parent,
    1200             :                       dpo_id_t *clone)
    1201             : {
    1202             :     mpls_label_dpo_t *mld, *mld_clone;
    1203             : 
    1204          14 :     mld_clone = mpls_label_dpo_alloc();
    1205          14 :     mld = mpls_label_dpo_get(original->dpoi_index);
    1206             : 
    1207          14 :     mld_clone->mld_locks = 0;
    1208          14 :     clib_memcpy_fast(&mld_clone->mld_hdr,
    1209          14 :                 &mld->mld_hdr,
    1210             :                 sizeof(mld_clone->mld_hdr));
    1211          14 :     mld_clone->mld_payload_proto = mld->mld_payload_proto;
    1212          14 :     mld_clone->mld_n_labels = mld->mld_n_labels;
    1213          14 :     mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
    1214             : 
    1215          14 :     dpo_stack(mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
    1216          14 :               mld_clone->mld_payload_proto,
    1217             :               &mld_clone->mld_dpo,
    1218             :               parent);
    1219             : 
    1220          14 :     dpo_set(clone,
    1221          14 :             mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
    1222          14 :             mld_clone->mld_payload_proto,
    1223             :             mpls_label_dpo_get_index(mld_clone));
    1224          14 : }
    1225             : 
    1226             : static u16
    1227           0 : mpls_label_dpo_get_mtu (const dpo_id_t *dpo)
    1228             : {
    1229             :     mpls_label_dpo_t *mld;
    1230             : 
    1231           0 :     mld = mpls_label_dpo_get(dpo->dpoi_index);
    1232             : 
    1233             :     /* return the parent's MTU minus the amount of header
    1234             :      * this DPO imposes */
    1235           0 :     return (dpo_get_mtu (&mld->mld_dpo) - sizeof(mpls_label_t) * mld->mld_n_labels);
    1236             : }
    1237             : 
    1238             : const static dpo_vft_t mld_vft = {
    1239             :     .dv_lock = mpls_label_dpo_lock,
    1240             :     .dv_unlock = mpls_label_dpo_unlock,
    1241             :     .dv_format = format_mpls_label_dpo,
    1242             :     .dv_mem_show = mpls_label_dpo_mem_show,
    1243             :     .dv_mk_interpose = mpls_label_interpose,
    1244             :     .dv_get_mtu = mpls_label_dpo_get_mtu,
    1245             : };
    1246             : 
    1247             : const static char* const mpls_label_imp_pipe_ip4_nodes[] =
    1248             : {
    1249             :     "ip4-mpls-label-imposition-pipe",
    1250             :     NULL,
    1251             : };
    1252             : const static char* const mpls_label_imp_pipe_ip6_nodes[] =
    1253             : {
    1254             :     "ip6-mpls-label-imposition-pipe",
    1255             :     NULL,
    1256             : };
    1257             : const static char* const mpls_label_imp_pipe_mpls_nodes[] =
    1258             : {
    1259             :     "mpls-label-imposition-pipe",
    1260             :     NULL,
    1261             : };
    1262             : const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
    1263             : {
    1264             :     "ethernet-mpls-label-imposition-pipe",
    1265             :     NULL,
    1266             : };
    1267             : 
    1268             : const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
    1269             : {
    1270             :     [DPO_PROTO_IP4]  = mpls_label_imp_pipe_ip4_nodes,
    1271             :     [DPO_PROTO_IP6]  = mpls_label_imp_pipe_ip6_nodes,
    1272             :     [DPO_PROTO_MPLS] = mpls_label_imp_pipe_mpls_nodes,
    1273             :     [DPO_PROTO_ETHERNET] = mpls_label_imp_pipe_ethernet_nodes,
    1274             : };
    1275             : 
    1276             : const static char* const mpls_label_imp_uniform_ip4_nodes[] =
    1277             : {
    1278             :     "ip4-mpls-label-imposition-uniform",
    1279             :     NULL,
    1280             : };
    1281             : const static char* const mpls_label_imp_uniform_ip6_nodes[] =
    1282             : {
    1283             :     "ip6-mpls-label-imposition-uniform",
    1284             :     NULL,
    1285             : };
    1286             : const static char* const mpls_label_imp_uniform_mpls_nodes[] =
    1287             : {
    1288             :     "mpls-label-imposition-uniform",
    1289             :     NULL,
    1290             : };
    1291             : const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
    1292             : {
    1293             :     "ethernet-mpls-label-imposition-uniform",
    1294             :     NULL,
    1295             : };
    1296             : 
    1297             : const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
    1298             : {
    1299             :     [DPO_PROTO_IP4]  = mpls_label_imp_uniform_ip4_nodes,
    1300             :     [DPO_PROTO_IP6]  = mpls_label_imp_uniform_ip6_nodes,
    1301             :     [DPO_PROTO_MPLS] = mpls_label_imp_uniform_mpls_nodes,
    1302             :     [DPO_PROTO_ETHERNET] = mpls_label_imp_uniform_ethernet_nodes,
    1303             : };
    1304             : 
    1305             : const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[] =
    1306             : {
    1307             :     "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
    1308             :     NULL,
    1309             : };
    1310             : const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[] =
    1311             : {
    1312             :     "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
    1313             :     NULL,
    1314             : };
    1315             : 
    1316             : const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
    1317             : {
    1318             :     [DPO_PROTO_IP4]  = mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes,
    1319             :     [DPO_PROTO_IP6]  = mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes,
    1320             : };
    1321             : 
    1322             : const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[] =
    1323             : {
    1324             :     "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
    1325             :     NULL,
    1326             : };
    1327             : const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[] =
    1328             : {
    1329             :     "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
    1330             :     NULL,
    1331             : };
    1332             : 
    1333             : const static char* const * const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
    1334             : {
    1335             :     [DPO_PROTO_IP4]  = mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes,
    1336             :     [DPO_PROTO_IP6]  = mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes,
    1337             : };
    1338             : 
    1339             : void
    1340         559 : mpls_label_dpo_module_init (void)
    1341             : {
    1342         559 :     mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE] =
    1343         559 :         dpo_register_new_type(&mld_vft,
    1344             :                               mpls_label_imp_pipe_nodes);
    1345         559 :     mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
    1346         559 :         dpo_register_new_type(&mld_vft,
    1347             :                               mpls_label_imp_pipe_no_ip_tll_decr_nodes);
    1348         559 :     mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE] =
    1349         559 :         dpo_register_new_type(&mld_vft,
    1350             :                               mpls_label_imp_uniform_nodes);
    1351             :     mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
    1352         559 :                          MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
    1353         559 :         dpo_register_new_type(&mld_vft,
    1354             :                               mpls_label_imp_uniform_no_ip_tll_decr_nodes);
    1355         559 : }
    1356             : 
    1357             : dpo_type_t
    1358          65 : mpls_label_dpo_get_type (mpls_label_dpo_flags_t flags)
    1359             : {
    1360          65 :     return (mpls_label_dpo_types[flags]);
    1361             : }
    1362             : #endif /* CLIB_MARCH_VARIANT */
    1363             : 
    1364             : // clang-format on

Generated by: LCOV version 1.14