/* * Copyright (c) 2015 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. */ /* * interface.h: VNET interfaces/sub-interfaces * * Copyright (c) 2008 Eliot Dresselhaus * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef included_vnet_interface_h #define included_vnet_interface_h #include #include #include #include struct vnet_main_t; struct vnet_hw_interface_t; struct vnet_sw_interface_t; union ip46_address_t_; typedef enum { VNET_HW_IF_RX_MODE_UNKNOWN, VNET_HW_IF_RX_MODE_POLLING, VNET_HW_IF_RX_MODE_INTERRUPT, VNET_HW_IF_RX_MODE_ADAPTIVE, VNET_HW_IF_RX_MODE_DEFAULT, VNET_HW_IF_NUM_RX_MODES, } vnet_hw_if_rx_mode; /* Interface up/down callback. */ typedef clib_error_t *(vnet_interface_function_t) (struct vnet_main_t * vnm, u32 if_index, u32 flags); /* Sub-interface add/del callback. */ typedef clib_error_t *(vnet_subif_add_del_function_t) (struct vnet_main_t * vnm, u32 if_index, struct vnet_sw_interface_t * template, int is_add); /* Interface set mac address callback. */ typedef clib_error_t *(vnet_interface_set_mac_address_function_t) (struct vnet_hw_interface_t * hi, const u8 * old_address, const u8 * new_address); /* Interface add/del additional mac address callback */ typedef clib_error_t *(vnet_interface_add_del_mac_address_function_t) (struct vnet_hw_interface_t * hi, const u8 * address, u8 is_add); /* Interface set rx mode callback. */ typedef clib_error_t *(vnet_interface_set_rx_mode_function_t) (struct vnet_main_t * vnm, u32 if_index, u32 queue_id, vnet_hw_if_rx_mode mode); /* Interface set l2 mode callback. */ typedef clib_error_t *(vnet_interface_set_l2_mode_function_t) (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi, i32 l2_if_adjust); /* Interface to set rss queues of the interface */ typedef clib_error_t *(vnet_interface_rss_queues_set_t) (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi, clib_bitmap_t * bitmap); typedef enum { VNET_FLOW_DEV_OP_ADD_FLOW, VNET_FLOW_DEV_OP_DEL_FLOW, VNET_FLOW_DEV_OP_GET_COUNTER, VNET_FLOW_DEV_OP_RESET_COUNTER, } vnet_flow_dev_op_t; /* Interface flow operations callback. */ typedef int (vnet_flow_dev_ops_function_t) (struct vnet_main_t * vnm, vnet_flow_dev_op_t op, u32 hw_if_index, u32 index, uword * private_data); typedef enum vnet_interface_function_priority_t_ { VNET_ITF_FUNC_PRIORITY_LOW, VNET_ITF_FUNC_PRIORITY_HIGH, } vnet_interface_function_priority_t; #define VNET_ITF_FUNC_N_PRIO ((vnet_interface_function_priority_t)VNET_ITF_FUNC_PRIORITY_HIGH+1) typedef struct _vnet_interface_function_list_elt { struct _vnet_interface_function_list_elt *next_interface_function; clib_error_t *(*fp) (struct vnet_main_t * vnm, u32 if_index, u32 flags); } _vnet_interface_function_list_elt_t; #ifndef CLIB_MARCH_VARIANT #define _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,tag,p) \ \ static void __vnet_interface_function_init_##tag##_##f (void) \ __attribute__((__constructor__)) ; \ \ static void __vnet_interface_function_init_##tag##_##f (void) \ { \ vnet_main_t * vnm = vnet_get_main(); \ static _vnet_interface_function_list_elt_t init_function; \ init_function.next_interface_function = vnm->tag##_functions[p]; \ vnm->tag##_functions[p] = &init_function; \ init_function.fp = (void *) &f; \ } \ static void __vnet_interface_function_deinit_##tag##_##f (void) \ __attribute__((__destructor__)) ; \ \ static void __vnet_interface_function_deinit_##tag##_##f (void) \ { \ vnet_main_t * vnm = vnet_get_main(); \ _vnet_interface_function_list_elt_t *next; \ if (vnm->tag##_functions[p]->fp == f) \ { \ vnm->tag##_functions[p] = \ vnm->tag##_functions[p]->next_interface_function; \ return; \ } \ next = vnm->tag##_functions[p]; \ while (next->next_interface_function) \ { \ if (next->next_interface_function->fp == f) \ { \ next->next_interface_function = \ next->next_interface_function->next_interface_function; \ return; \ } \ next = next->next_interface_function; \ } \ } #else /* create unused pointer to silence compiler warnings and get whole function optimized out */ #define _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,tag,p) \ static __clib_unused void * __clib_unused_##f = f; #endif #define _VNET_INTERFACE_FUNCTION_DECL(f,tag) \ _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,tag,VNET_ITF_FUNC_PRIORITY_LOW) #define VNET_HW_INTERFACE_ADD_DEL_FUNCTION(f) \ _VNET_INTERFACE_FUNCTION_DECL(f,hw_interface_add_del) #define VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(f) \ _VNET_INTERFACE_FUNCTION_DECL(f,hw_interface_link_up_down) #define VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION_PRIO(f,p) \ _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,hw_interface_link_up_down,p) #define VNET_SW_INTERFACE_MTU_CHANGE_FUNCTION(f) \ _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_mtu_change) #define VNET_SW_INTERFACE_ADD_DEL_FUNCTION(f) \ _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_add_del) #define VNET_SW_INTERFACE_ADD_DEL_FUNCTION_PRIO(f,p) \ _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,sw_interface_add_del,p) #define VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(f) \ _VNET_INTERFACE_FUNCTION_DECL(f,sw_interface_admin_up_down) #define VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(f,p) \ _VNET_INTERFACE_FUNCTION_DECL_PRIO(f,sw_interface_admin_up_down, p) /** * Tunnel description parameters */ typedef int (*vnet_dev_class_ip_tunnel_desc_t) (u32 sw_if_index, union ip46_address_t_ * src, union ip46_address_t_ * dst, u8 * is_l2); /* A class of hardware interface devices. */ typedef struct _vnet_device_class { /* Index into main vector. */ u32 index; /* Device name (e.g. "FOOBAR 1234a"). */ char *name; /* Function to call when hardware interface is added/deleted. */ vnet_interface_function_t *interface_add_del_function; /* Function to bring device administratively up/down. */ vnet_interface_function_t *admin_up_down_function; /* Function to call when sub-interface is added/deleted */ vnet_subif_add_del_function_t *subif_add_del_function; /* Function to call interface rx mode is changed */ vnet_interface_set_rx_mode_function_t *rx_mode_change_function; /* Function to call interface l2 mode is changed */ vnet_interface_set_l2_mode_function_t *set_l2_mode_function; /* Redistribute flag changes/existence of this interface class. */ u32 redistribute; /* Transmit function. */ vlib_node_function_t *tx_function; /* Transmit function candidate registration with priority */ vlib_node_fn_registration_t *tx_fn_registrations; /* Error strings indexed by error code for this node. */ char **tx_function_error_strings; vlib_error_desc_t *tx_function_error_counters; /* Number of error codes used by this node. */ u32 tx_function_n_errors; /* Renumber device name [only!] support, a control-plane kludge */ int (*name_renumber) (struct vnet_hw_interface_t * hi, u32 new_dev_instance); /* Interface flow offload operations */ vnet_flow_dev_ops_function_t *flow_ops_function; /* Format device instance as name. */ format_function_t *format_device_name; /* Parse function for device name. */ unformat_function_t *unformat_device_name; /* Format device verbosely for this class. */ format_function_t *format_device; /* Trace buffer format for TX function. */ format_function_t *format_tx_trace; /* Format flow offload entry */ format_function_t *format_flow; vnet_dev_class_ip_tunnel_desc_t ip_tun_desc; /* Function to clear hardware counters for device. */ void (*clear_counters) (u32 dev_class_instance); uword (*is_valid_class_for_interface) (struct vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index); /* Called when hardware class of an interface changes. */ void (*hw_class_change) (struct vnet_main_t * vnm, u32 hw_if_index, u32 new_hw_class_index); /* Called to redirect traffic from a specific interface instance */ void (*rx_redirect_to_node) (struct vnet_main_t * vnm, u32 hw_if_index, u32 node_index); /* Link-list of all device classes set up by constructors created below */ struct _vnet_device_class *next_class_registration; /* Function to set mac address. */ vnet_interface_set_mac_address_function_t *mac_addr_change_function; /* Function to add/delete additional MAC addresses */ vnet_interface_add_del_mac_address_function_t *mac_addr_add_del_function; /* Interface to set rss queues of the interface */ vnet_interface_rss_queues_set_t *set_rss_queues_function; } vnet_device_class_t; #ifndef CLIB_MARCH_VARIANT #define VNET_DEVICE_CLASS(x,...) \ __VA_ARGS__ vnet_device_class_t x; \ static void __vnet_add_device_class_registration_##x (void) \ __attribute__((__constructor__)) ; \ static void __vnet_add_device_class_registration_##x (void) \ { \ vnet_main_t * vnm = vnet_get_main(); \ x.next_class_registration = vnm->device_class_registrations; \ vnm->device_class_registrations = &x; \ } \ static void __vnet_rm_device_class_registration_##x (void) \ __attribute__((__destructor__)) ; \ static void __vnet_rm_device_class_registration_##x (void) \ { \ vnet_main_t * vnm = vnet_get_main(); \ VLIB_REMOVE_FROM_LINKED_LIST (vnm->device_class_registrations, \ &x, next_class_registration); \ } \ __VA_ARGS__ vnet_device_class_t x #else /* create unused pointer to silence compiler warnings and get whole function optimized out */ #define VNET_DEVICE_CLASS(x,...) \ static __clib_unused vnet_device_class_t __clib_unused_##x #endif #define VNET_DEVICE_CLASS_TX_FN(devclass) \ uword CLIB_MARCH_SFX (devclass##_tx_fn) (); \ static vlib_node_fn_registration_t CLIB_MARCH_SFX ( \ devclass##_tx_fn_registration) = { \ .function = &CLIB_MARCH_SFX (devclass##_tx_fn), \ }; \ \ static void __clib_constructor CLIB_MARCH_SFX ( \ devclass##_tx_fn_multiarch_register) (void) \ { \ extern vnet_device_class_t devclass; \ vlib_node_fn_registration_t *r; \ r = &CLIB_MARCH_SFX (devclass##_tx_fn_registration); \ r->march_variant = CLIB_MARCH_SFX (CLIB_MARCH_VARIANT_TYPE); \ r->next_registration = devclass.tx_fn_registrations; \ devclass.tx_fn_registrations = r; \ } \ uword CLIB_MARCH_SFX (devclass##_tx_fn) /** * Link Type: A description of the protocol of packets on the link. * On an ethernet link this maps directly into the ethertype. On a GRE tunnel * it maps to the GRE-proto, etc for other lnk types. */ typedef enum vnet_link_t_ { #if CLIB_DEBUG > 0 VNET_LINK_IP4 = 1, #else VNET_LINK_IP4 = 0, #endif VNET_LINK_IP6, VNET_LINK_MPLS, VNET_LINK_ETHERNET, VNET_LINK_ARP, VNET_LINK_NSH, } __attribute__ ((packed)) vnet_link_t; #define VNET_LINKS { \ [VNET_LINK_ETHERNET] = "ethernet", \ [VNET_LINK_IP4] = "ipv4", \ [VNET_LINK_IP6] = "ipv6", \ [VNET_LINK_MPLS] = "mpls", \ [VNET_LINK_ARP] = "arp", \ [VNET_LINK_NSH] = "nsh", \ } #define FOR_EACH_VNET_LINK(_link) \ for (_link = VNET_LINK_IP4; \ _link <= VNET_LINK_NSH; \ _link++) #define FOR_EACH_VNET_IP_LINK(_link) \ for (_link = VNET_LINK_IP4; \ _link <= VNET_LINK_IP6; \ _link++) /** * @brief Number of link types. Not part of the enum so it does not have to be * included in switch statements */ #define VNET_LINK_NUM (VNET_LINK_NSH+1) #define VNET_N_LINKS VNET_LINK_NUM /** * @brief Convert a link to to an Et
# Copyright (c) 2018 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.

