LCOV - code coverage report
Current view: top level - vnet/bonding - cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 269 558 48.2 %
Date: 2023-07-05 22:20:52 Functions: 25 36 69.4 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * Copyright (c) 2017 Cisco and/or its affiliates.
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at:
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  *------------------------------------------------------------------
      16             :  */
      17             : 
      18             : #include <stdint.h>
      19             : #include <vlib/vlib.h>
      20             : #include <vlib/unix/unix.h>
      21             : #include <vnet/ethernet/ethernet.h>
      22             : #include <vnet/bonding/node.h>
      23             : #include <vlib/stats/stats.h>
      24             : 
      25             : void
      26          48 : bond_disable_collecting_distributing (vlib_main_t * vm, member_if_t * mif)
      27             : {
      28          48 :   bond_main_t *bm = &bond_main;
      29             :   bond_if_t *bif;
      30             :   int i;
      31             :   uword p;
      32          48 :   u8 switching_active = 0;
      33             : 
      34          48 :   bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
      35          48 :   clib_spinlock_lock_if_init (&bif->lockp);
      36          53 :   vec_foreach_index (i, bif->active_members)
      37             :   {
      38          11 :     p = *vec_elt_at_index (bif->active_members, i);
      39          11 :     if (p == mif->sw_if_index)
      40             :       {
      41           6 :         if ((bif->mode == BOND_MODE_ACTIVE_BACKUP) && (i == 0) &&
      42           0 :             (vec_len (bif->active_members) > 1))
      43             :           /* deleting the active member for active-backup */
      44           0 :           switching_active = 1;
      45           6 :         vec_del1 (bif->active_members, i);
      46           6 :         if (mif->lacp_enabled && bif->numa_only)
      47             :           {
      48             :             /* For lacp mode, if we check it is a member on local numa node,
      49             :                bif->n_numa_members should be decreased by 1 becasue the first
      50             :                bif->n_numa_members are all members on local numa node */
      51           0 :             if (i < bif->n_numa_members)
      52             :               {
      53           0 :                 bif->n_numa_members--;
      54           0 :                 ASSERT (bif->n_numa_members >= 0);
      55             :               }
      56             :           }
      57           6 :         break;
      58             :       }
      59             :   }
      60             : 
      61             :   /* We get a new member just becoming active */
      62          48 :   if (switching_active)
      63           0 :     vlib_process_signal_event (bm->vlib_main, bond_process_node.index,
      64           0 :                                BOND_SEND_GARP_NA, bif->hw_if_index);
      65          48 :   clib_spinlock_unlock_if_init (&bif->lockp);
      66          48 : }
      67             : 
      68             : /*
      69             :  * return 1 if s2 is preferred.
      70             :  * return -1 if s1 is preferred.
      71             :  */
      72             : static int
      73           0 : bond_member_sort (void *a1, void *a2)
      74             : {
      75           0 :   u32 *s1 = a1;
      76           0 :   u32 *s2 = a2;
      77           0 :   member_if_t *mif1 = bond_get_member_by_sw_if_index (*s1);
      78           0 :   member_if_t *mif2 = bond_get_member_by_sw_if_index (*s2);
      79             :   bond_if_t *bif;
      80             : 
      81           0 :   ALWAYS_ASSERT (mif1);
      82           0 :   ALWAYS_ASSERT (mif2);
      83             :   /*
      84             :    * sort entries according to preference rules:
      85             :    * 1. biggest weight
      86             :    * 2. numa-node
      87             :    * 3. current active member (to prevent churning)
      88             :    * 4. lowest sw_if_index (for deterministic behavior)
      89             :    *
      90             :    */
      91           0 :   if (mif2->weight > mif1->weight)
      92           0 :     return 1;
      93           0 :   if (mif2->weight < mif1->weight)
      94           0 :     return -1;
      95             :   else
      96             :     {
      97           0 :       if (mif2->is_local_numa > mif1->is_local_numa)
      98           0 :         return 1;
      99           0 :       if (mif2->is_local_numa < mif1->is_local_numa)
     100           0 :         return -1;
     101             :       else
     102             :         {
     103           0 :           bif = bond_get_bond_if_by_dev_instance (mif1->bif_dev_instance);
     104             :           /* Favor the current active member to avoid churning */
     105           0 :           if (bif->active_members[0] == mif2->sw_if_index)
     106           0 :             return 1;
     107           0 :           if (bif->active_members[0] == mif1->sw_if_index)
     108           0 :             return -1;
     109             :           /* go for the tiebreaker as the last resort */
     110           0 :           if (mif1->sw_if_index > mif2->sw_if_index)
     111           0 :             return 1;
     112           0 :           if (mif1->sw_if_index < mif2->sw_if_index)
     113           0 :             return -1;
     114             :           else
     115           0 :             ASSERT (0);
     116             :         }
     117             :     }
     118           0 :   return 0;
     119             : }
     120             : 
     121             : static void
     122           0 : bond_sort_members (bond_if_t * bif)
     123             : {
     124           0 :   bond_main_t *bm = &bond_main;
     125           0 :   u32 old_active = bif->active_members[0];
     126             : 
     127           0 :   vec_sort_with_function (bif->active_members, bond_member_sort);
     128           0 :   if (old_active != bif->active_members[0])
     129           0 :     vlib_process_signal_event (bm->vlib_main, bond_process_node.index,
     130           0 :                                BOND_SEND_GARP_NA, bif->hw_if_index);
     131           0 : }
     132             : 
     133             : void
     134          14 : bond_enable_collecting_distributing (vlib_main_t * vm, member_if_t * mif)
     135             : {
     136             :   bond_if_t *bif;
     137          14 :   bond_main_t *bm = &bond_main;
     138          14 :   vnet_main_t *vnm = vnet_get_main ();
     139          14 :   vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, mif->sw_if_index);
     140             :   int i;
     141             :   uword p;
     142             : 
     143          14 :   bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
     144          14 :   clib_spinlock_lock_if_init (&bif->lockp);
     145          19 :   vec_foreach_index (i, bif->active_members)
     146             :   {
     147          13 :     p = *vec_elt_at_index (bif->active_members, i);
     148          13 :     if (p == mif->sw_if_index)
     149           8 :       goto done;
     150             :   }
     151             : 
     152           6 :   if (mif->lacp_enabled && bif->numa_only && (vm->numa_node == hw->numa_node))
     153             :     {
     154           0 :       vec_insert_elts (bif->active_members, &mif->sw_if_index, 1,
     155             :                        bif->n_numa_members);
     156           0 :       bif->n_numa_members++;
     157             :     }
     158             :   else
     159           6 :     vec_add1 (bif->active_members, mif->sw_if_index);
     160             : 
     161           6 :   mif->is_local_numa = (vm->numa_node == hw->numa_node) ? 1 : 0;
     162           6 :   if (bif->mode == BOND_MODE_ACTIVE_BACKUP)
     163             :     {
     164           0 :       if (vec_len (bif->active_members) == 1)
     165             :         /* First member becomes active? */
     166           0 :         vlib_process_signal_event (bm->vlib_main, bond_process_node.index,
     167           0 :                                    BOND_SEND_GARP_NA, bif->hw_if_index);
     168             :       else
     169           0 :         bond_sort_members (bif);
     170             :     }
     171             : 
     172           6 : done:
     173          14 :   clib_spinlock_unlock_if_init (&bif->lockp);
     174          14 : }
     175             : 
     176             : int
     177           7 : bond_dump_ifs (bond_interface_details_t ** out_bondifs)
     178             : {
     179           7 :   vnet_main_t *vnm = vnet_get_main ();
     180           7 :   bond_main_t *bm = &bond_main;
     181             :   bond_if_t *bif;
     182             :   vnet_hw_interface_t *hi;
     183           7 :   bond_interface_details_t *r_bondifs = NULL;
     184           7 :   bond_interface_details_t *bondif = NULL;
     185             : 
     186             :   /* *INDENT-OFF* */
     187          20 :   pool_foreach (bif, bm->interfaces) {
     188          13 :     vec_add2(r_bondifs, bondif, 1);
     189          13 :     clib_memset (bondif, 0, sizeof (*bondif));
     190          13 :     bondif->id = bif->id;
     191          13 :     bondif->sw_if_index = bif->sw_if_index;
     192          13 :     hi = vnet_get_hw_interface (vnm, bif->hw_if_index);
     193          13 :     clib_memcpy(bondif->interface_name, hi->name,
     194             :                 MIN (ARRAY_LEN (bondif->interface_name) - 1,
     195             :                      vec_len ((const char *) hi->name)));
     196             :     /* enforce by memset() above */
     197          13 :     ASSERT(0 == bondif->interface_name[ARRAY_LEN (bondif->interface_name) - 1]);
     198          13 :     bondif->mode = bif->mode;
     199          13 :     bondif->lb = bif->lb;
     200          13 :     bondif->numa_only = bif->numa_only;
     201          13 :     bondif->active_members = vec_len (bif->active_members);
     202          13 :     bondif->members = vec_len (bif->members);
     203             :   }
     204             :   /* *INDENT-ON* */
     205             : 
     206           7 :   *out_bondifs = r_bondifs;
     207             : 
     208           7 :   return 0;
     209             : }
     210             : 
     211             : int
     212          13 : bond_dump_member_ifs (member_interface_details_t ** out_memberifs,
     213             :                       u32 bond_sw_if_index)
     214             : {
     215          13 :   vnet_main_t *vnm = vnet_get_main ();
     216             :   bond_if_t *bif;
     217             :   vnet_hw_interface_t *hi;
     218             :   vnet_sw_interface_t *sw;
     219          13 :   member_interface_details_t *r_memberifs = NULL;
     220          13 :   member_interface_details_t *memberif = NULL;
     221          13 :   u32 *sw_if_index = NULL;
     222             :   member_if_t *mif;
     223             : 
     224          13 :   bif = bond_get_bond_if_by_sw_if_index (bond_sw_if_index);
     225          13 :   if (!bif)
     226           0 :     return 1;
     227             : 
     228          27 :   vec_foreach (sw_if_index, bif->members)
     229             :   {
     230          14 :     vec_add2 (r_memberifs, memberif, 1);
     231          14 :     clib_memset (memberif, 0, sizeof (*memberif));
     232          14 :     mif = bond_get_member_by_sw_if_index (*sw_if_index);
     233          14 :     if (mif)
     234             :       {
     235          14 :         sw = vnet_get_sw_interface (vnm, mif->sw_if_index);
     236          14 :         hi = vnet_get_hw_interface (vnm, sw->hw_if_index);
     237          14 :         clib_memcpy (memberif->interface_name, hi->name,
     238             :                      MIN (ARRAY_LEN (memberif->interface_name) - 1,
     239             :                           vec_len ((const char *) hi->name)));
     240             :         /* enforce by memset() above */
     241          14 :         ASSERT (0 ==
     242             :                 memberif->interface_name[ARRAY_LEN (memberif->interface_name)
     243             :                                          - 1]);
     244          14 :         memberif->sw_if_index = mif->sw_if_index;
     245          14 :         memberif->is_passive = mif->is_passive;
     246          14 :         memberif->is_long_timeout = mif->is_long_timeout;
     247          14 :         memberif->is_local_numa = mif->is_local_numa;
     248          14 :         memberif->weight = mif->weight;
     249             :       }
     250             :   }
     251          13 :   *out_memberifs = r_memberifs;
     252             : 
     253          13 :   return 0;
     254             : }
     255             : 
     256             : /*
     257             :  * Manage secondary mac addresses when attaching/detaching a member.
     258             :  * If adding, copy any secondary addresses from bond interface to member.
     259             :  * If deleting, delete the bond interface's secondary addresses from the
     260             :  * member.
     261             :  */
     262             : static void
     263          26 : bond_member_add_del_mac_addrs (bond_if_t * bif, u32 mif_sw_if_index,
     264             :                                u8 is_add)
     265             : {
     266          26 :   vnet_main_t *vnm = vnet_get_main ();
     267             :   ethernet_interface_t *b_ei;
     268             :   ethernet_interface_address_t *sec_mac;
     269             :   vnet_hw_interface_t *s_hwif;
     270             : 
     271          26 :   b_ei = ethernet_get_interface (&ethernet_main, bif->hw_if_index);
     272          26 :   if (!b_ei || !b_ei->secondary_addrs)
     273          22 :     return;
     274             : 
     275           4 :   s_hwif = vnet_get_sup_hw_interface (vnm, mif_sw_if_index);
     276             : 
     277          12 :   vec_foreach (sec_mac, b_ei->secondary_addrs)
     278           8 :     vnet_hw_interface_add_del_mac_address (vnm, s_hwif->hw_if_index,
     279           8 :                                            sec_mac->mac.bytes, is_add);
     280             : }
     281             : 
     282             : static void
     283          13 : bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, member_if_t * mif)
     284             : {
     285          13 :   bond_main_t *bm = &bond_main;
     286          13 :   vnet_main_t *vnm = vnet_get_main ();
     287             :   int i;
     288             :   vnet_hw_interface_t *mif_hw;
     289             : 
     290          13 :   mif_hw = vnet_get_sup_hw_interface (vnm, mif->sw_if_index);
     291             : 
     292          13 :   bif->port_number_bitmap =
     293          13 :     clib_bitmap_set (bif->port_number_bitmap,
     294          13 :                      ntohs (mif->actor_admin.port_number) - 1, 0);
     295          13 :   bm->member_by_sw_if_index[mif->sw_if_index] = 0;
     296          13 :   vec_free (mif->last_marker_pkt);
     297          13 :   vec_free (mif->last_rx_pkt);
     298          13 :   vec_foreach_index (i, bif->members)
     299             :   {
     300          13 :     uword p = *vec_elt_at_index (bif->members, i);
     301          13 :     if (p == mif->sw_if_index)
     302             :       {
     303          13 :         vec_del1 (bif->members, i);
     304          13 :         break;
     305             :       }
     306             :   }
     307             : 
     308          13 :   bond_disable_collecting_distributing (vm, mif);
     309             : 
     310          13 :   vnet_feature_enable_disable ("device-input", "bond-input",
     311             :                                mif->sw_if_index, 0, 0, 0);
     312             : 
     313             :   /* Put back the old mac */
     314          13 :   vnet_hw_interface_change_mac_address (vnm, mif_hw->hw_if_index,
     315          13 :                                         mif->persistent_hw_address);
     316             : 
     317             :   /* delete the bond's secondary/virtual mac addrs from the member */
     318          13 :   bond_member_add_del_mac_addrs (bif, mif->sw_if_index, 0 /* is_add */ );
     319             : 
     320             : 
     321          13 :   if ((bif->mode == BOND_MODE_LACP) && bm->lacp_enable_disable)
     322          11 :     (*bm->lacp_enable_disable) (vm, bif, mif, 0);
     323             : 
     324          13 :   if (bif->mode == BOND_MODE_LACP)
     325             :     {
     326          11 :       vlib_stats_remove_entry (
     327          11 :         bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state);
     328          11 :       vlib_stats_remove_entry (
     329          11 :         bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state);
     330             :     }
     331             : 
     332          13 :   pool_put (bm->neighbors, mif);
     333          13 : }
     334             : 
     335             : int
     336           9 : bond_delete_if (vlib_main_t * vm, u32 sw_if_index)
     337             : {
     338           9 :   bond_main_t *bm = &bond_main;
     339           9 :   vnet_main_t *vnm = vnet_get_main ();
     340             :   bond_if_t *bif;
     341             :   member_if_t *mif;
     342             :   vnet_hw_interface_t *hw;
     343             :   u32 *mif_sw_if_index;
     344           9 :   u32 *s_list = 0;
     345             : 
     346           9 :   hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
     347           9 :   if (hw == NULL || bond_dev_class.index != hw->dev_class_index)
     348           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
     349             : 
     350           9 :   bif = bond_get_bond_if_by_dev_instance (hw->dev_instance);
     351             : 
     352           9 :   vec_append (s_list, bif->members);
     353          16 :   vec_foreach (mif_sw_if_index, s_list)
     354             :   {
     355           7 :     mif = bond_get_member_by_sw_if_index (*mif_sw_if_index);
     356           7 :     if (mif)
     357           7 :       bond_delete_neighbor (vm, bif, mif);
     358             :   }
     359           9 :   vec_free (s_list);
     360             : 
     361             :   /* bring down the interface */
     362           9 :   vnet_hw_interface_set_flags (vnm, bif->hw_if_index, 0);
     363           9 :   vnet_sw_interface_set_flags (vnm, bif->sw_if_index, 0);
     364             : 
     365           9 :   ethernet_delete_interface (vnm, bif->hw_if_index);
     366             : 
     367           9 :   clib_bitmap_free (bif->port_number_bitmap);
     368           9 :   hash_unset (bm->bond_by_sw_if_index, bif->sw_if_index);
     369           9 :   hash_unset (bm->id_used, bif->id);
     370           9 :   clib_memset (bif, 0, sizeof (*bif));
     371           9 :   pool_put (bm->interfaces, bif);
     372             : 
     373           9 :   return 0;
     374             : }
     375             : 
     376             : void
     377           9 : bond_create_if (vlib_main_t * vm, bond_create_if_args_t * args)
     378             : {
     379           9 :   vnet_eth_interface_registration_t eir = {};
     380           9 :   bond_main_t *bm = &bond_main;
     381           9 :   vnet_main_t *vnm = vnet_get_main ();
     382             :   vnet_sw_interface_t *sw;
     383             :   bond_if_t *bif;
     384             : 
     385           9 :   if ((args->mode == BOND_MODE_LACP) && bm->lacp_plugin_loaded == 0)
     386             :     {
     387           0 :       args->rv = VNET_API_ERROR_FEATURE_DISABLED;
     388           0 :       args->error = clib_error_return (0, "LACP plugin is not loaded");
     389           0 :       return;
     390             :     }
     391           9 :   if (args->mode > BOND_MODE_LACP || args->mode < BOND_MODE_ROUND_ROBIN)
     392             :     {
     393           0 :       args->rv = VNET_API_ERROR_INVALID_ARGUMENT;
     394           0 :       args->error = clib_error_return (0, "Invalid mode");
     395           0 :       return;
     396             :     }
     397           9 :   if (args->lb > BOND_LB_L23)
     398             :     {
     399           0 :       args->rv = VNET_API_ERROR_INVALID_ARGUMENT;
     400           0 :       args->error = clib_error_return (0, "Invalid load-balance");
     401           0 :       return;
     402             :     }
     403           9 :   pool_get (bm->interfaces, bif);
     404           9 :   clib_memset (bif, 0, sizeof (*bif));
     405           9 :   bif->dev_instance = bif - bm->interfaces;
     406           9 :   bif->id = args->id;
     407           9 :   bif->lb = args->lb;
     408           9 :   bif->mode = args->mode;
     409           9 :   bif->gso = args->gso;
     410             : 
     411           9 :   if (bif->lb == BOND_LB_L2)
     412           8 :     bif->hash_func =
     413           8 :       vnet_hash_function_from_name ("hash-eth-l2", VNET_HASH_FN_TYPE_ETHERNET);
     414           1 :   else if (bif->lb == BOND_LB_L34)
     415           1 :     bif->hash_func = vnet_hash_function_from_name ("hash-eth-l34",
     416             :                                                    VNET_HASH_FN_TYPE_ETHERNET);
     417           0 :   else if (bif->lb == BOND_LB_L23)
     418           0 :     bif->hash_func = vnet_hash_function_from_name ("hash-eth-l23",
     419             :                                                    VNET_HASH_FN_TYPE_ETHERNET);
     420             : 
     421             :   // Adjust requested interface id
     422           9 :   if (bif->id == ~0)
     423           9 :     bif->id = bif->dev_instance;
     424           9 :   if (hash_get (bm->id_used, bif->id))
     425             :     {
     426           0 :       args->rv = VNET_API_ERROR_INSTANCE_IN_USE;
     427           0 :       pool_put (bm->interfaces, bif);
     428           0 :       return;
     429             :     }
     430           9 :   hash_set (bm->id_used, bif->id, 1);
     431             : 
     432             :   // Special load-balance mode used for rr and bc
     433           9 :   if (bif->mode == BOND_MODE_ROUND_ROBIN)
     434           1 :     bif->lb = BOND_LB_RR;
     435           8 :   else if (bif->mode == BOND_MODE_BROADCAST)
     436           0 :     bif->lb = BOND_LB_BC;
     437           8 :   else if (bif->mode == BOND_MODE_ACTIVE_BACKUP)
     438           0 :     bif->lb = BOND_LB_AB;
     439             : 
     440           9 :   bif->use_custom_mac = args->hw_addr_set;
     441           9 :   if (!args->hw_addr_set)
     442             :     {
     443           6 :       f64 now = vlib_time_now (vm);
     444             :       u32 rnd;
     445           6 :       rnd = (u32) (now * 1e6);
     446           6 :       rnd = random_u32 (&rnd);
     447             : 
     448           6 :       memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
     449           6 :       args->hw_addr[0] = 2;
     450           6 :       args->hw_addr[1] = 0xfe;
     451             :     }
     452           9 :   memcpy (bif->hw_address, args->hw_addr, 6);
     453             : 
     454           9 :   eir.dev_class_index = bond_dev_class.index;
     455           9 :   eir.dev_instance = bif->dev_instance;
     456           9 :   eir.address = bif->hw_address;
     457           9 :   bif->hw_if_index = vnet_eth_register_interface (vnm, &eir);
     458             : 
     459           9 :   sw = vnet_get_hw_sw_interface (vnm, bif->hw_if_index);
     460           9 :   bif->sw_if_index = sw->sw_if_index;
     461           9 :   bif->group = bif->sw_if_index;
     462           9 :   bif->numa_only = args->numa_only;
     463             : 
     464             :   /*
     465             :    * Add GSO and Checksum offload flags if GSO is enabled on Bond
     466             :    */
     467           9 :   if (args->gso)
     468             :     {
     469           0 :       vnet_hw_if_set_caps (vnm, bif->hw_if_index,
     470             :                            VNET_HW_IF_CAP_TCP_GSO |
     471             :                              VNET_HW_IF_CAP_TX_TCP_CKSUM |
     472             :                              VNET_HW_IF_CAP_TX_UDP_CKSUM);
     473             :     }
     474           9 :   if (vlib_get_thread_main ()->n_vlib_mains > 1)
     475           0 :     clib_spinlock_init (&bif->lockp);
     476             : 
     477           9 :   vnet_hw_interface_set_flags (vnm, bif->hw_if_index,
     478             :                                VNET_HW_INTERFACE_FLAG_LINK_UP);
     479             : 
     480           9 :   hash_set (bm->bond_by_sw_if_index, bif->sw_if_index, bif->dev_instance);
     481             : 
     482             :   // for return
     483           9 :   args->sw_if_index = bif->sw_if_index;
     484           9 :   args->rv = 0;
     485             : }
     486             : 
     487             : static clib_error_t *
     488           0 : bond_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
     489             :                         vlib_cli_command_t * cmd)
     490             : {
     491           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     492           0 :   bond_create_if_args_t args = { 0 };
     493           0 :   u8 mode_is_set = 0;
     494             : 
     495             :   /* Get a line of input. */
     496           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     497           0 :     return clib_error_return (0, "Missing required arguments.");
     498             : 
     499           0 :   args.id = ~0;
     500           0 :   args.mode = -1;
     501           0 :   args.lb = BOND_LB_L2;
     502           0 :   args.rv = -1;
     503           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     504             :     {
     505           0 :       if (unformat (line_input, "mode %U", unformat_bond_mode, &args.mode))
     506           0 :         mode_is_set = 1;
     507           0 :       else if (((args.mode == BOND_MODE_LACP) || (args.mode == BOND_MODE_XOR))
     508           0 :                && unformat (line_input, "load-balance %U",
     509             :                             unformat_bond_load_balance, &args.lb))
     510             :         ;
     511           0 :       else if (unformat (line_input, "hw-addr %U",
     512             :                          unformat_ethernet_address, args.hw_addr))
     513           0 :         args.hw_addr_set = 1;
     514           0 :       else if (unformat (line_input, "id %u", &args.id))
     515             :         ;
     516           0 :       else if (unformat (line_input, "gso"))
     517           0 :         args.gso = 1;
     518           0 :       else if (unformat (line_input, "numa-only"))
     519             :         {
     520           0 :           if (args.mode == BOND_MODE_LACP)
     521           0 :             args.numa_only = 1;
     522             :           else
     523             :             {
     524           0 :               unformat_free (line_input);
     525           0 :               return clib_error_return (
     526             :                 0, "Only lacp mode supports numa-only so far!");
     527             :             }
     528             :         }
     529             :       else
     530             :         {
     531           0 :           unformat_free (line_input);
     532           0 :           return clib_error_return (0, "unknown input `%U'",
     533             :                                     format_unformat_error, input);
     534             :         }
     535             :     }
     536           0 :   unformat_free (line_input);
     537             : 
     538           0 :   if (mode_is_set == 0)
     539           0 :     return clib_error_return (0, "Missing bond mode");
     540             : 
     541           0 :   bond_create_if (vm, &args);
     542             : 
     543           0 :   if (!args.rv)
     544           0 :     vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
     545             :                      vnet_get_main (), args.sw_if_index);
     546             : 
     547           0 :   return args.error;
     548             : }
     549             : 
     550             : /* *INDENT-OFF* */
     551      272887 : VLIB_CLI_COMMAND (bond_create_command, static) = {
     552             :   .path = "create bond",
     553             :   .short_help = "create bond mode {round-robin | active-backup | broadcast | "
     554             :     "{lacp | xor} [load-balance { l2 | l23 | l34 } [numa-only]]} "
     555             :     "[hw-addr <mac-address>] [id <if-id>] [gso]",
     556             :   .function = bond_create_command_fn,
     557             : };
     558             : /* *INDENT-ON* */
     559             : 
     560             : static clib_error_t *
     561           0 : bond_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
     562             :                         vlib_cli_command_t * cmd)
     563             : {
     564           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     565           0 :   u32 sw_if_index = ~0;
     566           0 :   vnet_main_t *vnm = vnet_get_main ();
     567             :   int rv;
     568             : 
     569             :   /* Get a line of input. */
     570           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     571           0 :     return clib_error_return (0, "Missing <interface>");
     572             : 
     573           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     574             :     {
     575           0 :       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
     576             :         ;
     577           0 :       else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
     578             :                          vnm, &sw_if_index))
     579             :         ;
     580             :       else
     581           0 :         return clib_error_return (0, "unknown input `%U'",
     582             :                                   format_unformat_error, input);
     583             :     }
     584           0 :   unformat_free (line_input);
     585             : 
     586           0 :   if (sw_if_index == ~0)
     587           0 :     return clib_error_return (0,
     588             :                               "please specify interface name or sw_if_index");
     589             : 
     590           0 :   rv = bond_delete_if (vm, sw_if_index);
     591           0 :   if (rv == VNET_API_ERROR_INVALID_SW_IF_INDEX)
     592           0 :     return clib_error_return (0, "not a bond interface");
     593           0 :   else if (rv != 0)
     594           0 :     return clib_error_return (0, "error on deleting bond interface");
     595             : 
     596           0 :   return 0;
     597             : }
     598             : 
     599             : /* *INDENT-OFF* */
     600      272887 : VLIB_CLI_COMMAND (bond_delete__command, static) =
     601             : {
     602             :   .path = "delete bond",
     603             :   .short_help = "delete bond {<interface> | sw_if_index <sw_idx>}",
     604             :   .function = bond_delete_command_fn,
     605             : };
     606             : /* *INDENT-ON* */
     607             : 
     608             : void
     609          13 : bond_add_member (vlib_main_t * vm, bond_add_member_args_t * args)
     610             : {
     611          13 :   bond_main_t *bm = &bond_main;
     612          13 :   vnet_main_t *vnm = vnet_get_main ();
     613             :   bond_if_t *bif;
     614             :   member_if_t *mif;
     615          13 :   vnet_interface_main_t *im = &vnm->interface_main;
     616             :   vnet_hw_interface_t *bif_hw, *mif_hw;
     617             :   vnet_sw_interface_t *sw;
     618             :   u32 thread_index;
     619             :   u32 mif_if_index;
     620             : 
     621          13 :   bif = bond_get_bond_if_by_sw_if_index (args->group);
     622          13 :   if (!bif)
     623             :     {
     624           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     625           0 :       args->error = clib_error_return (0, "bond interface not found");
     626           0 :       return;
     627             :     }
     628             :   // make sure the interface is not already added as member
     629          13 :   if (bond_get_member_by_sw_if_index (args->member))
     630             :     {
     631           0 :       args->rv = VNET_API_ERROR_VALUE_EXIST;
     632           0 :       args->error = clib_error_return
     633             :         (0, "interface was already added as member");
     634           0 :       return;
     635             :     }
     636          13 :   mif_hw = vnet_get_sup_hw_interface (vnm, args->member);
     637          13 :   if (mif_hw->dev_class_index == bond_dev_class.index)
     638             :     {
     639           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     640           0 :       args->error =
     641           0 :         clib_error_return (0, "bond interface cannot be added as member");
     642           0 :       return;
     643             :     }
     644          13 :   if (bif->gso && !(mif_hw->caps & VNET_HW_IF_CAP_TCP_GSO))
     645             :     {
     646           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     647           0 :       args->error =
     648           0 :         clib_error_return (0, "member interface is not gso capable");
     649           0 :       return;
     650             :     }
     651          13 :   if (bif->mode == BOND_MODE_LACP)
     652             :     {
     653             :       u32 actor_idx, partner_idx;
     654             : 
     655          11 :       actor_idx = vlib_stats_add_gauge ("/if/lacp/%u/%u/state",
     656             :                                         bif->sw_if_index, args->member);
     657          11 :       if (actor_idx == ~0)
     658             :         {
     659           0 :           args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     660           0 :           return;
     661             :         }
     662             : 
     663          11 :       partner_idx = vlib_stats_add_gauge ("/if/lacp/%u/%u/partner-state",
     664             :                                           bif->sw_if_index, args->member);
     665          11 :       if (partner_idx == ~0)
     666             :         {
     667           0 :           vlib_stats_remove_entry (actor_idx);
     668           0 :           args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     669           0 :           return;
     670             :         }
     671             : 
     672          11 :       vec_validate (bm->stats, bif->sw_if_index);
     673          11 :       vec_validate (bm->stats[bif->sw_if_index], args->member);
     674          11 :       bm->stats[bif->sw_if_index][args->member].actor_state = actor_idx;
     675          11 :       bm->stats[bif->sw_if_index][args->member].partner_state = partner_idx;
     676             :     }
     677             : 
     678          13 :   pool_get (bm->neighbors, mif);
     679          13 :   clib_memset (mif, 0, sizeof (*mif));
     680          13 :   sw = pool_elt_at_index (im->sw_interfaces, args->member);
     681             :   /* port_enabled is both admin up and hw link up */
     682          13 :   mif->port_enabled = vnet_sw_interface_is_up (vnm, sw->sw_if_index);
     683          13 :   mif->sw_if_index = sw->sw_if_index;
     684          13 :   mif->hw_if_index = sw->hw_if_index;
     685          13 :   mif->packet_template_index = (u8) ~ 0;
     686          13 :   mif->is_passive = args->is_passive;
     687          13 :   mif->group = args->group;
     688          13 :   mif->bif_dev_instance = bif->dev_instance;
     689          13 :   mif->mode = bif->mode;
     690             : 
     691          13 :   mif->is_long_timeout = args->is_long_timeout;
     692          13 :   if (args->is_long_timeout)
     693           0 :     mif->ttl_in_seconds = LACP_LONG_TIMOUT_TIME;
     694             :   else
     695          13 :     mif->ttl_in_seconds = LACP_SHORT_TIMOUT_TIME;
     696             : 
     697          13 :   vec_validate_aligned (bm->member_by_sw_if_index, mif->sw_if_index,
     698             :                         CLIB_CACHE_LINE_BYTES);
     699             :   /*
     700             :    * mif - bm->neighbors may be 0
     701             :    * Left shift it by 1 bit to distinguish the valid entry that we actually
     702             :    * store from the null entries
     703             :    */
     704          13 :   bm->member_by_sw_if_index[mif->sw_if_index] =
     705          13 :     (uword) (((mif - bm->neighbors) << 1) | 1);
     706          13 :   vec_add1 (bif->members, mif->sw_if_index);
     707             : 
     708          13 :   mif_hw = vnet_get_sup_hw_interface (vnm, mif->sw_if_index);
     709             : 
     710             :   /* Save the old mac */
     711          13 :   memcpy (mif->persistent_hw_address, mif_hw->hw_address, 6);
     712          13 :   bif_hw = vnet_get_sup_hw_interface (vnm, bif->sw_if_index);
     713          13 :   if (bif->use_custom_mac)
     714             :     {
     715           5 :       vnet_hw_interface_change_mac_address (vnm, mif_hw->hw_if_index,
     716           5 :                                             bif->hw_address);
     717             :     }
     718             :   else
     719             :     {
     720             :       // bond interface gets the mac address from the first member
     721           8 :       if (vec_len (bif->members) == 1)
     722             :         {
     723           4 :           memcpy (bif->hw_address, mif_hw->hw_address, 6);
     724           4 :           vnet_hw_interface_change_mac_address (vnm, bif_hw->hw_if_index,
     725           4 :                                                 mif_hw->hw_address);
     726             :         }
     727             :       else
     728             :         {
     729             :           // subsequent members gets the mac address of the bond interface
     730           4 :           vnet_hw_interface_change_mac_address (vnm, mif_hw->hw_if_index,
     731           4 :                                                 bif->hw_address);
     732             :         }
     733             :     }
     734             : 
     735             :   /* if there are secondary/virtual mac addrs, propagate to the member */
     736          13 :   bond_member_add_del_mac_addrs (bif, mif->sw_if_index, 1 /* is_add */ );
     737             : 
     738          13 :   if (bif_hw->l2_if_count)
     739           0 :     ethernet_set_flags (vnm, mif_hw->hw_if_index,
     740             :                         ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
     741             :   else
     742          13 :     ethernet_set_flags (vnm, mif_hw->hw_if_index,
     743             :                         /*ETHERNET_INTERFACE_FLAG_DEFAULT_L3 */ 0);
     744             : 
     745          13 :   if (bif->mode == BOND_MODE_LACP)
     746             :     {
     747          11 :       if (bm->lacp_enable_disable)
     748          11 :         (*bm->lacp_enable_disable) (vm, bif, mif, 1);
     749             :     }
     750           2 :   else if (mif->port_enabled)
     751             :     {
     752           2 :       bond_enable_collecting_distributing (vm, mif);
     753             :     }
     754             : 
     755          26 :   vec_foreach_index (thread_index, bm->per_thread_data)
     756             :   {
     757          13 :     bond_per_thread_data_t *ptd = vec_elt_at_index (bm->per_thread_data,
     758             :                                                     thread_index);
     759             : 
     760          13 :     vec_validate_aligned (ptd->per_port_queue, vec_len (bif->members) - 1,
     761             :                           CLIB_CACHE_LINE_BYTES);
     762             : 
     763          35 :     vec_foreach_index (mif_if_index, ptd->per_port_queue)
     764             :     {
     765          22 :       ptd->per_port_queue[mif_if_index].n_buffers = 0;
     766             :     }
     767             :   }
     768             : 
     769          26 :   args->rv = vnet_feature_enable_disable ("device-input", "bond-input",
     770          13 :                                           mif->sw_if_index, 1, 0, 0);
     771             : 
     772          13 :   if (args->rv)
     773             :     {
     774           0 :       args->error =
     775           0 :         clib_error_return (0,
     776             :                            "Error encountered on input feature arc enable");
     777             :     }
     778             : }
     779             : 
     780             : static clib_error_t *
     781           0 : add_member_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
     782             :                                  vlib_cli_command_t * cmd)
     783             : {
     784           0 :   bond_add_member_args_t args = { 0 };
     785           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     786           0 :   vnet_main_t *vnm = vnet_get_main ();
     787             : 
     788             :   /* Get a line of input. */
     789           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     790           0 :     return clib_error_return (0, "Missing required arguments.");
     791             : 
     792           0 :   args.member = ~0;
     793           0 :   args.group = ~0;
     794           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     795             :     {
     796           0 :       if (unformat (line_input, "%U %U",
     797             :                     unformat_vnet_sw_interface, vnm, &args.group,
     798             :                     unformat_vnet_sw_interface, vnm, &args.member))
     799             :         ;
     800           0 :       else if (unformat (line_input, "passive"))
     801           0 :         args.is_passive = 1;
     802           0 :       else if (unformat (line_input, "long-timeout"))
     803           0 :         args.is_long_timeout = 1;
     804             :       else
     805             :         {
     806           0 :           args.error = clib_error_return (0, "unknown input `%U'",
     807             :                                           format_unformat_error, input);
     808           0 :           break;
     809             :         }
     810             :     }
     811           0 :   unformat_free (line_input);
     812             : 
     813           0 :   if (args.error)
     814           0 :     return args.error;
     815           0 :   if (args.group == ~0)
     816           0 :     return clib_error_return (0, "Missing bond interface");
     817           0 :   if (args.member == ~0)
     818           0 :     return clib_error_return (0,
     819             :                               "please specify valid member interface name");
     820             : 
     821           0 :   bond_add_member (vm, &args);
     822             : 
     823           0 :   return args.error;
     824             : }
     825             : 
     826             : /* *INDENT-OFF* */
     827      272887 : VLIB_CLI_COMMAND (add_member_interface_command, static) = {
     828             :   .path = "bond add",
     829             :   .short_help = "bond add <BondEthernetx> <member-interface> "
     830             :                 "[passive] [long-timeout]",
     831             :   .function = add_member_interface_command_fn,
     832             : };
     833             : /* *INDENT-ON* */
     834             : 
     835             : void
     836           6 : bond_detach_member (vlib_main_t * vm, bond_detach_member_args_t * args)
     837             : {
     838             :   bond_if_t *bif;
     839             :   member_if_t *mif;
     840             : 
     841           6 :   mif = bond_get_member_by_sw_if_index (args->member);
     842           6 :   if (!mif)
     843             :     {
     844           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
     845           0 :       args->error = clib_error_return (0, "interface was not a member");
     846           0 :       return;
     847             :     }
     848           6 :   bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
     849           6 :   bond_delete_neighbor (vm, bif, mif);
     850             : }
     851             : 
     852             : static clib_error_t *
     853           0 : detach_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
     854             :                              vlib_cli_command_t * cmd)
     855             : {
     856           0 :   bond_detach_member_args_t args = { 0 };
     857           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     858           0 :   vnet_main_t *vnm = vnet_get_main ();
     859             : 
     860             :   /* Get a line of input. */
     861           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     862           0 :     return clib_error_return (0, "Missing required arguments.");
     863             : 
     864           0 :   args.member = ~0;
     865           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     866             :     {
     867           0 :       if (unformat (line_input, "%U",
     868             :                     unformat_vnet_sw_interface, vnm, &args.member))
     869             :         ;
     870             :       else
     871             :         {
     872           0 :           args.error = clib_error_return (0, "unknown input `%U'",
     873             :                                           format_unformat_error, input);
     874           0 :           break;
     875             :         }
     876             :     }
     877           0 :   unformat_free (line_input);
     878             : 
     879           0 :   if (args.error)
     880           0 :     return args.error;
     881           0 :   if (args.member == ~0)
     882           0 :     return clib_error_return (0,
     883             :                               "please specify valid member interface name");
     884             : 
     885           0 :   bond_detach_member (vm, &args);
     886             : 
     887           0 :   return args.error;
     888             : }
     889             : 
     890             : /* *INDENT-OFF* */
     891      272887 : VLIB_CLI_COMMAND (detach_interface_command, static) = {
     892             :   .path = "bond del",
     893             :   .short_help = "bond del <member-interface>",
     894             :   .function = detach_interface_command_fn,
     895             : };
     896             : /* *INDENT-ON* */
     897             : 
     898             : static void
     899           0 : show_bond (vlib_main_t * vm)
     900             : {
     901           0 :   bond_main_t *bm = &bond_main;
     902             :   bond_if_t *bif;
     903             : 
     904           0 :   vlib_cli_output (vm, "%-16s %-12s %-13s %-13s %-14s %s",
     905             :                    "interface name", "sw_if_index", "mode",
     906             :                    "load balance", "active members", "members");
     907             : 
     908             :   /* *INDENT-OFF* */
     909           0 :   pool_foreach (bif, bm->interfaces)
     910             :    {
     911           0 :     vlib_cli_output (vm, "%-16U %-12d %-13U %-13U %-14u %u",
     912             :                      format_bond_interface_name, bif->dev_instance,
     913           0 :                      bif->sw_if_index, format_bond_mode, bif->mode,
     914           0 :                      format_bond_load_balance, bif->lb,
     915           0 :                      vec_len (bif->active_members), vec_len (bif->members));
     916             :   }
     917             :   /* *INDENT-ON* */
     918           0 : }
     919             : 
     920             : static void
     921           0 : show_bond_details (vlib_main_t * vm)
     922             : {
     923           0 :   bond_main_t *bm = &bond_main;
     924             :   bond_if_t *bif;
     925             :   u32 *sw_if_index;
     926             : 
     927             :   /* *INDENT-OFF* */
     928           0 :   pool_foreach (bif, bm->interfaces)
     929             :    {
     930           0 :     vlib_cli_output (vm, "%U", format_bond_interface_name, bif->dev_instance);
     931           0 :     vlib_cli_output (vm, "  mode: %U",
     932           0 :                      format_bond_mode, bif->mode);
     933           0 :     vlib_cli_output (vm, "  load balance: %U",
     934           0 :                      format_bond_load_balance, bif->lb);
     935           0 :     if (bif->gso)
     936           0 :       vlib_cli_output (vm, "  gso enable");
     937           0 :     if (bif->mode == BOND_MODE_ROUND_ROBIN)
     938           0 :       vlib_cli_output (vm, "  last xmit member index: %u",
     939             :                        bif->lb_rr_last_index);
     940           0 :     vlib_cli_output (vm, "  number of active members: %d",
     941           0 :                      vec_len (bif->active_members));
     942           0 :     vec_foreach (sw_if_index, bif->active_members)
     943             :       {
     944           0 :         vlib_cli_output (vm, "    %U", format_vnet_sw_if_index_name,
     945             :                          vnet_get_main (), *sw_if_index);
     946           0 :         if (bif->mode == BOND_MODE_ACTIVE_BACKUP)
     947             :           {
     948           0 :             member_if_t *mif = bond_get_member_by_sw_if_index (*sw_if_index);
     949           0 :             if (mif)
     950           0 :               vlib_cli_output (vm, "      weight: %u, is_local_numa: %u, "
     951             :                                "sw_if_index: %u", mif->weight,
     952           0 :                                mif->is_local_numa, mif->sw_if_index);
     953             :           }
     954             :       }
     955           0 :     vlib_cli_output (vm, "  number of members: %d", vec_len (bif->members));
     956           0 :     vec_foreach (sw_if_index, bif->members)
     957             :       {
     958           0 :         vlib_cli_output (vm, "    %U", format_vnet_sw_if_index_name,
     959             :                          vnet_get_main (), *sw_if_index);
     960             :       }
     961           0 :     vlib_cli_output (vm, "  device instance: %d", bif->dev_instance);
     962           0 :     vlib_cli_output (vm, "  interface id: %d", bif->id);
     963           0 :     vlib_cli_output (vm, "  sw_if_index: %d", bif->sw_if_index);
     964           0 :     vlib_cli_output (vm, "  hw_if_index: %d", bif->hw_if_index);
     965             :   }
     966             :   /* *INDENT-ON* */
     967           0 : }
     968             : 
     969             : static clib_error_t *
     970           0 : show_bond_fn (vlib_main_t * vm, unformat_input_t * input,
     971             :               vlib_cli_command_t * cmd)
     972             : {
     973           0 :   u8 details = 0;
     974             : 
     975           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     976             :     {
     977           0 :       if (unformat (input, "details"))
     978           0 :         details = 1;
     979             :       else
     980             :         {
     981           0 :           return clib_error_return (0, "unknown input `%U'",
     982             :                                     format_unformat_error, input);
     983             :         }
     984             :     }
     985             : 
     986           0 :   if (details)
     987           0 :     show_bond_details (vm);
     988             :   else
     989           0 :     show_bond (vm);
     990             : 
     991           0 :   return 0;
     992             : }
     993             : 
     994             : /* *INDENT-OFF* */
     995      272887 : VLIB_CLI_COMMAND (show_bond_command, static) = {
     996             :   .path = "show bond",
     997             :   .short_help = "show bond [details]",
     998             :   .function = show_bond_fn,
     999             : };
    1000             : /* *INDENT-ON* */
    1001             : 
    1002             : void
    1003           0 : bond_set_intf_weight (vlib_main_t * vm, bond_set_intf_weight_args_t * args)
    1004             : {
    1005             :   member_if_t *mif;
    1006             :   bond_if_t *bif;
    1007             :   vnet_main_t *vnm;
    1008             :   u32 old_weight;
    1009             : 
    1010           0 :   mif = bond_get_member_by_sw_if_index (args->sw_if_index);
    1011           0 :   if (!mif)
    1012             :     {
    1013           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
    1014           0 :       args->error = clib_error_return (0, "Interface not a member");
    1015           0 :       return;
    1016             :     }
    1017           0 :   bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
    1018           0 :   if (!bif)
    1019             :     {
    1020           0 :       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
    1021           0 :       args->error = clib_error_return (0, "bond interface not found");
    1022           0 :       return;
    1023             :     }
    1024           0 :   if (bif->mode != BOND_MODE_ACTIVE_BACKUP)
    1025             :     {
    1026           0 :       args->rv = VNET_API_ERROR_INVALID_ARGUMENT;
    1027           0 :       args->error =
    1028           0 :         clib_error_return (0, "Weight valid for active-backup only");
    1029           0 :       return;
    1030             :     }
    1031             : 
    1032           0 :   old_weight = mif->weight;
    1033           0 :   mif->weight = args->weight;
    1034           0 :   vnm = vnet_get_main ();
    1035             :   /*
    1036             :    * No need to sort the list if the affected member is not up (not in active
    1037             :    * member set), active member count is 1, or the current member is already the
    1038             :    * primary member and new weight > old weight.
    1039             :    */
    1040           0 :   if (!vnet_sw_interface_is_up (vnm, mif->sw_if_index) ||
    1041           0 :       (vec_len (bif->active_members) == 1) ||
    1042           0 :       ((bif->active_members[0] == mif->sw_if_index) &&
    1043           0 :        (mif->weight >= old_weight)))
    1044           0 :     return;
    1045             : 
    1046           0 :   bond_sort_members (bif);
    1047             : }
    1048             : 
    1049             : static clib_error_t *
    1050           0 : bond_set_intf_cmd (vlib_main_t * vm, unformat_input_t * input,
    1051             :                    vlib_cli_command_t * cmd)
    1052             : {
    1053           0 :   bond_set_intf_weight_args_t args = { 0 };
    1054           0 :   u32 sw_if_index = (u32) ~ 0;
    1055           0 :   unformat_input_t _line_input, *line_input = &_line_input;
    1056           0 :   vnet_main_t *vnm = vnet_get_main ();
    1057           0 :   u8 weight_enter = 0;
    1058           0 :   u32 weight = 0;
    1059             : 
    1060             :   /* Get a line of input. */
    1061           0 :   if (!unformat_user (input, unformat_line_input, line_input))
    1062           0 :     return clib_error_return (0, "Missing required arguments.");
    1063             : 
    1064           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    1065             :     {
    1066           0 :       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
    1067             :         ;
    1068           0 :       else if (unformat (line_input, "%U", unformat_vnet_sw_interface, vnm,
    1069             :                          &sw_if_index))
    1070             :         ;
    1071           0 :       else if (unformat (line_input, "weight %u", &weight))
    1072           0 :         weight_enter = 1;
    1073             :       else
    1074             :         {
    1075           0 :           clib_error_return (0, "unknown input `%U'", format_unformat_error,
    1076             :                              input);
    1077           0 :           break;
    1078             :         }
    1079             :     }
    1080             : 
    1081           0 :   unformat_free (line_input);
    1082           0 :   if (sw_if_index == (u32) ~ 0)
    1083             :     {
    1084           0 :       args.rv = VNET_API_ERROR_INVALID_INTERFACE;
    1085           0 :       clib_error_return (0, "Interface name is invalid!");
    1086             :     }
    1087           0 :   if (weight_enter == 0)
    1088             :     {
    1089           0 :       args.rv = VNET_API_ERROR_INVALID_ARGUMENT;
    1090           0 :       clib_error_return (0, "weight missing");
    1091             :     }
    1092             : 
    1093           0 :   args.sw_if_index = sw_if_index;
    1094           0 :   args.weight = weight;
    1095           0 :   bond_set_intf_weight (vm, &args);
    1096             : 
    1097           0 :   return args.error;
    1098             : }
    1099             : 
    1100             : /* *INDENT-OFF* */
    1101      272887 : VLIB_CLI_COMMAND(set_interface_bond_cmd, static) = {
    1102             :   .path = "set interface bond",
    1103             :   .short_help = "set interface bond <interface> | sw_if_index <idx>"
    1104             :                 " weight <value>",
    1105             :   .function = bond_set_intf_cmd,
    1106             : };
    1107             : /* *INDENT-ON* */
    1108             : 
    1109             : clib_error_t *
    1110         559 : bond_cli_init (vlib_main_t * vm)
    1111             : {
    1112         559 :   bond_main_t *bm = &bond_main;
    1113             : 
    1114         559 :   bm->vlib_main = vm;
    1115         559 :   bm->vnet_main = vnet_get_main ();
    1116         559 :   vec_validate_aligned (bm->member_by_sw_if_index, 1, CLIB_CACHE_LINE_BYTES);
    1117         559 :   vec_validate_aligned (bm->per_thread_data,
    1118             :                         vlib_get_thread_main ()->n_vlib_mains - 1,
    1119             :                         CLIB_CACHE_LINE_BYTES);
    1120             : 
    1121         559 :   return 0;
    1122             : }
    1123             : 
    1124       30799 : VLIB_INIT_FUNCTION (bond_cli_init);
    1125             : 
    1126             : /*
    1127             :  * fd.io coding-style-patch-verification: ON
    1128             :  *
    1129             :  * Local Variables:
    1130             :  * eval: (c-set-style "gnu")
    1131             :  * End:
    1132             :  */

Generated by: LCOV version 1.14