LCOV - code coverage report
Current view: top level - vnet/srv6 - sr_pt_node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 3 88 3.4 %
Date: 2023-07-05 22:20:52 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: Apache-2.0
       2             :  * Copyright(c) 2022 Cisco Systems, Inc.
       3             :  */
       4             : 
       5             : #include <vnet/fib/ip6_fib.h>
       6             : #include <vnet/dpo/load_balance.h>
       7             : #include <vnet/l2/feat_bitmap.h>
       8             : #include <vnet/fib/fib_table.h>
       9             : #include <vnet/srv6/sr.h>
      10             : #include <vnet/srv6/sr_pt.h>
      11             : 
      12             : /**
      13             :  * @brief PT node trace
      14             :  */
      15             : typedef struct
      16             : {
      17             :   u32 iface;
      18             :   u16 id;
      19             :   u8 load;
      20             :   timestamp_64_t t64;
      21             :   u8 tts_template;
      22             :   u8 tts;
      23             :   u8 behavior;
      24             : } pt_trace_t;
      25             : 
      26             : static u8 *
      27           0 : format_pt_trace (u8 *s, va_list *args)
      28             : {
      29           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      30           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      31           0 :   pt_trace_t *t = va_arg (*args, pt_trace_t *);
      32           0 :   switch (t->behavior)
      33             :     {
      34           0 :     case PT_BEHAVIOR_MID:
      35           0 :       s = format (
      36             :         s,
      37             :         "Behavior Midpoint, outgoing interface %U, outgoing interface id %u, "
      38             :         "outgoing interface load %u, t64_sec %u, t64_nsec %u, tts_template "
      39             :         "%u, tts %u",
      40           0 :         format_vnet_sw_if_index_name, vnet_get_main (), t->iface, t->id,
      41           0 :         t->load, clib_host_to_net_u32 (t->t64.sec),
      42           0 :         clib_host_to_net_u32 (t->t64.nsec), t->tts_template, t->tts);
      43           0 :       break;
      44           0 :     default:
      45           0 :       break;
      46             :     }
      47           0 :   return s;
      48             : }
      49             : 
      50             : static_always_inline void
      51           0 : pt_midpoint_processing (vlib_main_t *vm, vlib_node_runtime_t *node,
      52             :                         vlib_buffer_t *b0, ip6_header_t *ip0,
      53             :                         sr_pt_iface_t *ls, timestamp_64_t t64)
      54             : {
      55             :   ip6_hop_by_hop_header_t *hbh;
      56             :   ip6_hop_by_hop_option_t *hbh_opt;
      57             :   ip6_hop_by_hop_option_pt_t *hbh_opt_pt;
      58             : 
      59           0 :   if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
      60             :     {
      61           0 :       hbh = (void *) (ip0 + 1);
      62           0 :       hbh_opt = (void *) (hbh + 1);
      63           0 :       if (hbh_opt->type == IP6_HBH_PT_TYPE)
      64             :         {
      65           0 :           hbh_opt_pt = (void *) (hbh_opt + 1);
      66           0 :           clib_memcpy_fast (&hbh_opt_pt->cmd_stack[1],
      67           0 :                             &hbh_opt_pt->cmd_stack[0], 33);
      68           0 :           hbh_opt_pt->cmd_stack[0].oif_oil =
      69           0 :             clib_host_to_net_u16 (ls->id << 4);
      70           0 :           hbh_opt_pt->cmd_stack[0].oif_oil |= ls->egress_load;
      71           0 :           switch (ls->tts_template)
      72             :             {
      73           0 :             case SR_PT_TTS_TEMPLATE_0:
      74           0 :               hbh_opt_pt->cmd_stack[0].tts =
      75           0 :                 t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_0;
      76           0 :               break;
      77           0 :             case SR_PT_TTS_TEMPLATE_1:
      78           0 :               hbh_opt_pt->cmd_stack[0].tts =
      79           0 :                 t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_1;
      80           0 :               break;
      81           0 :             case SR_PT_TTS_TEMPLATE_2:
      82           0 :               hbh_opt_pt->cmd_stack[0].tts =
      83           0 :                 t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_2;
      84           0 :               break;
      85           0 :             case SR_PT_TTS_TEMPLATE_3:
      86           0 :               hbh_opt_pt->cmd_stack[0].tts =
      87           0 :                 t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_0;
      88           0 :               break;
      89           0 :             default:
      90           0 :               break;
      91             :             }
      92           0 :         }
      93             :     }
      94           0 :   return;
      95             : }
      96             : 
      97         559 : VLIB_NODE_FN (sr_pt_node)
      98             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
      99             : {
     100             :   u32 n_left_from, next_index, *from, *to_next;
     101           0 :   from = vlib_frame_vector_args (from_frame);
     102           0 :   n_left_from = from_frame->n_vectors;
     103           0 :   next_index = node->cached_next_index;
     104           0 :   u8 pt_behavior = ~(u8) 0;
     105           0 :   sr_pt_iface_t *ls = 0;
     106           0 :   while (n_left_from > 0)
     107             :     {
     108             :       u32 n_left_to_next;
     109           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     110             : 
     111             :       // Single loop for potentially the last three packets
     112           0 :       while (n_left_from > 0 && n_left_to_next > 0)
     113             :         {
     114             :           u32 bi0;
     115             :           u32 iface;
     116             :           vlib_buffer_t *b0;
     117           0 :           u32 next0 = 0;
     118             :           ethernet_header_t *en0;
     119           0 :           ip6_header_t *ip0 = 0;
     120           0 :           bi0 = from[0];
     121           0 :           to_next[0] = bi0;
     122           0 :           from += 1;
     123           0 :           to_next += 1;
     124           0 :           n_left_from -= 1;
     125           0 :           n_left_to_next -= 1;
     126           0 :           timestamp_64_t t64 = {};
     127             : 
     128           0 :           b0 = vlib_get_buffer (vm, bi0);
     129           0 :           iface = vnet_buffer (b0)->sw_if_index[VLIB_TX];
     130           0 :           ls = sr_pt_find_iface (iface);
     131           0 :           if (ls)
     132             :             {
     133           0 :               en0 = vlib_buffer_get_current (b0);
     134           0 :               ip0 = (void *) (en0 + 1);
     135           0 :               unix_time_now_nsec_fraction (&t64.sec, &t64.nsec);
     136           0 :               pt_midpoint_processing (vm, node, b0, ip0, ls, t64);
     137           0 :               pt_behavior = PT_BEHAVIOR_MID;
     138             :             }
     139           0 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     140             :             {
     141           0 :               pt_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     142           0 :               tr->iface = iface;
     143           0 :               tr->id = ls->id;
     144           0 :               tr->load = ls->egress_load;
     145           0 :               tr->tts_template = ls->tts_template;
     146           0 :               tr->t64.sec = t64.sec;
     147           0 :               tr->t64.nsec = t64.nsec;
     148           0 :               tr->tts = t64.nsec >> 20;
     149           0 :               tr->behavior = pt_behavior;
     150             :             }
     151           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
     152             :                                            n_left_to_next, bi0, next0);
     153             :         }
     154           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     155             :     }
     156             : 
     157           0 :   return from_frame->n_vectors;
     158             : }
     159             : 
     160      178120 : VLIB_REGISTER_NODE (sr_pt_node) = {
     161             :   .name = "pt",
     162             :   .vector_size = sizeof (u32),
     163             :   .format_trace = format_pt_trace,
     164             :   .type = VLIB_NODE_TYPE_INTERNAL,
     165             :   .n_errors = 0,
     166             :   .n_next_nodes = 1,
     167             :   .next_nodes = { [0] = "interface-output" },
     168             : };
     169             : 
     170       70583 : VNET_FEATURE_INIT (sr_pt_node, static) = {
     171             :   .arc_name = "ip6-output",
     172             :   .node_name = "pt",
     173             : };

Generated by: LCOV version 1.14