*** Settings ***
| Resource | resources/libraries/robot/performance/performance_setup.robot
| ...
| Force Tags | 3_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | MRR
| ... | NIC_Intel-X710 | ETH | L2XCFWD | BASE | L2XCBASE
| ...
| Suite Setup | Set up 3-node performance topology with DUT's NIC model
| ... | L2 | Intel-X710
| ...
| Suite Teardown | Tear down 3-node performance topology
| ...
| Test Setup | Set up performance test
| ...
| Test Teardown | Tear down performance mrr test
| ...
| Test Template | Local Template
| ...
| Documentation | *Raw results L2XC test cases*
| ...
| ... | *[Top] Network Topologies:* TG-DUT1-DUT2-TG 3-node circular topology
| ... | with single links between nodes.
| ... | *[Enc] Packet Encapsulations:* Eth-IPv4 for L2 cross connect.
| ... | *[Cfg] DUT configuration:* DUT1 and DUT2 are configured with L2 cross-
| ... | connect. DUT1 and DUT2 tested with 2p10GE NIC X710 by Intel.
| ... | *[Ver] TG verification:* In MaxReceivedRate tests TG sends traffic
| ... | at line rate and reports total received/sent packets over trial period.
| ... | Test packets are generated by TG on links to DUTs. TG traffic profile
| ... | contains two L3 flow-groups (flow-group per direction, 253 flows per
| ... | flow-group) with all packets containing Ethernet header, IPv4 header
| ... | with IP protocol=61 and static payload. MAC addresses are matching MAC
| ... | addresses of the TG node interfaces.
| ... | *[Ref] Applicable standard specifications:* RFC2544.

