LCOV - code coverage report
Current view: top level - vnet/bier - bier_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 231 259 89.2 %
Date: 2023-07-05 22:20:52 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * bier_api.c - vnet BIER api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vnet/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/api_errno.h>
      24             : #include <vnet/bier/bier_table.h>
      25             : #include <vnet/bier/bier_imp.h>
      26             : #include <vnet/bier/bier_disp_table.h>
      27             : #include <vnet/bier/bier_disp_entry.h>
      28             : #include <vnet/bier/bier_bit_string.h>
      29             : #include <vnet/bier/bier_hdr_inlines.h>
      30             : #include <vnet/fib/fib_path_list.h>
      31             : #include <vnet/fib/fib_api.h>
      32             : #include <vnet/fib/fib_table.h>
      33             : #include <vnet/mfib/mfib_table.h>
      34             : 
      35             : #include <vnet/format_fns.h>
      36             : #include <bier/bier.api_enum.h>
      37             : #include <bier/bier.api_types.h>
      38             : 
      39             : #define REPLY_MSG_ID_BASE bier_main.msg_id_base
      40             : #include <vlibapi/api_helper_macros.h>
      41             : 
      42             : typedef struct
      43             : {
      44             :   u16 msg_id_base;
      45             : } bier_main_t;
      46             : 
      47             : bier_main_t bier_main;
      48             : 
      49             : static void
      50          14 : vl_api_bier_table_add_del_t_handler (vl_api_bier_table_add_del_t * mp)
      51             : {
      52             :     vl_api_bier_table_add_del_reply_t *rmp;
      53             :     vnet_main_t *vnm;
      54             :     int rv;
      55             : 
      56          14 :     vnm = vnet_get_main ();
      57          14 :     vnm->api_errno = 0;
      58             : 
      59          14 :     if (mp->bt_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048)
      60             :     {
      61           0 :         rv = VNET_API_ERROR_BIER_BSL_UNSUP;
      62             :     }
      63             :     else
      64             :     {
      65          14 :         bier_table_id_t bti = {
      66          14 :             .bti_set = mp->bt_tbl_id.bt_set,
      67          14 :             .bti_sub_domain = mp->bt_tbl_id.bt_sub_domain,
      68          14 :             .bti_hdr_len = mp->bt_tbl_id.bt_hdr_len_id,
      69             :             .bti_type = BIER_TABLE_MPLS_SPF,
      70             :             .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN,
      71             :         };
      72             : 
      73          14 :         if (mp->bt_is_add)
      74             :         {
      75           7 :             mpls_label_t label = ntohl(mp->bt_label);
      76             : 
      77             :             /*
      78             :              * convert acceptable 'don't want a label' values from 
      79             :              * the API to the correct internal INVLID value
      80             :              */
      81           7 :             if ((0 == label) || (~0 == label))
      82             :             {
      83           0 :                 label = MPLS_LABEL_INVALID;
      84             :             }
      85           7 :             bier_table_add_or_lock(&bti, label);
      86             :         }
      87             :         else
      88             :         {
      89           7 :             bier_table_unlock(&bti);
      90             :         }
      91             : 
      92          14 :         rv = vnm->api_errno;
      93             :     }
      94             : 
      95          14 :     REPLY_MACRO (VL_API_BIER_TABLE_ADD_DEL_REPLY);
      96             : }
      97             : 
      98             : static void
      99           7 : send_bier_table_details (vl_api_registration_t * reg,
     100             :                          u32 context,
     101             :                          const bier_table_t *bt)
     102             : {
     103             :     vl_api_bier_table_details_t *mp;
     104             : 
     105           7 :     mp = vl_msg_api_alloc(sizeof(*mp));
     106           7 :     if (!mp)
     107           0 :         return;
     108           7 :     clib_memset(mp, 0, sizeof(*mp));
     109           7 :     mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BIER_TABLE_DETAILS);
     110           7 :     mp->context = context;
     111             : 
     112           7 :     mp->bt_label = bt->bt_ll;
     113           7 :     mp->bt_tbl_id.bt_set = bt->bt_id.bti_set;
     114           7 :     mp->bt_tbl_id.bt_sub_domain = bt->bt_id.bti_sub_domain;
     115           7 :     mp->bt_tbl_id.bt_hdr_len_id = bt->bt_id.bti_hdr_len;
     116             : 
     117           7 :     vl_api_send_msg (reg, (u8 *) mp);
     118             : }
     119             : 
     120             : static void
     121          14 : vl_api_bier_table_dump_t_handler (vl_api_bier_table_dump_t * mp)
     122             : {
     123             :     vl_api_registration_t *reg;
     124             :     bier_table_t *bt;
     125             : 
     126          14 :     reg = vl_api_client_index_to_registration (mp->client_index);
     127          14 :     if (!reg)
     128           0 :       return;
     129             : 
     130         133 :     pool_foreach (bt, bier_table_pool)
     131             :      {
     132             :         /*
     133             :          * skip the ecmp tables.
     134             :          */
     135         119 :         if (bier_table_is_main(bt))
     136             :         {
     137           7 :             send_bier_table_details(reg, mp->context, bt);
     138             :         }
     139             :     }
     140             : }
     141             : 
     142             : static void
     143         147 : vl_api_bier_route_add_del_t_handler (vl_api_bier_route_add_del_t * mp)
     144             : {
     145             :     vl_api_bier_route_add_del_reply_t *rmp;
     146             :     fib_route_path_t *brpaths, *brpath;
     147             :     vnet_main_t *vnm;
     148             :     bier_bp_t bp;
     149         147 :     int rv = 0;
     150             :     u8 ii;
     151             : 
     152         147 :     vnm = vnet_get_main ();
     153         147 :     vnm->api_errno = 0;
     154         147 :     bp = ntohl(mp->br_route.br_bp);
     155         147 :     brpaths = NULL;
     156             : 
     157         147 :     if (mp->br_route.br_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048)
     158             :     {
     159           0 :         rv = VNET_API_ERROR_BIER_BSL_UNSUP;
     160           0 :         goto done;
     161             :     }
     162         147 :     if (0 == bp || bp > BIER_BP_MAX)
     163             :     {
     164           0 :         rv = -1;
     165           0 :         goto done;
     166             :     }
     167             : 
     168         147 :     bier_table_id_t bti = {
     169         147 :         .bti_set = mp->br_route.br_tbl_id.bt_set,
     170         147 :         .bti_sub_domain = mp->br_route.br_tbl_id.bt_sub_domain,
     171         147 :         .bti_hdr_len = mp->br_route.br_tbl_id.bt_hdr_len_id,
     172             :         .bti_type = BIER_TABLE_MPLS_SPF,
     173             :         .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN,
     174             :     };
     175             : 
     176         147 :     vec_validate(brpaths, mp->br_route.br_n_paths - 1);
     177             : 
     178         297 :     vec_foreach_index(ii, brpaths)
     179             :     {
     180         150 :         brpath = &brpaths[ii];
     181         150 :         rv = fib_api_path_decode(&mp->br_route.br_paths[ii], brpath);
     182             : 
     183         150 :         if (0 != rv)
     184             :         {
     185           0 :             goto done;
     186             :         }
     187             :     }
     188             : 
     189         147 :     if (mp->br_is_replace)
     190             :     {
     191           2 :         if (0 == vec_len(brpaths))
     192             :         {
     193           1 :             bier_table_route_delete(&bti, bp);
     194             :         }
     195             :         else
     196             :         {
     197           1 :             bier_table_route_path_update(&bti, bp, brpaths);
     198             :         }
     199             :     }
     200         145 :     else if (mp->br_is_add)
     201             :     {
     202          72 :         bier_table_route_path_add(&bti, bp, brpaths);
     203             :     }
     204             :     else
     205             :     {
     206          73 :         bier_table_route_path_remove(&bti, bp, brpaths);
     207             :     }
     208         147 :     vec_free(brpaths);
     209             : 
     210         147 : done:
     211         147 :     rv = (rv == 0) ? vnm->api_errno : rv;
     212             : 
     213         147 :     REPLY_MACRO (VL_API_BIER_ROUTE_ADD_DEL_REPLY);
     214             : }
     215             : 
     216             : typedef struct bier_route_details_walk_t_
     217             : {
     218             :     vl_api_registration_t * reg;
     219             :     u32 context;
     220             : } bier_route_details_walk_t;
     221             : 
     222             : static void
     223          11 : send_bier_route_details (const bier_table_t *bt,
     224             :                          const bier_entry_t *be,
     225             :                          void *args)
     226             : {
     227          11 :     bier_route_details_walk_t *ctx = args;
     228             :     vl_api_bier_route_details_t *mp;
     229          11 :     fib_path_encode_ctx_t path_ctx = {
     230             :         .rpaths = NULL,
     231             :     };
     232             :     fib_route_path_t *rpath;
     233             :     vl_api_fib_path_t *fp;
     234             :     u32 n_paths, m_size;
     235             : 
     236          11 :     n_paths = fib_path_list_get_n_paths(be->be_path_list);
     237          11 :     m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t));
     238          11 :     mp = vl_msg_api_alloc(m_size);
     239          11 :     if (!mp)
     240           0 :         return;
     241             : 
     242          11 :     clib_memset(mp, 0, m_size);
     243          11 :     mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BIER_ROUTE_DETAILS);
     244          11 :     mp->context = ctx->context;
     245             : 
     246          11 :     mp->br_route.br_tbl_id.bt_set = bt->bt_id.bti_set;
     247          11 :     mp->br_route.br_tbl_id.bt_sub_domain = bt->bt_id.bti_sub_domain;
     248          11 :     mp->br_route.br_tbl_id.bt_hdr_len_id = bt->bt_id.bti_hdr_len;
     249          11 :     mp->br_route.br_bp = htonl(be->be_bp);
     250          11 :     mp->br_route.br_n_paths = htonl(n_paths);
     251             : 
     252          11 :     fib_path_list_walk_w_ext(be->be_path_list,
     253             :                              NULL,
     254             :                              fib_path_encode,
     255             :                             &path_ctx);
     256             : 
     257          11 :     fp = mp->br_route.br_paths;
     258          22 :     vec_foreach (rpath, path_ctx.rpaths)
     259             :     {
     260          11 :         fib_api_path_encode(rpath, fp);
     261          11 :         fp++;
     262             :     }
     263             : 
     264          11 :     vec_free(path_ctx.rpaths);
     265          11 :     vl_api_send_msg (ctx->reg, (u8 *) mp);
     266             : }
     267             : 
     268             : static void
     269          79 : vl_api_bier_route_dump_t_handler (vl_api_bier_route_dump_t * mp)
     270             : {
     271             :     vl_api_registration_t *reg;
     272             : 
     273          79 :     reg = vl_api_client_index_to_registration (mp->client_index);
     274          79 :     if (!reg)
     275           0 :       return;
     276             : 
     277          79 :     bier_table_id_t bti = {
     278          79 :         .bti_set = mp->br_tbl_id.bt_set,
     279          79 :         .bti_sub_domain = mp->br_tbl_id.bt_sub_domain,
     280          79 :         .bti_hdr_len = mp->br_tbl_id.bt_hdr_len_id,
     281             :         .bti_type = BIER_TABLE_MPLS_SPF,
     282             :         .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN,
     283             :     };
     284          79 :     bier_route_details_walk_t ctx = {
     285             :         .reg = reg,
     286          79 :         .context = mp->context,
     287             :     };
     288          79 :     bier_table_walk(&bti, send_bier_route_details, &ctx);
     289             : }
     290             : 
     291             : static void
     292           6 : vl_api_bier_imp_add_t_handler (vl_api_bier_imp_add_t * mp)
     293             : {
     294             :     vl_api_bier_imp_add_reply_t *rmp;
     295             :     vnet_main_t *vnm;
     296           6 :     index_t bii = ~0;
     297           6 :     int rv = 0;
     298             : 
     299           6 :     vnm = vnet_get_main ();
     300           6 :     vnm->api_errno = 0;
     301             : 
     302             :     /*
     303             :      * The BSL support by VPP is limited to the size of the
     304             :      * available space in the vlib_buffer_t
     305             :      */
     306           6 :     if (mp->bi_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048)
     307             :     {
     308           0 :         rv = VNET_API_ERROR_BIER_BSL_UNSUP;
     309             :     }
     310             :     else
     311             :     {
     312           6 :         bier_table_id_t bti = {
     313           6 :             .bti_set = mp->bi_tbl_id.bt_set,
     314           6 :             .bti_sub_domain = mp->bi_tbl_id.bt_sub_domain,
     315           6 :             .bti_hdr_len = mp->bi_tbl_id.bt_hdr_len_id,
     316             :             .bti_type = BIER_TABLE_MPLS_SPF,
     317             :             .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN,
     318             :         };
     319           6 :         bier_bit_string_t bs = {
     320           6 :             .bbs_len = mp->bi_n_bytes,
     321           6 :             .bbs_buckets = mp->bi_bytes,
     322             :         };
     323             : 
     324           6 :         bii = bier_imp_add_or_lock(&bti, ntohs(mp->bi_src), &bs);
     325             :     }
     326             : 
     327           6 :     REPLY_MACRO2 (VL_API_BIER_IMP_ADD_REPLY,
     328             :     ({
     329             :         rmp->bi_index = ntohl (bii);
     330             :     }));
     331             : }
     332             : 
     333             : static void
     334           6 : vl_api_bier_imp_del_t_handler (vl_api_bier_imp_del_t * mp)
     335             : {
     336             :     vl_api_bier_imp_del_reply_t *rmp;
     337             :     vnet_main_t *vnm;
     338           6 :     int rv = 0;
     339             : 
     340           6 :     vnm = vnet_get_main ();
     341           6 :     vnm->api_errno = 0;
     342             : 
     343           6 :     bier_imp_unlock(ntohl(mp->bi_index));
     344             : 
     345           6 :     REPLY_MACRO(VL_API_BIER_IMP_DEL_REPLY);
     346             : }
     347             : 
     348             : static void
     349          10 : send_bier_imp_details (vl_api_registration_t * reg,
     350             :                        u32 context,
     351             :                        const bier_imp_t *bi)
     352             : {
     353             :     vl_api_bier_imp_details_t *mp;
     354             :     bier_hdr_t copy;
     355             :     u8 n_bytes;
     356             : 
     357          10 :     copy = bi->bi_hdr;
     358          10 :     bier_hdr_ntoh(&copy);
     359             : 
     360          10 :     n_bytes = bier_hdr_len_id_to_num_bytes(
     361          10 :                   bier_hdr_get_len_id(&copy));
     362          10 :     mp = vl_msg_api_alloc(sizeof(*mp) + n_bytes);
     363          10 :     if (!mp)
     364           0 :         return;
     365          10 :     clib_memset(mp, 0, sizeof(*mp)+n_bytes);
     366          10 :     mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_BIER_IMP_DETAILS);
     367          10 :     mp->context = context;
     368             : 
     369          10 :     mp->bi_tbl_id.bt_set = bi->bi_tbl.bti_set;
     370          10 :     mp->bi_tbl_id.bt_sub_domain = bi->bi_tbl.bti_sub_domain;
     371          10 :     mp->bi_tbl_id.bt_hdr_len_id = bi->bi_tbl.bti_hdr_len;
     372             : 
     373          10 :     mp->bi_src = htons(bier_hdr_get_src_id(&copy));
     374          10 :     mp->bi_n_bytes = n_bytes;
     375          10 :     memcpy(mp->bi_bytes, bi->bi_bits, n_bytes);
     376             : 
     377          10 :     vl_api_send_msg (reg, (u8 *) mp);
     378             : }
     379             : 
     380             : static void
     381          12 : vl_api_bier_imp_dump_t_handler (vl_api_bier_imp_dump_t * mp)
     382             : {
     383             :     vl_api_registration_t *reg;
     384             :     bier_imp_t *bi;
     385             : 
     386          12 :     reg = vl_api_client_index_to_registration (mp->client_index);
     387          12 :     if (!reg)
     388           0 :       return;
     389             : 
     390          22 :     pool_foreach (bi, bier_imp_pool)
     391             :      {
     392          10 :         send_bier_imp_details(reg, mp->context, bi);
     393             :     }
     394             : }
     395             : 
     396             : static void
     397           6 : vl_api_bier_disp_table_add_del_t_handler (vl_api_bier_disp_table_add_del_t * mp)
     398             : {
     399             :     vl_api_bier_disp_table_add_del_reply_t *rmp;
     400             :     vnet_main_t *vnm;
     401             :     u32 table_id;
     402             :     int rv;
     403             : 
     404           6 :     vnm = vnet_get_main ();
     405           6 :     vnm->api_errno = 0;
     406           6 :     table_id = ntohl(mp->bdt_tbl_id);
     407             : 
     408           6 :     if (mp->bdt_is_add)
     409             :     {
     410           3 :         bier_disp_table_add_or_lock(table_id);
     411             :     }
     412             :     else
     413             :     {
     414           3 :         bier_disp_table_unlock_w_table_id(table_id);
     415             :     }
     416             : 
     417           6 :     rv = vnm->api_errno;
     418             : 
     419           6 :     REPLY_MACRO (VL_API_BIER_DISP_TABLE_ADD_DEL_REPLY);
     420             : }
     421             : 
     422             : static void
     423           3 : send_bier_disp_table_details (vl_api_registration_t * reg,
     424             :                               u32 context,
     425             :                               const bier_disp_table_t *bdt)
     426             : {
     427             :     vl_api_bier_disp_table_details_t *mp;
     428             : 
     429           3 :     mp = vl_msg_api_alloc(sizeof(*mp));
     430           3 :     if (!mp)
     431           0 :         return;
     432           3 :     clib_memset(mp, 0, sizeof(*mp));
     433           3 :     mp->_vl_msg_id =
     434           3 :       ntohs (REPLY_MSG_ID_BASE + VL_API_BIER_DISP_TABLE_DETAILS);
     435           3 :     mp->context = context;
     436             : 
     437           3 :     mp->bdt_tbl_id = htonl(bdt->bdt_table_id);
     438             : 
     439           3 :     vl_api_send_msg (reg, (u8 *) mp);
     440             : }
     441             : 
     442             : static void
     443           6 : vl_api_bier_disp_table_dump_t_handler (vl_api_bier_disp_table_dump_t * mp)
     444             : {
     445             :     vl_api_registration_t *reg;
     446             :     bier_disp_table_t *bdt;
     447             : 
     448           6 :     reg = vl_api_client_index_to_registration (mp->client_index);
     449           6 :     if (!reg)
     450           0 :       return;
     451             : 
     452           9 :     pool_foreach (bdt, bier_disp_table_pool)
     453             :      {
     454           3 :         send_bier_disp_table_details(reg, mp->context, bdt);
     455             :     }
     456             : }
     457             : 
     458             : static void
     459          10 : vl_api_bier_disp_entry_add_del_t_handler (vl_api_bier_disp_entry_add_del_t * mp)
     460             : {
     461             :     vl_api_bier_disp_entry_add_del_reply_t *rmp;
     462          10 :     fib_route_path_t *brps = NULL, *brp;
     463             :     vnet_main_t *vnm;
     464             :     bier_bp_t bp;
     465             :     u32 table_id;
     466          10 :     int rv = 0;
     467             :     u32 ii;
     468             : 
     469          10 :     vnm = vnet_get_main ();
     470          10 :     vnm->api_errno = 0;
     471          10 :     table_id = ntohl(mp->bde_tbl_id);
     472          10 :     bp = ntohs(mp->bde_bp);
     473             : 
     474             :     /*
     475             :      * BP=0 is the default route
     476             :      */
     477          10 :     if (bp > 0xffff)
     478             :     {
     479           0 :         rv = -1;
     480           0 :         goto done;
     481             :     }
     482             : 
     483          10 :     vec_validate(brps, mp->bde_n_paths - 1);
     484          20 :     vec_foreach_index(ii, brps)
     485             :     {
     486          10 :         brp = &brps[ii];
     487          10 :         brp->frp_fib_index = ntohl(mp->bde_paths[ii].table_id);
     488          10 :         brp->frp_sw_if_index = ntohl(mp->bde_paths[ii].sw_if_index);
     489             : 
     490          10 :         if (~0 != ntohl(mp->bde_paths[ii].rpf_id))
     491             :         {
     492          10 :             brp->frp_flags = FIB_ROUTE_PATH_RPF_ID;
     493          10 :             brp->frp_rpf_id = ntohl(mp->bde_paths[ii].rpf_id);
     494             :         }
     495             : 
     496          10 :         if (FIB_API_PATH_NH_PROTO_IP4 == mp->bde_paths[ii].proto)
     497             :         {
     498          10 :             clib_memcpy (&brp->frp_addr.ip4,
     499             :                          &mp->bde_paths[ii].nh.address.ip4,
     500             :                          sizeof (brp->frp_addr.ip4));
     501             :         }
     502           0 :         else if (FIB_API_PATH_NH_PROTO_IP6 == mp->bde_paths[ii].proto)
     503             :         {
     504           0 :             clib_memcpy (&brp->frp_addr.ip6,
     505             :                          &mp->bde_paths[ii].nh.address.ip6,
     506             :                          sizeof (brp->frp_addr.ip6));
     507             :         }
     508          10 :         if (ip46_address_is_zero(&brp->frp_addr))
     509             :         {
     510             :             index_t fti;
     511             : 
     512          10 :             switch (mp->bde_payload_proto)
     513             :             {
     514           0 :             case BIER_HDR_PROTO_INVALID:
     515             :             case BIER_HDR_PROTO_MPLS_DOWN_STREAM:
     516             :             case BIER_HDR_PROTO_MPLS_UP_STREAM:
     517             :             case BIER_HDR_PROTO_ETHERNET:
     518             :             case BIER_HDR_PROTO_VXLAN:
     519             :             case BIER_HDR_PROTO_CTRL:
     520             :             case BIER_HDR_PROTO_OAM:
     521           0 :                 rv = VNET_API_ERROR_UNSUPPORTED;
     522           0 :                 goto done;
     523             :                 break;
     524          10 :             case BIER_HDR_PROTO_IPV4:
     525             :             case BIER_HDR_PROTO_IPV6:
     526             :             {
     527             :                 fib_protocol_t fproto;
     528             : 
     529          10 :                 fproto = (mp->bde_payload_proto == BIER_HDR_PROTO_IPV4 ?
     530          10 :                           FIB_PROTOCOL_IP4 :
     531             :                           FIB_PROTOCOL_IP6);
     532             : 
     533          10 :                 if (brp->frp_flags & FIB_ROUTE_PATH_RPF_ID)
     534             :                 {
     535          10 :                     fti = mfib_table_find (fproto,
     536             :                                            ntohl (mp->bde_paths[ii].table_id));
     537             :                 }
     538             :                 else
     539             :                 {
     540           0 :                     fti = fib_table_find (fproto,
     541             :                                           ntohl (mp->bde_paths[ii].table_id));
     542             :                 }
     543             : 
     544          10 :                 if (INDEX_INVALID != fti)
     545             :                 {
     546          10 :                     brp->frp_fib_index = fti;
     547             :                 }
     548             :                 else
     549             :                 {
     550           0 :                     rv = VNET_API_ERROR_NO_SUCH_FIB;
     551           0 :                     goto done;
     552             :                 }
     553          10 :                 break;
     554             :             }
     555             :             }
     556          10 :         }
     557             :     }
     558             : 
     559          10 :     if (mp->bde_is_add)
     560             :     {
     561           5 :         bier_disp_table_entry_path_add(table_id, bp,
     562           5 :                                        mp->bde_payload_proto,
     563             :                                        brps);
     564             :     }
     565             :     else
     566             :     {
     567           5 :         bier_disp_table_entry_path_remove(table_id, bp,
     568           5 :                                           mp->bde_payload_proto,
     569             :                                           brps);
     570             :     }
     571             : 
     572          10 : done:
     573          10 :     vec_free(brps);
     574          10 :     rv = (rv == 0) ? vnm->api_errno : rv;
     575             : 
     576          10 :     REPLY_MACRO (VL_API_BIER_DISP_ENTRY_ADD_DEL_REPLY);
     577             : }
     578             : 
     579             : typedef struct bier_disp_entry_details_walk_t_
     580             : {
     581             :     vl_api_registration_t * reg;
     582             :     u32 context;
     583             : } bier_disp_entry_details_walk_t;
     584             : 
     585             : static void
     586           9 : send_bier_disp_entry_details (const bier_disp_table_t *bdt,
     587             :                               const bier_disp_entry_t *bde,
     588             :                               u16 bp,
     589             :                               void *args)
     590             : {
     591           9 :     bier_disp_entry_details_walk_t *ctx = args;
     592             :     vl_api_bier_disp_entry_details_t *mp;
     593             :     bier_hdr_proto_id_t pproto;
     594             :     vl_api_fib_path_t *fp;
     595             :     u32 n_paths, m_size;
     596             : 
     597          81 :     FOR_EACH_BIER_HDR_PROTO(pproto)
     598             :     {
     599          72 :         fib_node_index_t pl = bde->bde_pl[pproto];
     600             : 
     601          72 :         if (INDEX_INVALID != pl)
     602             :         {
     603           9 :             fib_path_encode_ctx_t path_ctx = {
     604             :                 .rpaths = NULL,
     605             :             };
     606             :             fib_route_path_t *rpath;
     607             : 
     608           9 :             n_paths = fib_path_list_get_n_paths(pl);
     609           9 :             m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t));
     610           9 :             mp = vl_msg_api_alloc(m_size);
     611           9 :             if (!mp)
     612           0 :                 return;
     613             : 
     614           9 :             clib_memset(mp, 0, m_size);
     615           9 :             mp->_vl_msg_id =
     616           9 :               ntohs (REPLY_MSG_ID_BASE + VL_API_BIER_DISP_ENTRY_DETAILS);
     617           9 :             mp->context = ctx->context;
     618             : 
     619           9 :             mp->bde_tbl_id = htonl (bdt->bdt_table_id);
     620           9 :             mp->bde_n_paths = htonl (n_paths);
     621           9 :             mp->bde_payload_proto = pproto;
     622           9 :             mp->bde_bp = htons (bp);
     623             : 
     624           9 :             fib_path_list_walk_w_ext (pl, NULL, fib_path_encode, &path_ctx);
     625             : 
     626           9 :             fp = mp->bde_paths;
     627          18 :             vec_foreach (rpath, path_ctx.rpaths)
     628             :               {
     629           9 :                 fib_api_path_encode (rpath, fp);
     630           9 :                 fp++;
     631             :               }
     632             : 
     633           9 :             vl_api_send_msg (ctx->reg, (u8 *) mp);
     634           9 :             vec_free (path_ctx.rpaths);
     635             :         }
     636             :     }
     637             : }
     638             : 
     639             : static void
     640          10 : vl_api_bier_disp_entry_dump_t_handler (vl_api_bier_disp_entry_dump_t * mp)
     641             : {
     642             :     vl_api_registration_t *reg;
     643             : 
     644          10 :     reg = vl_api_client_index_to_registration (mp->client_index);
     645          10 :     if (!reg)
     646           0 :       return;
     647             : 
     648          10 :     bier_disp_entry_details_walk_t ctx = {
     649             :         .reg = reg,
     650          10 :         .context = mp->context,
     651             :     };
     652          10 :     bier_disp_table_walk(ntohl(mp->bde_tbl_id),
     653             :                          send_bier_disp_entry_details,
     654             :                          &ctx);
     655             : }
     656             : 
     657             : #include <bier/bier.api.c>
     658             : 
     659             : static clib_error_t *
     660         559 : bier_api_hookup (vlib_main_t * vm)
     661             : {
     662         559 :   bier_main.msg_id_base = setup_message_id_table ();
     663             : 
     664         559 :   return 0;
     665             : }
     666             : 
     667       19039 : VLIB_API_INIT_FUNCTION (bier_api_hookup);

Generated by: LCOV version 1.14