aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python/Constants.py
blob: 8a22a4288d78f8bf92e110b044d121c839b802e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright (c) 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.

"""Constants used in CSIT."""


class Constants(object):
    """Constants used in CSIT.

    TODO: Yaml files are easier for humans to edit.
    Figure out how to set the attributes by parsing a file
    that works regardless of current working directory.
    """

    # OpenVPP testing directory location at topology nodes
    REMOTE_FW_DIR = '/tmp/openvpp-testing'

    # shell scripts location
    RESOURCES_LIB_SH = 'resources/libraries/bash'

    # Python API provider location
    RESOURCES_PAPI_PROVIDER = 'resources/tools/papi/vpp_papi_provider.py'

    # vat templates location
    RESOURCES_TPL_VAT = 'resources/templates/vat'

    # OpenVPP VAT binary name
    VAT_BIN_NAME = 'vpp_api_test'

    # VPP service unit name
    VPP_UNIT = 'vpp'

    # QEMU version to install
    QEMU_INSTALL_VERSION = 'qemu-2.11.2'

    # QEMU install directory
    QEMU_INSTALL_DIR = '/opt/qemu-2.11.2'

    # QEMU performance test VM kernel image path
    QEMU_PERF_VM_KERNEL = '/opt/boot/vmlinuz'

    # QEMU performance test VM nested image path
    QEMU_PERF_VM_IMAGE = '/var/lib/vm/csit-nested-1.7.img'

    # QEMU performance test VM DPDK path
    QEMU_PERF_VM_DPDK = '/opt/dpdk-19.02'

    # TRex install version
    TREX_INSTALL_VERSION = '2.35'

    # TRex install directory
    TREX_INSTALL_DIR = '/opt/trex-core-2.35'

    # Kubernetes templates location
    RESOURCES_TPL_K8S = 'resources/templates/kubernetes'

    # KernelVM templates location
    RESOURCES_TPL_VM = 'resources/templates/vm'

    # Honeycomb directory location at topology nodes:
    REMOTE_HC_DIR = '/opt/honeycomb'

    # Honeycomb persistence files location
    REMOTE_HC_PERSIST = '/var/lib/honeycomb/persist'

    # Honeycomb log file location
    REMOTE_HC_LOG = '/var/log/honeycomb/honeycomb.log'

    # Honeycomb templates location
    RESOURCES_TPL_HC = 'resources/templates/honeycomb'

    # ODL Client Restconf listener port
    ODL_PORT = 8181

    # Sysctl kernel.core_pattern
    KERNEL_CORE_PATTERN = '/tmp/%p-%u-%g-%s-%t-%h-%e.core'

    # Core dump directory
    CORE_DUMP_DIR = '/tmp'

    # Mapping from NIC name to its bps limit.
    # TODO: Implement logic to lower limits to TG NIC or software. Or PCI.
    NIC_NAME_TO_LIMIT = {
        # TODO: Explain why ~40Gbps NICs are using ~25Gbps limit.
        "Cisco-VIC-1227": 10000000000,
        "Cisco-VIC-1385": 24500000000,
        "Intel-X520-DA2": 10000000000,
        "Intel-X553": 10000000000,
        "Intel-X710": 10000000000,
        "Intel-XL710": 24500000000,
        "Intel-XXV710": 24500000000,
    }

    # Suite file names use somewhat more rich (less readable) codes for NICs.
    NIC_NAME_TO_CODE = {
        "Cisco-VIC-1227": "10ge2p1vic1227",
        "Cisco-VIC-1385": "40ge2p1vic1385",
        "Intel-X520-DA2": "10ge2p1x520",
        "Intel-X553": "10ge2p1x553",
        "Intel-X710": "10ge2p1x710",
        "Intel-XL710": "40ge2p1xl710",
        "Intel-XXV710": "25ge2p1xxv710",
    }

    # TODO CSIT-1481: Crypto HW should be read from topology file instead.
    NIC_NAME_TO_CRYPTO_HW = {
        "Intel-X553": "HW_C3xxx",
        "Intel-X710": "HW_DH895xcc",
        "Intel-XL710": "HW_DH895xcc",
    }

    PERF_TYPE_TO_KEYWORD = {
        "mrr": "Traffic should pass with maximum rate",
        "ndrpdr": "Find NDR and PDR intervals using optimized search",
        "soak": "Find critical load using PLRsearch",
    }

    PERF_TYPE_TO_SUITE_DOC_VER = {
        "mrr" : '''fication:* In MaxReceivedRate tests TG sends traffic\\
| ... | at line rate and reports total received packets over trial period.\\''',
        # TODO: Figure out how to include the full "*[Ver] TG verification:*"
        # while keeping this readable and without breaking line length limit.
        "ndrpdr": '''fication:* TG finds and reports throughput NDR (Non Drop\\
| ... | Rate) with zero packet loss tolerance and throughput PDR (Partial Drop\\
| ... | Rate) with non-zero packet loss tolerance (LT) expressed in percentage\\
| ... | of packets transmitted. NDR and PDR are discovered for different\\
| ... | Ethernet L2 frame sizes using MLRsearch library.\\''',
        "soak": '''fication:* TG sends traffic at dynamically computed\\
| ... | rate as PLRsearch algorithm gathers data and improves its estimate\\
| ... | of a rate at which a prescribed small fraction of packets\\
| ... | would be lost. After set time, the serarch stops\\
| ... | and the algorithm reports its current estimate.\\''',
    }

    PERF_TYPE_TO_TEMPLATE_DOC_VER = {
        "mrr": '''Measure MaxReceivedRate for ${frame_size}B frames\\
| | ... | using burst trials throughput test.\\''',
        "ndrpdr": '''Measure NDR and PDR values using MLRsearch algorithm.\\''',
        "soak": '''Estimate critical rate using PLRsearch algorithm.\\''',
    }