*** Variables ***
# X710-DA2 bandwidth limit
| ${s_limit}= | ${10000000000}
# Traffic profile:
| ${traffic_profile}= | trex-sl-3n-ethip4-ip4src254

*** Keywords ***
| Local Template
| | [Documentation]
| | ... | [Cfg] DUT runs L2XC config with ${phy_cores} phy
| | ... | core(s).
| | ... | [Ver] Measure MaxReceivedRate for ${framesize}B frames using single\
| | ... | trial throughput test.
| | ...
| | ... | *Arguments:*
| | ... | - framesize - Framesize in Bytes in integer or string (IMIX_v4_1).
| | ... | Type: integer, string
| | ... | - phy_cores - Number of physical cores. Type: integer
| | ... | - rxq - Number of RX queues, default value: ${None}. Type: integer
| | ...
| | [Arguments] | ${framesize} | ${phy_cores} | ${rxq}=${None}
| | ...
| | Given Add worker threads and rxqueues to all DUTs | ${phy_cores} | ${rxq}
| | And Add PCI devices to all DUTs
| | ${max_rate} | ${jumbo} = | Get Max Rate And Jumbo And Handle Multi Seg
| | ... | ${s_limit} | ${framesize}
| | And Apply startup configuration on all VPP DUTs
| | And Initialize L2 xconnect in 3-node circular topology
| | Then Traffic should pass with maximum rate
| | ... | ${max_rate}pps | ${framesize} | ${traffic_profile}

*** Test Cases ***
| tc01-64B-1c-eth-l2xcbase-mrr
| | [Tags] | 64B | 1C
| | framesize=${64} | phy_cores=${1}

| tc02-64B-2c-eth-l2xcbase-mrr
| | [Tags] | 64B | 2C
| | framesize=${64} | phy_cores=${2}

| tc03-64B-4c-eth-l2xcbase-mrr
| | [Tags] | 64B | 4C
| | framesize=${64} | phy_cores=${4}

| tc04-1518B-1c-eth-l2xcbase-mrr
| | [Tags] | 1518B | 1C
| | framesize=${1518} | phy_cores=${1}

| tc05-1518B-2c-eth-l2xcbase-mrr
| | [Tags] | 1518B | 2C
| | framesize=${1518} | phy_cores=${2}

| tc06-1518B-4c-eth-l2xcbase-mrr
| | [Tags] | 1518B | 4C
| | framesize=${1518} | phy_cores=${<