/* * Copyright (c) 2017-2019 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 #define __plugin_msg_base hicn_test_main.msg_id_base #include #include #include "error.h" // uword unformat_sw_if_index(unformat_input_t * input, va_list * args); /* Declare message IDs */ #include "hicn_msg_enum.h" /* declare message handlers for each api */ #define vl_endianfun /* define message structures */ #include "hicn_all_api_h.h" #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) #define vl_printfun #include "hicn_all_api_h.h" #undef vl_printfun /* Get the API version number. */ #define vl_api_version(n, v) static u32 api_version=(v); #include "hicn_all_api_h.h" #undef vl_api_version /* SUPPORTING FUNCTIONS NOT LOADED BY VPP_API_TEST */ uword unformat_ip46_address (unformat_input_t * input, va_list * args) { ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); ip46_type_t type = va_arg (*args, ip46_type_t); if ((type != IP46_TYPE_IP6) && unformat (input, "%U", unformat_ip4_address, &ip46->ip4)) { ip46_address_mask_ip4 (ip46); return 1; } else if ((type != IP46_TYPE_IP4) && unformat (input, "%U", unformat_ip6_address, &ip46->ip6)) { return 1; } return 0; } ///////////////////////////////////////////////////// #define HICN_FACE_NULL ~0 typedef struct { /* API message ID base */ u16 msg_id_base; vat_main_t *vat_main; } hicn_test_main_t; hicn_test_main_t hicn_test_main; #define foreach_standard_reply_retval_handler \ _(hicn_api_node_params_set_reply) \ _(hicn_api_face_ip_del_reply) \ _(hicn_api_route_nhops_add_reply) \ _(hicn_api_route_del_reply) \ _(hicn_api_route_nhop_del_reply) #define _(n) \ static void vl_api_##n##_t_handler \ (vl_api_##n##_t * mp) \ { \ vat_main_t * vam = hicn_test_main.vat_main; \ i32 retval = ntohl(mp->retval); \ if (vam->async_mode) { \ vam->async_errors += (retval < 0); \ } else { \ fformat (vam->ofp,"%s\n", get_error_string(retval));\ vam->retval = retval; \ vam->result_ready = 1; \ } \ } foreach_standard_reply_retval_handler; #undef _ /* * Table of message reply handlers, must include boilerplate handlers we just * generated */ #define foreach_vpe_api_reply_msg \ _(HICN_API_NODE_PARAMS_SET_REPLY, hicn_api_node_params_set_reply) \ _(HICN_API_NODE_PARAMS_GET_REPLY, hicn_api_node_params_get_reply) \ _(HICN_API_NODE_STATS_GET_REPLY, hicn_api_node_stats_get_reply) \ _(HICN_API_FACE_IP_DEL_REPLY, hicn_api_face_ip_del_reply) \ _(HICN_API_FACE_IP_ADD_REPLY, hicn_api_face_ip_add_reply) \ _(HICN_API_ROUTE_NHOPS_ADD_REPLY, hicn_api_route_nhops_add_reply) \ _(HICN_API_FACE_IP_PARAMS_GET_REPLY, hicn_api_face_ip_params_get_reply) \ _(HICN_API_ROUTE_GET_REPLY, hicn_api_route_get_reply) \ _(HICN_API_ROUTE_DEL_REPLY, hicn_api_route_del_reply) \ _(HICN_API_ROUTE_NHOP_DEL_REPLY, hicn_api_route_nhop_del_reply) \ _(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \ _(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \ _(HICN_API_REGISTER_PROD_APP_REPLY, hicn_api_register_prod_app_reply) \ _(HICN_API_REGISTER_CONS_APP_REPLY, hicn_api_register_cons_app_reply) static int api_hicn_api_node_params_set (vat_main_t * vam) { unformat_input_t *input = vam->input; int enable_disable = 1; int pit_size = -1, cs_size = -1; f64 pit_dflt_lifetime_sec = -1.0f; f64 pit_min_lifetime_sec = -1.0f, pit_max_lifetime_sec = -1.0f; int ret; vl_api_hicn_api_node_params_set_t *mp; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) { enable_disable = 0; } else if (unformat (input, "PIT size %d", &pit_size)) {; } else if (unformat (input, "CS size %d", &cs_size)) {; } else if (unformat (input, "PIT dfltlife %f", &pit_dflt_lifetime_sec)) {; } else if (unformat (input, "PIT minlife %f", &pit_min_lifetime_sec)) {; } else if (unformat (input, "PIT maxlife %f", &pit_max_lifetime_sec)) {; } else { break; } } /* Construct the API message */ M (HICN_API_NODE_PARAMS_SET, mp); mp->enable_disable = enable_disable; mp->pit_max_size = clib_host_to_net_i32 (pit_size); mp->cs_max_size = clib_host_to_net_i32 (cs_size); mp->pit_dflt_lifetime_sec = pit_dflt_lifetime_sec; mp->pit_min_lifetime_sec = pit_min_lifetime_sec; mp->pit_max_lifetime_sec = pit_max_lifetime_sec; /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static int api_hicn_api_node_params_get (vat_main_t * vam) { vl_api_hicn_api_node_params_get_t *mp; int ret; //Construct the A
from vpp_interface import VppInterface


class VppMPLSTunnelInterface(VppInterface):
    """
    VPP MPLS Tunnel interface
    """

    def __init__(self, test, paths, is_multicast=0, is_l2=0):
        """Create MPLS Tunnel interface"""
        super(VppMPLSTunnelInterface, self).__init__(test)
        self.t_paths = paths
        self.is_multicast = is_multicast
        self.is_l2 = is_l2
        self.encoded_paths = []
        for path in self.t_paths:
            self.encoded_paths.append(path.encode())

    def add_vpp_config(self):
        reply = self.test.vapi.mpls_tunnel_add_del(
            0xFFFFFFFF,
            self.encoded_paths,
            is_multicast=self.is_multicast,
            l2_only=self.is_l2,
        )
        self.set_sw_if_index(reply.sw_if_index)
        self.tunnel_index = reply.tunnel_index
        self._test.registry.register(self, self._test.logger)

    def remove_vpp_config(self):
        reply = self.test.vapi.mpls_tunnel_add_del(
            self.sw_if_index, self.encoded_paths, is_add=0
        )

    def query_vpp_config(self):
        dump = self._test.vapi.mpls_tunnel_dump()
        for t in dump:
            if (
                self.sw_if_index == t.mt_tunnel.mt_sw_if_index
                and self.tunnel_index == t.mt_tunnel.mt_tunnel_index
            ):
                return True
        return False

    def object_id(self):
        return "mpls-tunnel%d-%d" % (self.tunnel_index, self.sw_if_index)