c noise_remote_t * wg_remote_get (const uint8_t public[NOISE_PUBLIC_KEY_LEN]) { index_t peeri; peeri = wg_peer_walk (wg_if_find_peer_by_public_key, (void *) public); if (INDEX_INVALID != peeri) return &wg_peer_get (peeri)->remote; return NULL; } static uint32_t wg_index_set (noise_remote_t * remote) { wg_main_t *wmp = &wg_main; u32 rnd_seed = (u32) (vlib_time_now (wmp->vlib_main) * 1e6); u32 ret = wg_index_table_add (&wmp->index_table, remote->r_peer_idx, rnd_seed); return ret; } static void wg_index_drop (uint32_t key) { wg_main_t *wmp = &wg_main; wg_index_table_del (&wmp->index_table, key); } static clib_error_t * wg_if_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) { vnet_hw_interface_t *hi; index_t wgii; u32 hw_flags; hi = vnet_get_hw_interface (vnm, hw_if_index); hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0); vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags); wgii = wg_if_find_by_sw_if_index (hi->sw_if_index); wg_if_peer_walk (wg_if_get (wgii), wg_peer_if_admin_state_change, NULL); return (NULL); } void wg_if_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) { index_t wgii; /* Convert any neighbour adjacency that has a next-hop reachable through * the wg interface into a midchain. This is to avoid sending ARP/ND to * resolve the next-hop address via the wg interface. Then, if one of the * peers has matching prefix among allowed prefixes, the midchain will be * updated to the corresponding one. */ adj_nbr_midchain_update_rewrite (ai, NULL, NULL, ADJ_FLAG_NONE, NULL); wgii = wg_if_find_by_sw_if_index (sw_if_index); wg_if_peer_walk (wg_if_get (wgii), wg_peer_if_adj_change, &ai); } /* *INDENT-OFF* */ VNET_DEVICE_CLASS (wg_if_device_class) = { .name = "Wireguard Tunnel", .format_device_name = format_wg_if_name, .admin_up_down_function = wg_if_admin_up_down, }; VNET_HW_INTERFACE_CLASS(wg_hw_interface_class) = { .name = "Wireguard", .update_adjacency = wg_if_update_adj, .flags = VNET_HW_INTERFACE_CLASS_FLAG_NBMA, }; /* *INDENT-ON* */ /* * Maintain a bitmap of allocated wg_if instance numbers. */ #define WG_ITF_MAX_INSTANCE (16 * 1024) static u32 wg_if_instance_alloc (u32 want) { /* * Check for dynamically allocated instance number. */ if (~0 == want) { u32 bit; bit = clib_bitmap_first_clear (wg_if_instances); if (bit >= WG_ITF_MAX_INSTANCE) { return ~0; } wg_if_instances = clib_bitmap_set (wg_if_instances, bit, 1); return bit; } /* * In range? */ if (want >= WG_ITF_MAX_INSTANCE) { return ~0; } /* * Already in use? */ if (clib_bitmap_get (wg_if_instances, want)) { return ~0; } /* * Grant allocation request. */ wg_if_instances = clib_bitmap_set (wg_if_instances, want, 1); return want; } static int wg_if_instance_free (u32 instance) { if (instance >= WG_ITF_MAX_INSTANCE) { return -1; } if (clib_bitmap_get (wg_if_instances, instance) == 0) { return -1; } wg_if_instances = clib_bitmap_set (wg_if_instances, instance, 0); return 0; } int wg_if_create (u32 user_instance, const u8 private_key[NOISE_PUBLIC_KEY_LEN], u16 port, const ip_address_t * src_ip, u32 * sw_if_indexp) { vnet_main_t *vnm = vnet_get_main (); u32 instance, hw_if_index; vnet_hw_interface_t *hi; wg_if_t *wg_if; noise_local_t *local; ASSERT (sw_if_indexp); *sw_if_indexp = (u32) ~ 0; /* * Allocate a wg_if instance. Either select on dynamically * or try to use the desired user_instance number. */ instance = wg_if_instance_alloc (user_instance); if (instance == ~0) return VNET_API_ERROR_INVALID_REGISTRATION; /* *INDENT-OFF* */ struct noise_upcall upcall = { .u_remote_get = wg_remote_get, .u_index_set = wg_index_set, .u_index_drop = wg_index_drop, }; /* *INDENT-ON* */ pool_get (noise_local_pool, local); noise_local_init (local, &upcall); if (!noise_local_set_private (local, private_key)) { pool_put (noise_local_pool, local); wg_if_instance_free (instance); return VNET_API_ERROR_INVALID_REGISTRATION; } pool_get (wg_if_pool, wg_if); /* tunnel index (or instance) */ u32 t_idx = wg_if - wg_if_pool; wg_if->user_instance = instance; if (~0 == wg_if->user_instance) wg_if->user_instance = t_idx; vec_validate_init_empty (wg_if_indexes_by_port, port, NULL); if (vec_len (wg_if_indexes_by_port[port]) == 0) { udp_register_dst_port (vlib_get_main (), port, wg4_input_node.index, UDP_IP4); udp_register_dst_port (vlib_get_main (), port, wg6_input_node.index, UDP_IP6); } vec_add1 (wg_if_indexes_by_port[port], t_idx); wg_if->port = port; wg_if->local_idx = local - noise_local_pool; cookie_checker_update (&wg_if->cookie_checker, local->l_public); hw_if_index = vnet_register_interface (vnm, wg_if_device_class.index, t_idx, wg_hw_interface_class.index, t_idx); hi = vnet_get_hw_interface (vnm, hw_if_index); vec_validate_init_empty (wg_if_index_by_sw_if_index, hi->sw_if_index, INDEX_INVALID); wg_if_index_by_sw_if_index[hi->sw_if_index] = t_idx; ip_address_copy (&wg_if->src_ip, src_ip); wg_if->sw_if_index = *sw_if_indexp = hi->sw_if_index; vnet_set_interface_l3_output_node (vnm->vlib_main, hi->sw_if_index, (u8 *) "tunnel-output"); return 0; } int wg_if_delete (u32 sw_if_index) { vnet_main_t *vnm = vnet_get_main (); if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) return VNET_API_ERROR_INVALID_SW_IF_INDEX; vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); if (hw == 0 || hw->dev_class_index != wg_if_device_class.index) return VNET_API_ERROR_INVALID_VALUE; wg_if_t *wg_if; index_t wgii = wg_if_find_by_sw_if_index (sw_if_index); wg_if = wg_if_get (wgii); if (NULL == wg_if) return VNET_API_ERROR_INVALID_SW_IF_INDEX_2; if (wg_if_instance_free (wg_if->user_instance) < 0) return VNET_API_ERROR_INVALID_VALUE_2; // Remove peers before interface deletion wg_if_peer_walk (wg_if, wg_peer_if_delete, NULL); index_t *ii; index_t *ifs = wg_if_indexes_get_by_port (wg_if->port); vec_foreach (ii, ifs) { if (*ii == wgii) { vec_del1 (ifs, ifs - ii); break; } } if (vec_len (ifs) == 0) { udp_unregister_dst_port (vlib_get_main (), wg_if->port, 1); udp_unregister_dst_port (vlib_get_main (), wg_if->port, 0); } vnet_reset_interface_l3_output_node (vnm->vlib_main, sw_if_index); vnet_delete_hw_interface (vnm, hw->hw_if_index); pool_put_index (noise_local_pool, wg_if->local_idx); pool_put (wg_if_pool, wg_if); return 0; } void wg_if_peer_add (wg_if_t * wgi, index_t peeri) { hash_set (wgi->peers, peeri, peeri); if (1 == hash_elts (wgi->peers)) { vnet_feature_enable_disable ("ip4-output", "wg4-output-tun", wgi->sw_if_index, 1, 0, 0); vnet_feature_enable_disable ("ip6-output", "wg6-output-tun", wgi->sw_if_index, 1, 0, 0); } } void wg_if_peer_remove (wg_if_t * wgi, index_t peeri) { hash_unset (wgi->peers, peeri); if (0 == hash_elts (wgi->peers)) { vnet_feature_enable_disable ("ip4-output", "wg4-output-tun", wgi->sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip6-output", "wg6-output-tun", wgi->sw_if_index, 0, 0, 0); } } void wg_if_walk (wg_if_walk_cb_t fn, void *data) { index_t wgii; /* *INDENT-OFF* */ pool_foreach_index (wgii, wg_if_pool) { if (WALK_STOP == fn(wgii, data)) break; } /* *INDENT-ON* */ } index_t wg_if_peer_walk (wg_if_t * wgi, wg_if_peer_walk_cb_t fn, void *data) { index_t peeri, val; /* *INDENT-OFF* */ hash_foreach (peeri, val, wgi->peers, { if (WALK_STOP == fn (peeri, data)) return peeri; }); /* *INDENT-ON* */ return INDEX_INVALID; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */