/* *------------------------------------------------------------------ * 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; 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, mp->context, bt); } })); } static void vl_api_bier_route_add_del_t_handler (vl_api_bier_route_add_del_t * mp) { vl_api_bier_route_add_del_reply_t *rmp; fib_route_path_t *brpaths, *brpath; vnet_main_t *vnm; bier_bp_t bp; int rv = 0; u8 ii; vnm = vnet_get_main (); vnm->api_errno = 0; bp = ntohl(mp->br_bp); brpaths = NULL; if (mp->br_tbl_id.bt_hdr_len_id >= BIER_HDR_LEN_2048) { rv = VNET_API_ERROR_BIER_BSL_UNSUP; goto done; } if (0 == bp || bp > BIER_BP_MAX) { rv = -1; goto done; } bier_table_id_t bti = { .bti_set = mp->br_tbl_id.bt_set, .bti_sub_domain = mp->br_tbl_id.bt_sub_domain, .bti_hdr_len = mp->br_tbl_id.bt_hdr_len_id, .bti_type = BIER_TABLE_MPLS_SPF, .bti_ecmp = BIER_ECMP_TABLE_ID_MAIN, }; vec_validate(brpaths, mp->br_n_paths - 1); vec_foreach_index(ii, brpaths) { brpath = &brpaths[ii]; rv = fib_path_api_parse(&mp->br_paths[ii], brpath); if (0 != rv) { goto done; } } if (mp->br_is_add) { bier_table_route_add(&bti, bp, brpaths); } else { bier_table_route_remove(&bti, bp, brpaths); } vec_free(brpaths); done: rv = (rv == 0) ? vnm->api_errno : rv; REPLY_MACRO (VL_API_BIER_ROUTE_ADD_DEL_REPLY); } typedef struct bier_route_details_walk_t_ { vl_api_registration_t * reg; u32 context; } bier_route_details_walk_t; static void send_bier_route_details (const bier_table_t *bt, const bier_entry_t *be, void *args) { fib_route_path_encode_t *api_rpaths = NULL, *api_rpath; bier_route_details_walk_t *ctx = args; vl_api_bier_route_details_t *mp; vl_api_fib_path_t *fp; u32 n_paths, m_size; n_paths = fib_path_list_get_n_paths(be->be_path_list); m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t)); mp = vl_msg_api_alloc(m_size); if (!mp) return; memset(mp, 0, m_siz
/*
 * 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.
 */

#ifndef __DVR_DPO_H__
#define __DVR_DPO_H__

#include <vnet/dpo/dpo.h>

/**
 * @brief
 * The DVR DPO. Used as the resolving object for a DVR route.
 * This is used, in place of the usual L3 Adjacency, to retransmit
 * the packet with the original L2 header intact but also to run L3 features.
 * After running L3 features the packet is re-injected back into the L2 path
 * so it can pick up the necessary VLAN tags of the egress interface.
 * This re-injection is done with an output feature.
 */
typedef struct dvr_dpo_t_
{
    /**
     * The Software interface index that the packets will output on
     */
    u32 dd_sw_if_index;

    /**
     * The protocol of packets using this DPO
     */
    dpo_proto_t dd_proto;

    /**
     * number of locks.
     */
    u16 dd_locks;
} dvr_dpo_t;

extern void dvr_dp