clib_net_to_host_i32 (mp->n_strategies); vec_reset_length (sbuf); sbuf = format (sbuf, "Available strategies:\n"); int i; for (i = 0; i < n_strategies; i++) { u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id[i]); sbuf = format (sbuf, "%d ", strategy_id); } fformat (vam->ofp, "%s", sbuf); } static int api_hicn_api_strategy_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_strategy_get_t *mp; int ret; u32 strategy_id = HICN_STRATEGY_NULL; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "strategy %d", strategy_id)) {; } else { break; } } if (strategy_id == HICN_STRATEGY_NULL) { clib_warning ("Please specify strategy id..."); return 1; } /* Construct the API message */ M (HICN_API_STRATEGY_GET, mp); mp->strategy_id = clib_host_to_net_u32 (strategy_id); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_strategy_get_reply_t_handler (vl_api_hicn_api_strategy_get_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } fformat (vam->ofp, "%s", mp->description); } static int api_hicn_api_register_prod_app (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_register_prod_app_t *mp; ip46_address_t prefix; int plen; u32 swif = ~0; int ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "prefix %U/%d", unformat_ip46_address, &prefix, IP46_TYPE_ANY, &plen)) {; } else if (unformat (input, "id %d", &swif)) {; } else { break; } } /* Check parse */ if (((prefix.as_u64[0] == 0) && (prefix.as_u64[1] == 0)) || (plen == 0)) { clib_warning ("Please specify prefix..."); return 1; } /* Construct the API message */ M (HICN_API_REGISTER_PROD_APP, mp); mp->prefix[0] = clib_host_to_net_u64 (prefix.as_u64[0]); mp->prefix[1] = clib_host_to_net_u64 (prefix.as_u64[1]); mp->len = (u8) plen; mp->swif = clib_host_to_net_u32 (swif); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_register_prod_app_reply_t_handler (vl_api_hicn_api_register_prod_app_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } } static int api_hicn_api_register_cons_app (vat_main_t * vam) { vl_api_hicn_api_register_cons_app_t *mp; int ret; /* Construct the API message */ M (HICN_API_REGISTER_CONS_APP, mp); /* send it... */ S (mp); /* Wait for a reply... */ W (ret); return ret; } static void vl_api_hicn_api_register_cons_app_reply_t_handler (vl_api_hicn_api_register_cons_app_reply_t * mp) { vat_main_t *vam = hicn_test_main.vat_main; i32 retval = ntohl (mp->retval); if (vam->async_mode) { vam->async_errors += (retval < 0); return; } vam->retval = retval; vam->result_ready = 1; if (vam->retval < 0) { //vpp_api_test infra will also print out string form of error fformat (vam->ofp, " (API call error: %d)\n", vam->retval); return; } ip4_address_t src_addr4; src_addr4.as_u32 = clib_net_to_host_u32 (mp->src_addr4); ip6_address_t src_addr6; src_addr6.as_u64[0] = clib_net_to_host_u64 (mp->src_addr6[0]); src_addr6.as_u64[1] = clib_net_to_host_u64 (mp->src_addr6[1]); fformat (vam->ofp, "ip4 address %U\n" "ip6 address :%U\n" "appif id :%d\n", format_ip4_address, &src_addr4, format_ip6_address, &src_addr6); } /* * List of messages that the api test plugin sends, and that the data plane * plugin processes */ #define foreach_vpe_api_msg \ _(hicn_api_node_params_set, "PIT size CS size " \ "PIT minlimit PIT maxlimit [disable] ") \ _(hicn_api_node_params_get, "") \ _(hicn_api_node_stats_get, "") \ _(hicn_api_face_ip_del, "face ") \ _(hicn_api_face_ip_add, "add
") \ _(hicn_api_route_nhops_add, "add prefix / face weight ") \ _(hicn_api_face_ip_params_get, "face ") \ _(hicn_api_route_get, "prefix /") \ _(hicn_api_route_del, "prefix /") \ _(hicn_api_route_nhop_del, "del prefix / face ") \ _(hicn_api_strategies_get, "") \ _(hicn_api_strategy_get, "strategy ") \ _(hicn_api_register_prod_app, "prefix / id ") \ _(hicn_api_register_cons_app, "") void hicn_vat_api_hookup (vat_main_t * vam) { hicn_test_main_t *sm = &hicn_test_main; /* Hook up handlers for replies from the data plane plug-in */ #define _(N, n) \ vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ #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_vpe_api_reply_msg; #undef _ /* API messages we can send */ #define _(n, h) hash_set_mem (vam->function_by_name, #n, api_##n); foreach_vpe_api_msg; #undef _ /* Help strings */ #define _(n, h) hash_set_mem (vam->help_by_name, #n, h); foreach_vpe_api_msg; #undef _ } clib_error_t * vat_plugin_register (vat_main_t * vam) { hicn_test_main_t *sm = &hicn_test_main; u8 *name; sm->vat_main = vam; /* Ask the vpp engine for the first assigned message-id */ name = format (0, "hicn_%08x%c", api_version, 0); sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~ 0) hicn_vat_api_hookup (vam); vec_free (name); return 0; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: */