/* *------------------------------------------------------------------ * bier_api.c - vnet BIER api * * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define vl_typedefs /* define message structures */ #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun #include #include #define foreach_bier_api_msg \ _(BIER_TABLE_ADD_DEL, bier_table_add_del) \ _(BIER_TABLE_DUMP, bier_table_dump) \ _(BIER_ROUTE_ADD_DEL, bier_route_add_del) \ _(BIER_ROUTE_DUMP, bier_route_dump) \ _(BIER_IMP_ADD, bier_imp_add) \ _(BIER_IMP_DEL, bier_imp_del) \ _(BIER_IMP_DUMP, bier_imp_dump) \ _(BIER_DISP_TABLE_ADD_DEL, bier_disp_table_add_del) \ _(BIER_DISP_TABLE_DUMP, bier_disp_table_dump) \ _(BIER_DISP_ENTRY_ADD_DEL, bier_disp_entry_add_del) \ _(BIER_DISP_ENTRY_DUMP, bier_disp_entry_dump) static void vl_api_bier_table_add_del_t_handler (vl_api_bier_table_add_del_t * mp) { vl_api_bier_table_add_del_reply_t *rmp; vnet_main_t *vnm; int rv; vnm = vnet_get_main (); vnm->api_errno = 0; if (mp->bt_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048) { rv = VNET_API_ERROR_BIER_BSL_UNSUP; } else { bier_table_id_t bti = { .bti_set = mp->bt_tbl_id.bt_set, .bti_sub_domain = mp->bt_tbl_id.bt_sub_domain, .bti_hdr_len = mp->bt_tbl_id.bt_hdr_len_id, .bti_type = BIER_TABLE_MPLS_SPF, .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN, }; if (mp->bt_is_add) { mpls_label_t label = ntohl(mp->bt_label); /* * convert acceptable 'don't want a label' values from * the API to the correct internal INVLID value */ if ((0 == label) || (~0 == label)) { label = MPLS_LABEL_INVALID; } bier_table_add_or_lock(&bti, label); } else { bier_table_unlock(&bti); } rv = vnm->api_errno; } REPLY_MACRO (VL_API_BIER_TABLE_ADD_DEL_REPLY); } static void send_bier_table_details (vl_api_registration_t * reg, u32 context, const bier_table_t *bt) { vl_api_bier_table_details_t *mp; mp = vl_msg_api_alloc(sizeof(*mp)); if (!mp) return; clib_memset(mp, 0, sizeof(*mp)); mp->_vl_msg_id = ntohs(VL_API_BIER_TABLE_DETAILS); mp->context = context; mp->bt_label = bt->bt_ll; mp->bt_tbl_id.bt_set = bt->bt_id.bti_set; mp->bt_tbl_id.bt_sub_domain = bt->bt_id.bti_sub_domain; mp->bt_tbl_id.bt_hdr_len_id = bt->bt_id.bti_hdr_len; vl_api_send_msg (reg, (u8 *) mp); } static void vl_api_bier_table_dump_t_handler (vl_api_bier_table_dump_t * mp) { vl_api_registration_t *reg; bier_table_t *bt; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; pool_foreach(bt, bier_table_pool, ({ /* * skip the ecmp tables. */ if (bier_table_is_main(bt)) { send_bier_table_details(reg,
#!/usr/bin/env python

""" sanity check script """
import vpp_papi
fproto = (mp->bde_payload_proto == BIER_HDR_PROTO_IPV4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); if (brp->frp_flags & FIB_ROUTE_PATH_RPF_ID) { fti = mfib_table_find (fproto, ntohl (mp->bde_paths[ii].table_id)); } else { fti = fib_table_find (fproto, ntohl (mp->bde_paths[ii].table_id)); } if (INDEX_INVALID != fti) { brp->frp_fib_index = fti; } else { rv = VNET_API_ERROR_NO_SUCH_FIB; goto done; } break; } } } } if (mp->bde_is_add) { bier_disp_table_entry_path_add(table_id, bp, mp->bde_payload_proto, brps); } else { bier_disp_table_entry_path_remove(table_id, bp, mp->bde_payload_proto, brps); } done: vec_free(brps); rv = (rv == 0) ? vnm->api_errno : rv; REPLY_MACRO (VL_API_BIER_DISP_ENTRY_ADD_DEL_REPLY); } typedef struct bier_disp_entry_details_walk_t_ { vl_api_registration_t * reg; u32 context; } bier_disp_entry_details_walk_t; static void send_bier_disp_entry_details (const bier_disp_table_t *bdt, const bier_disp_entry_t *bde, u16 bp, void *args) { bier_disp_entry_details_walk_t *ctx = args; vl_api_bier_disp_entry_details_t *mp; bier_hdr_proto_id_t pproto; vl_api_fib_path_t *fp; u32 n_paths, m_size; FOR_EACH_BIER_HDR_PROTO(pproto) { fib_node_index_t pl = bde->bde_pl[pproto]; if (INDEX_INVALID != pl) { fib_path_encode_ctx_t path_ctx = { .rpaths = NULL, }; fib_route_path_t *rpath; n_paths = fib_path_list_get_n_paths(pl); m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t)); mp = vl_msg_api_alloc(m_size); if (!mp) return; clib_memset(mp, 0, m_size); mp->_vl_msg_id = ntohs(VL_API_BIER_DISP_ENTRY_DETAILS); mp->context = ctx->context; mp->bde_tbl_id = htonl(bdt->bdt_table_id); mp->bde_n_paths = htonl(n_paths); mp->bde_payload_proto = pproto; mp->bde_bp = htons(bp); fib_path_list_walk_w_ext(pl, NULL, fib_path_encode, &path_ctx); fp = mp->bde_paths; vec_foreach (rpath, path_ctx.rpaths) { fib_api_path_encode(rpath, fp); fp++; } vl_api_send_msg (ctx->reg, (u8 *) mp); vec_free(path_ctx.rpaths); } } } static void vl_api_bier_disp_entry_dump_t_handler (vl_api_bier_disp_entry_dump_t * mp) { vl_api_registration_t *reg; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; bier_disp_entry_details_walk_t ctx = { .reg = reg, .context = mp->context, }; bier_disp_table_walk(ntohl(mp->bde_tbl_id), send_bier_disp_entry_details, &ctx); } #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list static void setup_message_id_table (api_main_t * am) { #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); foreach_vl_msg_name_crc_bier; #undef _ } static clib_error_t * bier_api_hookup (vlib_main_t * vm) { api_main_t *am = vlibapi_get_main(); #define _(N,n) \ vl_msg_api_set_handlers(VL_API_##N, #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_bier_api_msg; #undef _ /* * Set up the (msg_name, crc, message-id) table */ setup_message_id_table (am); return 0; } VLIB_API_INIT_FUNCTION (bier_api_hookup);