LCOV - code coverage report
Current view: top level - vnet/feature - feature.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 193 328 58.8 %
Date: 2023-10-26 01:39:38 Functions: 20 25 80.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/feature/feature.h>
      17             : 
      18             : vnet_feature_main_t feature_main;
      19             : 
      20             : typedef struct vnet_feature_upd_registration_t_
      21             : {
      22             :   vnet_feature_update_cb_t cb;
      23             :   void *data;
      24             : } vnet_feature_upd_registration_t;
      25             : 
      26             : static vnet_feature_upd_registration_t *regs;
      27             : 
      28             : void
      29        1150 : vnet_feature_register (vnet_feature_update_cb_t cb, void *data)
      30             : {
      31             :   vnet_feature_upd_registration_t *reg;
      32             : 
      33        1150 :   vec_add2 (regs, reg, 1);
      34             : 
      35        1150 :   reg->cb = cb;
      36        1150 :   reg->data = data;
      37        1150 : }
      38             : 
      39             : static void
      40      135181 : vnet_feature_reg_invoke (u32 sw_if_index, u8 arc_index, u8 is_enable)
      41             : {
      42             :   vnet_feature_upd_registration_t *reg;
      43             : 
      44      402668 :   vec_foreach (reg, regs)
      45      267487 :     reg->cb (sw_if_index, arc_index, is_enable, reg->data);
      46      135181 : }
      47             : 
      48             : 
      49             : static clib_error_t *
      50         575 : vnet_feature_init (vlib_main_t * vm)
      51             : {
      52         575 :   vnet_feature_main_t *fm = &feature_main;
      53             :   vnet_feature_registration_t *freg;
      54             :   vnet_feature_arc_registration_t *areg;
      55             :   vnet_feature_constraint_registration_t *creg;
      56         575 :   u32 arc_index = 0;
      57             : 
      58         575 :   fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
      59         575 :   areg = fm->next_arc;
      60             : 
      61             :   /* process feature arc registrations */
      62       15525 :   while (areg)
      63             :     {
      64             :       char *s;
      65       14950 :       int i = 0;
      66       14950 :       areg->feature_arc_index = arc_index;
      67       14950 :       if (areg->arc_index_ptr)
      68       10925 :         *areg->arc_index_ptr = arc_index;
      69       29900 :       hash_set_mem (fm->arc_index_by_name, areg->arc_name,
      70             :                     pointer_to_uword (areg));
      71             : 
      72             :       /* process start nodes */
      73       35650 :       while ((s = areg->start_nodes[i]))
      74             :         {
      75       20700 :           i++;
      76             :         }
      77       14950 :       areg->n_start_nodes = i;
      78             : 
      79             :       /* next */
      80       14950 :       areg = areg->next;
      81       14950 :       arc_index++;
      82             :     }
      83             : 
      84         575 :   vec_validate (fm->next_feature_by_arc, arc_index - 1);
      85         575 :   vec_validate (fm->feature_nodes, arc_index - 1);
      86         575 :   vec_validate (fm->feature_config_mains, arc_index - 1);
      87         575 :   vec_validate (fm->next_feature_by_name, arc_index - 1);
      88         575 :   vec_validate (fm->sw_if_index_has_features, arc_index - 1);
      89         575 :   vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
      90         575 :   vec_validate (fm->next_constraint_by_arc, arc_index - 1);
      91             : 
      92         575 :   freg = fm->next_feature;
      93      140903 :   while (freg)
      94             :     {
      95             :       vnet_feature_registration_t *next;
      96      280656 :       uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
      97      140328 :       if (p == 0)
      98             :         {
      99             :           /* Don't start vpp with broken features arcs */
     100           0 :           clib_warning ("Unknown feature arc '%s'", freg->arc_name);
     101           0 :           os_exit (1);
     102             :         }
     103             : 
     104      140328 :       areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
     105      140328 :       arc_index = areg->feature_arc_index;
     106             : 
     107      140328 :       next = freg->next;
     108      140328 :       freg->next_in_arc = fm->next_feature_by_arc[arc_index];
     109      140328 :       fm->next_feature_by_arc[arc_index] = freg;
     110             : 
     111             :       /* next */
     112      140328 :       freg = next;
     113             :     }
     114             : 
     115             :   /* Move bulk constraints to the constraint by arc lists */
     116         575 :   creg = fm->next_constraint;
     117         575 :   while (creg)
     118             :     {
     119             :       vnet_feature_constraint_registration_t *next;
     120           0 :       uword *p = hash_get_mem (fm->arc_index_by_name, creg->arc_name);
     121           0 :       if (p == 0)
     122             :         {
     123             :           /* Don't start vpp with broken features arcs */
     124           0 :           clib_warning ("Unknown feature arc '%s'", creg->arc_name);
     125           0 :           os_exit (1);
     126             :         }
     127             : 
     128           0 :       areg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
     129           0 :       arc_index = areg->feature_arc_index;
     130             : 
     131           0 :       next = creg->next;
     132           0 :       creg->next_in_arc = fm->next_constraint_by_arc[arc_index];
     133           0 :       fm->next_constraint_by_arc[arc_index] = creg;
     134             : 
     135             :       /* next */
     136           0 :       creg = next;
     137             :     }
     138             : 
     139             : 
     140         575 :   areg = fm->next_arc;
     141       15525 :   while (areg)
     142             :     {
     143             :       clib_error_t *error;
     144             :       vnet_feature_config_main_t *cm;
     145             :       vnet_config_main_t *vcm;
     146             :       char **features_in_order, *last_feature;
     147             : 
     148       14950 :       arc_index = areg->feature_arc_index;
     149       14950 :       cm = &fm->feature_config_mains[arc_index];
     150       14950 :       vcm = &cm->config_main;
     151       14950 :       if ((error = vnet_feature_arc_init
     152             :            (vm, vcm, areg->start_nodes, areg->n_start_nodes,
     153             :             areg->last_in_arc,
     154       14950 :             fm->next_feature_by_arc[arc_index],
     155       14950 :             fm->next_constraint_by_arc[arc_index],
     156       14950 :             &fm->feature_nodes[arc_index])))
     157             :         {
     158           0 :           clib_error_report (error);
     159           0 :           os_exit (1);
     160             :         }
     161             : 
     162       14950 :       features_in_order = fm->feature_nodes[arc_index];
     163             : 
     164             :       /* If specified, verify that the last node in the arc is actually last */
     165       14950 :       if (areg->last_in_arc && vec_len (features_in_order) > 0)
     166             :         {
     167        7475 :           last_feature = features_in_order[vec_len (features_in_order) - 1];
     168        7475 :           if (strncmp (areg->last_in_arc, last_feature,
     169        7475 :                        strlen (areg->last_in_arc)))
     170           0 :             clib_warning
     171             :               ("WARNING: %s arc: last node is %s, but expected %s!",
     172             :                areg->arc_name, last_feature, areg->last_in_arc);
     173             :         }
     174             : 
     175       14950 :       fm->next_feature_by_name[arc_index] =
     176       14950 :         hash_create_string (0, sizeof (uword));
     177       14950 :       freg = fm->next_feature_by_arc[arc_index];
     178             : 
     179      155278 :       while (freg)
     180             :         {
     181      280656 :           hash_set_mem (fm->next_feature_by_name[arc_index],
     182             :                         freg->node_name, pointer_to_uword (freg));
     183      140328 :           freg = freg->next_in_arc;
     184             :         }
     185             : 
     186             :       /* next */
     187       14950 :       areg = areg->next;
     188       14950 :       arc_index++;
     189             :     }
     190             : 
     191         575 :   return 0;
     192             : }
     193             : 
     194       80063 : VLIB_INIT_FUNCTION (vnet_feature_init);
     195             : 
     196             : u8
     197      116697 : vnet_get_feature_arc_index (const char *s)
     198             : {
     199      116697 :   vnet_feature_main_t *fm = &feature_main;
     200             :   vnet_feature_arc_registration_t *reg;
     201             :   uword *p;
     202             : 
     203      116697 :   p = hash_get_mem (fm->arc_index_by_name, s);
     204      116697 :   if (p == 0)
     205           0 :     return ~0;
     206             : 
     207      116697 :   reg = uword_to_pointer (p[0], vnet_feature_arc_registration_t *);
     208      116697 :   return reg->feature_arc_index;
     209             : }
     210             : 
     211             : vnet_feature_registration_t *
     212           8 : vnet_get_feature_reg (const char *arc_name, const char *node_name)
     213             : {
     214             :   u8 arc_index;
     215             : 
     216           8 :   arc_index = vnet_get_feature_arc_index (arc_name);
     217           8 :   if (arc_index == (u8) ~ 0)
     218           0 :     return 0;
     219             : 
     220           8 :   vnet_feature_main_t *fm = &feature_main;
     221             :   vnet_feature_registration_t *reg;
     222             :   uword *p;
     223             : 
     224           8 :   p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
     225           8 :   if (p == 0)
     226           0 :     return 0;
     227             : 
     228           8 :   reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
     229           8 :   return reg;
     230             : }
     231             : 
     232             : u32
     233      109618 : vnet_get_feature_index (u8 arc, const char *s)
     234             : {
     235      109618 :   vnet_feature_main_t *fm = &feature_main;
     236             :   vnet_feature_registration_t *reg;
     237             :   uword *p;
     238             : 
     239      109618 :   if (s == 0)
     240           0 :     return ~0;
     241             : 
     242      109618 :   p = hash_get_mem (fm->next_feature_by_name[arc], s);
     243      109618 :   if (p == 0)
     244         641 :     return ~0;
     245             : 
     246      108977 :   reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
     247      108977 :   return reg->feature_index;
     248             : }
     249             : 
     250             : int
     251      109618 : vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
     252             :                                         u32 sw_if_index, int enable_disable,
     253             :                                         void *feature_config,
     254             :                                         u32 n_feature_config_bytes)
     255             : {
     256      109618 :   vnet_feature_main_t *fm = &feature_main;
     257             :   vnet_feature_config_main_t *cm;
     258             :   i16 feature_count;
     259             :   u32 ci;
     260             : 
     261      109618 :   if (arc_index == (u8) ~ 0)
     262           0 :     return VNET_API_ERROR_INVALID_VALUE;
     263             : 
     264      109618 :   if (feature_index == ~0)
     265         641 :     return VNET_API_ERROR_INVALID_VALUE_2;
     266             : 
     267      108977 :   cm = &fm->feature_config_mains[arc_index];
     268      132886 :   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
     269      108977 :   ci = cm->config_index_by_sw_if_index[sw_if_index];
     270             : 
     271      108977 :   vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
     272      108977 :   feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
     273             : 
     274      108977 :   if (!enable_disable && feature_count < 1)
     275        1336 :     return 0;
     276             : 
     277             :   ci = (enable_disable
     278             :         ? vnet_config_add_feature
     279      107641 :         : vnet_config_del_feature)
     280             :     (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
     281             :      n_feature_config_bytes);
     282      107641 :   if (ci == ~0)
     283             :     {
     284        1774 :       return 0;
     285             :     }
     286      105867 :   cm->config_index_by_sw_if_index[sw_if_index] = ci;
     287             : 
     288             :   /* update feature count */
     289      105867 :   enable_disable = (enable_disable > 0);
     290      105867 :   feature_count += enable_disable ? 1 : -1;
     291      105867 :   ASSERT (feature_count >= 0);
     292             : 
     293      211734 :   fm->sw_if_index_has_features[arc_index] =
     294      105867 :     clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
     295             :                      (feature_count > 0));
     296      105867 :   fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
     297             : 
     298      105867 :   vnet_feature_reg_invoke (sw_if_index, arc_index, (feature_count > 0));
     299             : 
     300      105867 :   return 0;
     301             : }
     302             : 
     303             : int
     304      109618 : vnet_feature_enable_disable (const char *arc_name, const char *node_name,
     305             :                              u32 sw_if_index, int enable_disable,
     306             :                              void *feature_config, u32 n_feature_config_bytes)
     307             : {
     308             :   u32 feature_index;
     309             :   u8 arc_index;
     310             : 
     311      109618 :   arc_index = vnet_get_feature_arc_index (arc_name);
     312             : 
     313      109618 :   if (arc_index == (u8) ~ 0)
     314           0 :     return VNET_API_ERROR_INVALID_VALUE;
     315             : 
     316      109618 :   feature_index = vnet_get_feature_index (arc_index, node_name);
     317             : 
     318      109618 :   return vnet_feature_enable_disable_with_index (arc_index, feature_index,
     319             :                                                  sw_if_index, enable_disable,
     320             :                                                  feature_config,
     321             :                                                  n_feature_config_bytes);
     322             : }
     323             : 
     324             : int
     325           0 : vnet_feature_is_enabled (const char *arc_name, const char *feature_node_name,
     326             :                          u32 sw_if_index)
     327             : {
     328           0 :   vnet_feature_main_t *fm = &feature_main;
     329             :   vnet_feature_config_main_t *cm;
     330             :   vnet_config_main_t *ccm;
     331             :   vnet_config_t *current_config;
     332             :   vnet_config_feature_t *f;
     333             :   u32 feature_index;
     334             :   u32 ci;
     335             :   u8 arc_index;
     336             :   u32 *p;
     337             : 
     338           0 :   arc_index = vnet_get_feature_arc_index (arc_name);
     339             : 
     340             :   /* No such arc? */
     341           0 :   if (arc_index == (u8) ~ 0)
     342           0 :     return VNET_API_ERROR_INVALID_VALUE;
     343             : 
     344           0 :   feature_index = vnet_get_feature_index (arc_index, feature_node_name);
     345             : 
     346             :   /* No such feature? */
     347           0 :   if (feature_index == (u32) ~ 0)
     348           0 :     return VNET_API_ERROR_INVALID_VALUE_2;
     349             : 
     350           0 :   cm = &fm->feature_config_mains[arc_index];
     351             : 
     352           0 :   if (sw_if_index < vec_len (cm->config_index_by_sw_if_index))
     353           0 :     ci = vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
     354             :   else
     355             :     /* sw_if_index out of range, certainly not enabled */
     356           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
     357             : 
     358             :   /* No features were ever configured? */
     359           0 :   if (ci == ~0)
     360           0 :     return 0;
     361             : 
     362           0 :   ccm = &cm->config_main;
     363             : 
     364           0 :   p = heap_elt_at_index (ccm->config_string_heap, ci);
     365             : 
     366           0 :   current_config = pool_elt_at_index (ccm->config_pool, p[-1]);
     367             : 
     368             :   /* Find feature with the required index */
     369           0 :   vec_foreach (f, current_config->features)
     370             :   {
     371           0 :     if (f->feature_index == feature_index)
     372             :       /* Feature was enabled */
     373           0 :       return 1;
     374             :   }
     375             :   /* feature wasn't enabled */
     376           0 :   return 0;
     377             : }
     378             : 
     379             : u32
     380         972 : vnet_feature_get_end_node (u8 arc_index, u32 sw_if_index)
     381             : {
     382         972 :   vnet_feature_main_t *fm = &feature_main;
     383             :   vnet_feature_config_main_t *cm;
     384             :   u32 ci;
     385             : 
     386         972 :   if (arc_index == (u8) ~0)
     387           0 :     return VNET_API_ERROR_INVALID_VALUE;
     388             : 
     389         972 :   cm = &fm->feature_config_mains[arc_index];
     390         972 :   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
     391         972 :   ci = cm->config_index_by_sw_if_index[sw_if_index];
     392             : 
     393         972 :   return (vnet_config_get_end_node (vlib_get_main (), &cm->config_main, ci));
     394             : }
     395             : 
     396             : u32
     397           0 : vnet_feature_reset_end_node (u8 arc_index, u32 sw_if_index)
     398             : {
     399           0 :   vnet_feature_main_t *fm = &feature_main;
     400             :   vnet_feature_config_main_t *cm;
     401             :   u32 ci;
     402             : 
     403           0 :   cm = &fm->feature_config_mains[arc_index];
     404           0 :   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
     405           0 :   ci = cm->config_index_by_sw_if_index[sw_if_index];
     406             : 
     407           0 :   ci = vnet_config_reset_end_node (vlib_get_main (), &cm->config_main, ci);
     408             : 
     409           0 :   if (ci != ~0)
     410           0 :     cm->config_index_by_sw_if_index[sw_if_index] = ci;
     411             : 
     412             :   i16 feature_count;
     413             : 
     414           0 :   if (NULL == fm->feature_count_by_sw_if_index ||
     415           0 :       vec_len (fm->feature_count_by_sw_if_index) <= arc_index ||
     416           0 :       vec_len (fm->feature_count_by_sw_if_index[arc_index]) <= sw_if_index)
     417           0 :     feature_count = 0;
     418             :   else
     419           0 :     feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
     420             : 
     421           0 :   vnet_feature_reg_invoke (sw_if_index, arc_index, (feature_count > 0));
     422             : 
     423           0 :   return ci;
     424             : }
     425             : 
     426             : u32
     427        4547 : vnet_feature_modify_end_node (u8 arc_index,
     428             :                               u32 sw_if_index, u32 end_node_index)
     429             : {
     430        4547 :   vnet_feature_main_t *fm = &feature_main;
     431             :   vnet_feature_config_main_t *cm;
     432             :   u32 ci;
     433             : 
     434        4547 :   if (arc_index == (u8) ~ 0)
     435           0 :     return VNET_API_ERROR_INVALID_VALUE;
     436             : 
     437        4547 :   if (end_node_index == ~0)
     438           0 :     return VNET_API_ERROR_INVALID_VALUE_2;
     439             : 
     440        4547 :   cm = &fm->feature_config_mains[arc_index];
     441        6987 :   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
     442        4547 :   ci = cm->config_index_by_sw_if_index[sw_if_index];
     443             : 
     444        4547 :   ci = vnet_config_modify_end_node (vlib_get_main (), &cm->config_main,
     445             :                                     ci, end_node_index);
     446             : 
     447        4547 :   if (ci != ~0)
     448        4547 :     cm->config_index_by_sw_if_index[sw_if_index] = ci;
     449             : 
     450             :   i16 feature_count;
     451             : 
     452        4547 :   if (NULL == fm->feature_count_by_sw_if_index ||
     453        9094 :       vec_len (fm->feature_count_by_sw_if_index) <= arc_index ||
     454        4547 :       vec_len (fm->feature_count_by_sw_if_index[arc_index]) <= sw_if_index)
     455        4189 :     feature_count = 0;
     456             :   else
     457         358 :     feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
     458             : 
     459        4547 :   vnet_feature_reg_invoke (sw_if_index, arc_index, (feature_count > 0));
     460             : 
     461        4547 :   return ci;
     462             : }
     463             : 
     464             : static int
     465           0 : feature_cmp (void *a1, void *a2)
     466             : {
     467           0 :   vnet_feature_registration_t *reg1 = a1;
     468           0 :   vnet_feature_registration_t *reg2 = a2;
     469             : 
     470           0 :   return (int) reg1->feature_index - reg2->feature_index;
     471             : }
     472             : 
     473             : /** Display the set of available driver features.
     474             :     Useful for verifying that expected features are present
     475             : */
     476             : 
     477             : static clib_error_t *
     478           0 : show_features_command_fn (vlib_main_t * vm,
     479             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     480             : {
     481           0 :   vnet_feature_main_t *fm = &feature_main;
     482             :   vnet_feature_arc_registration_t *areg;
     483             :   vnet_feature_registration_t *freg;
     484           0 :   vnet_feature_registration_t *feature_regs = 0;
     485           0 :   int verbose = 0;
     486             : 
     487           0 :   if (unformat (input, "verbose"))
     488           0 :     verbose = 1;
     489             : 
     490           0 :   vlib_cli_output (vm, "Available feature paths");
     491             : 
     492           0 :   areg = fm->next_arc;
     493           0 :   while (areg)
     494             :     {
     495           0 :       if (verbose)
     496           0 :         vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index,
     497             :                          areg->arc_name);
     498             :       else
     499           0 :         vlib_cli_output (vm, "%s:", areg->arc_name);
     500             : 
     501           0 :       freg = fm->next_feature_by_arc[areg->feature_arc_index];
     502           0 :       while (freg)
     503             :         {
     504           0 :           vec_add1 (feature_regs, freg[0]);
     505           0 :           freg = freg->next_in_arc;
     506             :         }
     507             : 
     508           0 :       vec_sort_with_function (feature_regs, feature_cmp);
     509             : 
     510           0 :       vec_foreach (freg, feature_regs)
     511             :       {
     512           0 :         if (verbose)
     513           0 :           vlib_cli_output (vm, "  [%2d]: %s\n", freg->feature_index,
     514             :                            freg->node_name);
     515             :         else
     516           0 :           vlib_cli_output (vm, "  %s\n", freg->node_name);
     517             :       }
     518           0 :       vec_reset_length (feature_regs);
     519             :       /* next */
     520           0 :       areg = areg->next;
     521             :     }
     522           0 :   vec_free (feature_regs);
     523             : 
     524           0 :   return 0;
     525             : }
     526             : 
     527             : /*?
     528             :  * Display the set of available driver features
     529             :  *
     530             :  * @cliexpar
     531             :  * Example:
     532             :  * @cliexcmd{show features [verbose]}
     533             :  * @cliexend
     534             :  * @endparblock
     535             : ?*/
     536             : /* *INDENT-OFF* */
     537      285289 : VLIB_CLI_COMMAND (show_features_command, static) = {
     538             :   .path = "show features",
     539             :   .short_help = "show features [verbose]",
     540             :   .function = show_features_command_fn,
     541             : };
     542             : /* *INDENT-ON* */
     543             : 
     544             : /** Display the set of driver features configured on a specific interface
     545             :   * Called by "show interface" handler
     546             :  */
     547             : 
     548             : void
     549           3 : vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index, int verbose)
     550             : {
     551           3 :   vnet_feature_main_t *fm = &feature_main;
     552             :   u32 node_index, current_config_index;
     553             :   u16 feature_arc;
     554           3 :   vnet_feature_config_main_t *cm = fm->feature_config_mains;
     555             :   vnet_feature_arc_registration_t *areg;
     556             :   vnet_config_main_t *vcm;
     557             :   vnet_config_t *cfg;
     558             :   u32 cfg_index;
     559             :   vnet_config_feature_t *feat;
     560             :   vlib_node_t *n;
     561             :   int i;
     562             : 
     563           3 :   vlib_cli_output (vm, "Feature paths configured on %U...",
     564             :                    format_vnet_sw_if_index_name,
     565             :                    vnet_get_main (), sw_if_index);
     566             : 
     567           3 :   areg = fm->next_arc;
     568          81 :   while (areg)
     569             :     {
     570          78 :       feature_arc = areg->feature_arc_index;
     571          78 :       vcm = &(cm[feature_arc].config_main);
     572             : 
     573          78 :       vlib_cli_output (vm, "\n%s:", areg->arc_name);
     574          78 :       areg = areg->next;
     575             : 
     576          78 :       if (!vnet_have_features (feature_arc, sw_if_index))
     577             :         {
     578          68 :           vlib_cli_output (vm, "  none configured");
     579          68 :           continue;
     580             :         }
     581             : 
     582          10 :       current_config_index =
     583          10 :         vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
     584          10 :       cfg_index =
     585          10 :         vec_elt (vcm->config_pool_index_by_user_index, current_config_index);
     586          10 :       cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
     587             : 
     588          28 :       for (i = 0; i < vec_len (cfg->features); i++)
     589             :         {
     590          18 :           feat = cfg->features + i;
     591          18 :           node_index = feat->node_index;
     592          18 :           n = vlib_get_node (vm, node_index);
     593          18 :           if (verbose)
     594           0 :             vlib_cli_output (vm, "  [%2d] %v", feat->feature_index, n->name);
     595             :           else
     596          18 :             vlib_cli_output (vm, "  %v", n->name);
     597             :         }
     598          10 :       if (verbose)
     599             :         {
     600             :           n =
     601           0 :             vlib_get_node (vm,
     602           0 :                            vcm->end_node_indices_by_user_index
     603           0 :                            [current_config_index]);
     604           0 :           vlib_cli_output (vm, "  [end] %v", n->name);
     605             :         }
     606             :     }
     607           3 : }
     608             : 
     609             : static clib_error_t *
     610           0 : set_interface_features_command_fn (vlib_main_t * vm,
     611             :                                    unformat_input_t * input,
     612             :                                    vlib_cli_command_t * cmd)
     613             : {
     614           0 :   vnet_main_t *vnm = vnet_get_main ();
     615           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     616           0 :   clib_error_t *error = 0;
     617             : 
     618           0 :   u8 *arc_name = 0;
     619           0 :   u8 *feature_name = 0;
     620           0 :   u32 sw_if_index = ~0;
     621           0 :   u8 enable = 1;
     622             : 
     623             :   /* Get a line of input. */
     624           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     625           0 :     return 0;
     626             : 
     627           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     628             :     {
     629           0 :       if (unformat
     630             :           (line_input, "%U %s arc %s", unformat_vnet_sw_interface, vnm,
     631             :            &sw_if_index, &feature_name, &arc_name))
     632             :         ;
     633           0 :       else if (unformat (line_input, "disable"))
     634           0 :         enable = 0;
     635             :       else
     636             :         {
     637           0 :           error = unformat_parse_error (line_input);
     638           0 :           goto done;
     639             :         }
     640             :     }
     641           0 :   if (!feature_name || !arc_name)
     642             :     {
     643           0 :       error = clib_error_return (0, "Both feature name and arc required...");
     644           0 :       goto done;
     645             :     }
     646             : 
     647           0 :   if (sw_if_index == ~0)
     648             :     {
     649           0 :       error = clib_error_return (0, "Interface not specified...");
     650           0 :       goto done;
     651             :     }
     652             : 
     653           0 :   vec_add1 (arc_name, 0);
     654           0 :   vec_add1 (feature_name, 0);
     655             : 
     656             :   u8 arc_index;
     657             : 
     658           0 :   arc_index = vnet_get_feature_arc_index ((const char *) arc_name);
     659             : 
     660           0 :   if (arc_index == (u8) ~ 0)
     661             :     {
     662             :       error =
     663           0 :         clib_error_return (0, "Unknown arc name (%s)... ",
     664             :                            (const char *) arc_name);
     665           0 :       goto done;
     666             :     }
     667             : 
     668             :   vnet_feature_registration_t *reg;
     669             :   reg =
     670           0 :     vnet_get_feature_reg ((const char *) arc_name,
     671             :                           (const char *) feature_name);
     672           0 :   if (reg == 0)
     673             :     {
     674             :       error =
     675           0 :         clib_error_return (0,
     676             :                            "Feature (%s) not registered to arc (%s)... See 'show features verbose' for valid feature/arc combinations. ",
     677             :                            feature_name, arc_name);
     678           0 :       goto done;
     679             :     }
     680           0 :   if (reg->enable_disable_cb)
     681           0 :     error = reg->enable_disable_cb (sw_if_index, enable);
     682           0 :   if (!error)
     683           0 :     vnet_feature_enable_disable ((const char *) arc_name,
     684             :                                  (const char *) feature_name, sw_if_index,
     685             :                                  enable, 0, 0);
     686             : 
     687           0 : done:
     688           0 :   vec_free (feature_name);
     689           0 :   vec_free (arc_name);
     690           0 :   unformat_free (line_input);
     691           0 :   return error;
     692             : }
     693             : 
     694             : /*?
     695             :  * Set feature for given interface
     696             :  *
     697             :  * @cliexpar
     698             :  * Example:
     699             :  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
     700             :  * @cliexend
     701             :  * @endparblock
     702             : ?*/
     703             : /* *INDENT-OFF* */
     704      285289 : VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
     705             :   .path = "set interface feature",
     706             :   .short_help = "set interface feature <intfc> <feature_name> arc <arc_name> "
     707             :       "[disable]",
     708             :   .function = set_interface_features_command_fn,
     709             : };
     710             : /* *INDENT-ON* */
     711             : 
     712             : static clib_error_t *
     713       11798 : vnet_feature_add_del_sw_interface (vnet_main_t * vnm, u32 sw_if_index,
     714             :                                    u32 is_add)
     715             : {
     716       11798 :   vnet_feature_main_t *fm = &feature_main;
     717             :   const vnet_feature_arc_registration_t *far;
     718             : 
     719       11798 :   if (is_add)
     720        7547 :     return 0;
     721             : 
     722             :   /*
     723             :    * remove all enabled features from an interface on deletion
     724             :    */
     725      114777 :   for (far = fm->next_arc; far != 0; far = far->next)
     726             :     {
     727      110526 :       const u8 arc_index = far->feature_arc_index;
     728      110526 :       vnet_feature_config_main_t *cm =
     729      110526 :         vec_elt_at_index (fm->feature_config_mains, arc_index);
     730      110526 :       const u32 ci =
     731      110526 :         vec_len (cm->config_index_by_sw_if_index) <=
     732      110526 :         sw_if_index ? ~0 : vec_elt (cm->config_index_by_sw_if_index,
     733             :                                     sw_if_index);
     734             : 
     735      110526 :       if (~0 == ci)
     736       85759 :         continue;
     737             : 
     738       49534 :       fm->sw_if_index_has_features[arc_index] =
     739       24767 :         clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
     740             :                          0);
     741             : 
     742       24767 :       vnet_feature_reg_invoke (sw_if_index, arc_index, 0);
     743             : 
     744       24767 :       if (vec_len (fm->feature_count_by_sw_if_index[arc_index]) > sw_if_index)
     745       22999 :         vec_elt (fm->feature_count_by_sw_if_index[arc_index], sw_if_index) =
     746             :           0;
     747             : 
     748       24767 :       vec_elt (cm->config_index_by_sw_if_index, sw_if_index) = ~0;
     749       24767 :       vnet_config_del (&cm->config_main, ci);
     750             :     }
     751             : 
     752        4251 :   return 0;
     753             : }
     754             : 
     755        1151 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION_PRIO (vnet_feature_add_del_sw_interface,
     756             :                                          VNET_ITF_FUNC_PRIORITY_HIGH);
     757             : 
     758             : /*
     759             :  * fd.io coding-style-patch-verification: ON
     760             :  *
     761             :  * Local Variables:
     762             :  * eval: (c-set-style "gnu")
     763             :  * End:
     764             :  */

Generated by: LCOV version 1.14