LCOV - code coverage report
Current view: top level - plugins/lacp - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 62 65 95.4 %
Date: 2023-10-26 01:39:38 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 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             : #define _GNU_SOURCE
      17             : #include <vnet/bonding/node.h>
      18             : #include <vnet/ethernet/packet.h>
      19             : #include <lacp/node.h>
      20             : 
      21             : lacp_state_struct lacp_state_array[] = {
      22             : #define _(b, s, n) {.bit = b, .str = #s, },
      23             :   foreach_lacp_state_flag
      24             : #undef _
      25             :   {.str = NULL}
      26             : };
      27             : 
      28             : /** \file
      29             : 
      30             :     2 x LACP graph nodes: an "interior" node to process
      31             :     incoming announcements, and a "process" node to periodically
      32             :     send announcements.
      33             : 
      34             :     The interior node is neither pipelined nor dual-looped, because
      35             :     it would be very unusual to see more than one LACP packet in
      36             :     a given input frame. So, it's a very simple / straightforward
      37             :     example.
      38             : */
      39             : 
      40             : /*
      41             :  * packet counter strings
      42             :  * Dump these counters via the "show error" CLI command
      43             :  */
      44             : static char *lacp_error_strings[] = {
      45             : #define _(sym,string) string,
      46             :   foreach_lacp_error
      47             : #undef _
      48             : };
      49             : 
      50             : /*
      51             :  * We actually send all lacp pkts to the "error" node after scanning
      52             :  * them, so the graph node has only one next-index. The "error-drop"
      53             :  * node automatically bumps our per-node packet counters for us.
      54             :  */
      55             : typedef enum
      56             : {
      57             :   LACP_INPUT_NEXT_NORMAL,
      58             :   LACP_INPUT_N_NEXT,
      59             : } lacp_next_t;
      60             : 
      61             : /*
      62             :  * Process a frame of lacp packets
      63             :  * Expect 1 packet / frame
      64             :  */
      65             : static uword
      66          17 : lacp_node_fn (vlib_main_t * vm,
      67             :               vlib_node_runtime_t * node, vlib_frame_t * frame)
      68             : {
      69             :   u32 n_left_from, *from;
      70             :   lacp_input_trace_t *t0;
      71             : 
      72          17 :   from = vlib_frame_vector_args (frame);        /* array of buffer indices */
      73          17 :   n_left_from = frame->n_vectors;    /* number of buffer indices */
      74             : 
      75          41 :   while (n_left_from > 0)
      76             :     {
      77             :       u32 bi0;
      78             :       vlib_buffer_t *b0;
      79             :       u32 next0, error0;
      80             : 
      81          24 :       bi0 = from[0];
      82          24 :       b0 = vlib_get_buffer (vm, bi0);
      83             : 
      84          24 :       next0 = LACP_INPUT_NEXT_NORMAL;
      85             : 
      86             :       /* scan this lacp pkt. error0 is the counter index to bump */
      87          24 :       error0 = lacp_input (vm, b0, bi0);
      88          24 :       b0->error = node->errors[error0];
      89             : 
      90             :       /* If this pkt is traced, snapshoot the data */
      91          24 :       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
      92             :         {
      93             :           int len;
      94             : 
      95           1 :           t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
      96           1 :           len = (b0->current_length < sizeof (t0->pkt))
      97           1 :             ? b0->current_length : sizeof (t0->pkt);
      98           1 :           t0->len = len;
      99           1 :           t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     100           1 :           clib_memcpy_fast (&t0->pkt, vlib_buffer_get_current (b0), len);
     101             :         }
     102             :       /* push this pkt to the next graph node, always error-drop */
     103          24 :       vlib_set_next_frame_buffer (vm, node, next0, bi0);
     104             : 
     105          24 :       from += 1;
     106          24 :       n_left_from -= 1;
     107             :     }
     108             : 
     109          17 :   return frame->n_vectors;
     110             : }
     111             : 
     112             : /*
     113             :  * lacp input graph node declaration
     114             :  */
     115             : /* *INDENT-OFF* */
     116      111212 : VLIB_REGISTER_NODE (lacp_input_node, static) = {
     117             :   .function = lacp_node_fn,
     118             :   .name = "lacp-input",
     119             :   .vector_size = sizeof (u32),
     120             :   .type = VLIB_NODE_TYPE_INTERNAL,
     121             : 
     122             :   .n_errors = LACP_N_ERROR,
     123             :   .error_strings = lacp_error_strings,
     124             : 
     125             :   .format_trace = lacp_input_format_trace,
     126             : 
     127             :   .n_next_nodes = LACP_INPUT_N_NEXT,
     128             :   .next_nodes = {
     129             :     [LACP_INPUT_NEXT_NORMAL] = "error-drop",
     130             :   },
     131             : };
     132             : /* *INDENT-ON* */
     133             : 
     134             : static void
     135           4 : lacp_elog_start_event (void)
     136             : {
     137           4 :   lacp_main_t *lm = &lacp_main;
     138             :   /* *INDENT-OFF* */
     139             :   ELOG_TYPE_DECLARE (e) =
     140             :     {
     141             :       .format = "Starting LACP process, interface count = %d",
     142             :       .format_args = "i4",
     143             :     };
     144             :   /* *INDENT-ON* */
     145             :   struct
     146             :   {
     147             :     u32 count;
     148             :   } *ed;
     149             : 
     150           4 :   ed = ELOG_DATA (&vlib_global_main.elog_main, e);
     151           4 :   ed->count = lm->lacp_int;
     152           4 : }
     153             : 
     154             : static void
     155           4 : lacp_elog_stop_event (void)
     156             : {
     157           4 :   lacp_main_t *lm = &lacp_main;
     158             :   /* *INDENT-OFF* */
     159             :   ELOG_TYPE_DECLARE (e) =
     160             :     {
     161             :       .format = "Stopping LACP process, interface count = %d",
     162             :       .format_args = "i4",
     163             :     };
     164             :   /* *INDENT-ON* */
     165             :   struct
     166             :   {
     167             :     u32 count;
     168             :   } *ed;
     169             : 
     170           4 :   ed = ELOG_DATA (&vlib_global_main.elog_main, e);
     171           4 :   ed->count = lm->lacp_int;
     172           4 : }
     173             : 
     174             : /*
     175             :  * lacp periodic function
     176             :  */
     177             : static uword
     178           3 : lacp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
     179             : {
     180           3 :   lacp_main_t *lm = &lacp_main;
     181             :   f64 poll_time_remaining;
     182           3 :   uword event_type, *event_data = 0;
     183             : 
     184           3 :   ethernet_register_input_type (vm, ETHERNET_TYPE_SLOW_PROTOCOLS /* LACP */ ,
     185             :                                 lacp_input_node.index);
     186             : 
     187           3 :   poll_time_remaining = 0.2;
     188             :   while (1)
     189             :     {
     190          38 :       if (lm->lacp_int > 0)
     191             :         poll_time_remaining =
     192          31 :           vlib_process_wait_for_event_or_clock (vm, poll_time_remaining);
     193             :       else
     194           7 :         vlib_process_wait_for_event (vm);
     195             : 
     196          35 :       event_type = vlib_process_get_events (vm, &event_data);
     197          35 :       switch (event_type)
     198             :         {
     199          27 :         case ~0:                /* no events => timeout */
     200          27 :           break;
     201           4 :         case LACP_PROCESS_EVENT_START:
     202           4 :           poll_time_remaining = 0.2;
     203           4 :           lacp_elog_start_event ();
     204           4 :           break;
     205           4 :         case LACP_PROCESS_EVENT_STOP:
     206           4 :           if (lm->lacp_int == 0)
     207             :             {
     208           4 :               poll_time_remaining = SECS_IN_A_DAY;
     209           4 :               lacp_elog_stop_event ();
     210             :             }
     211           4 :           break;
     212           0 :         default:
     213           0 :           clib_warning ("BUG: event type 0x%wx", event_type);
     214           0 :           break;
     215             :         }
     216          35 :       vec_reset_length (event_data);
     217             : 
     218          35 :       if (vlib_process_suspend_time_is_zero (poll_time_remaining))
     219             :         {
     220          15 :           lacp_periodic (vm);
     221          15 :           poll_time_remaining = 0.2;
     222             :         }
     223             :     }
     224             : 
     225             :   return 0;
     226             : }
     227             : 
     228             : void
     229          11 : lacp_create_periodic_process (void)
     230             : {
     231          11 :   lacp_main_t *lm = &lacp_main;
     232             : 
     233             :   /* Already created the process node? */
     234          11 :   if (lm->lacp_process_node_index > 0)
     235           8 :     return;
     236             : 
     237             :   /* No, create it now and make a note of the node index */
     238           3 :   lm->lacp_process_node_index =
     239           3 :     vlib_process_create (lm->vlib_main, "lacp-process", lacp_process,
     240             :                          16 /* log2_n_stack_bytes */ );
     241             : }
     242             : 
     243             : /*
     244             :  * fd.io coding-style-patch-verification: ON
     245             :  *
     246             :  * Local Variables:
     247             :  * eval: (c-set-style "gnu")
     248             :  * End:
     249             :  */

Generated by: LCOV version 1.14