aboutsummaryrefslogtreecommitdiffstats
path: root/tests/suites/honeycomb/3 - bridge_domain.robot
blob: e99b659b3f9bf797755fd2cc6f9a827ad04bf9fa (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
# 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.

*** Variables ***
# Node and interfaces to run tests on.
| ${node}= | ${nodes['DUT1']}
| @{interfaces}= | ${node['interfaces']['port1']['name']}
| ... | ${node['interfaces']['port3']['name']}
# Configuration which will be set and verified during tests.
| ${bd1_name}= | bd-01
| ${bd2_name}= | bd-02
| &{bd_settings}= | flood=${True} | forward=${True} | learn=${True}
| ... | unknown-unicast-flood=${True} | arp-termination=${True}
| &{if_settings}= | split_horizon_group=${1} | bvi=${True}

*** Settings ***
| Resource | resources/libraries/robot/default.robot
| Resource | resources/libraries/robot/honeycomb/interfaces.robot
| Resource | resources/libraries/robot/honeycomb/bridge_domain.robot
| Documentation | *Honeycomb bridge domain management test suite.*
| ...
| ... | Test suite uses the first two interfaces on the first DUT node.

*** Test Cases ***
| Honeycomb sets up l2 bridge domain
| | [Documentation] | Check if Honeycomb can create bridge domains on VPP node.
| | [Tags] | honeycomb_sanity
| | When Honeycomb creates first l2 bridge domain
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | Then Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | And Bridge domain configuration from VAT should be
| | ... | ${node} | ${0} | ${bd_settings}

| Honeycomb assigns interfaces to bridge domain
| | [Documentation] | Check if Honeycomb can assign VPP interfaces to an\
| | ... | existing bridge domain.
| | [Tags] | honeycomb_sanity
| | Given Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | When Honeycomb adds interfaces to bridge domain
| | ... | ${node} | @{interfaces} | ${bd1_name} | ${if_settings}
| | Then Honeycomb should show interfaces assigned to bridge domain
| | ... | ${node} | @{interfaces} | ${bd1_name} | ${if_settings}
| | And VAT should show interfaces assigned to bridge domain
| | ... | ${node} | ${0} | @{interfaces} | ${if_settings}

| Honeycomb manages multiple bridge domains on node
| | [Documentation] | Check if Honeycomb can manage multiple bridge domains on\
| | ... | a single node.
| | [Tags] | honeycomb_sanity
| | Given Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | When Honeycomb creates l2 bridge domain
| | ... | ${node} | ${bd2_name} | ${bd_settings}
| | Then Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | And Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd2_name} | ${bd_settings}
| | And Bridge domain configuration from VAT should be
| | ... | ${node} | ${0} | ${bd_settings}
| | And Bridge domain configuration from VAT should be
| | ... | ${node} | ${1} | ${bd_settings}

| Honeycomb removes bridge domains
| | [Documentation] | Check if Honeycomb can remove bridge domains from a VPP\
| | ... | node.
| | [Tags] | honeycomb_sanity
| | Given Bridge domain configuration from Honeycomb should be
| | ... | ${node} | ${bd1_name} | ${bd_settings}
| | When Honeycomb removes all bridge domains | ${node}
| | Then Honeycomb should show no bridge domains | ${node}
| | And VAT should show no bridge domains | ${node}
"o">= 0; else break; } if (~0 == sw_if_index) return clib_error_return (0, "unknown input '%U'", format_unformat_error, input); ip6_nd_proxy_enable_disable (sw_if_index, enable); return 0; } VLIB_CLI_COMMAND (set_int_ip6_nd_proxy_enable_command, static) = { .path = "set interface ip6-nd proxy", .short_help = "set interface ip6-nd proxy <intfc> [enable|disable]", .function = set_int_ip6_nd_proxy_command_fn, }; typedef struct { u8 is_multicast; u32 sw_if_index; } vnet_ip6_nd_proxy_trace_t; static u8 * format_ip6_nd_proxy_trace (u8 *s, va_list *args) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); vnet_main_t *vnm = vnet_get_main (); vnet_ip6_nd_proxy_trace_t *t = va_arg (*args, vnet_ip6_nd_proxy_trace_t *); u32 indent = format_get_indent (s); if (t->is_multicast) s = format (s, "%U %U multicast ", format_white_space, indent, format_vnet_sw_if_index_name, vnm, t->sw_if_index); else s = format (s, "%U %U unicast ", format_white_space, indent, format_vnet_sw_if_index_name, vnm, t->sw_if_index); return s; } static_always_inline void ip6_nd_proxy_unicast (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip6, u32 *next0) { if (PREDICT_FALSE (ip6->protocol == IP_PROTOCOL_ICMP6)) { icmp46_header_t *icmp0; icmp6_type_t type0; icmp0 = ip6_next_header (ip6); type0 = icmp0->type; if (type0 == ICMP6_neighbor_solicitation || type0 == ICMP6_neighbor_advertisement) { icmp6_neighbor_solicitation_or_advertisement_header_t *icmp6_nsa; icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *icmp6_nd_ell_addr; u32 sw_if_index0; icmp6_nsa = (void *) icmp0; icmp6_nd_ell_addr = (void *) (icmp6_nsa + 1); sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; /* unicast neighbor solicitation */ fib_node_index_t fei; u32 fib_index; fib_index = ip6_fib_table_get_index_for_sw_if_index (sw_if_index0); if (~0 == fib_index) { *next0 = ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP; } else { if (ip6_address_is_link_local_unicast (&ip6->dst_address)) { fei = ip6_fib_table_lookup_exact_match ( ip6_ll_fib_get (sw_if_index0), &ip6->dst_address, 128); } else { fei = ip6_fib_table_lookup_exact_match ( fib_index, &ip6->dst_address, 128); } if (FIB_NODE_INDEX_INVALID != fei) { *next0 = ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY; icmp6_send_neighbor_advertisement ( vm, b0, ip6, icmp6_nsa, icmp6_nd_ell_addr, sw_if_index0); } } if (b0->flags & VLIB_BUFFER_IS_TRACED) { vnet_ip6_nd_proxy_trace_t *t; t = vlib_add_trace (vm, node, b0, sizeof (t[0])); t->sw_if_index = sw_if_index0; t->is_multicast = 0; } } } } static_always_inline void ip6_nd_proxy_multicast (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip6, u32 *next0) { if (PREDICT_FALSE (ip6->protocol == IP_PROTOCOL_ICMP6)) { icmp46_header_t *icmp0; icmp6_type_t type0; icmp0 = ip6_next_header (ip6); type0 = icmp0->type; if (type0 == ICMP6_neighbor_solicitation || type0 == ICMP6_neighbor_advertisement) { icmp6_neighbor_solicitation_or_advertisement_header_t *icmp6_nsa; icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *icmp6_nd_ell_addr; u32 sw_if_index0; icmp6_nsa = (void *) icmp0; icmp6_nd_ell_addr = (void *) (icmp6_nsa + 1); sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; if (type0 == ICMP6_neighbor_solicitation) { if ( (icmp6_nd_ell_addr->header.type == ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address) && (!ip6_address_is_unspecified (&ip6->src_address)) && (!ip6_address_is_link_local_unicast (&ip6->src_address))) { ip_neighbor_learn_t learn = { .sw_if_index = sw_if_index0, .ip = { .version = AF_IP6, .ip.ip6 = ip6->src_address, } }; clib_memcpy (&learn.mac, icmp6_nd_ell_addr->ethernet_address, sizeof (learn.mac)); ip_neighbor_learn_dp (&learn); *next0 = ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY; icmp6_send_neighbor_advertisement ( vm, b0, ip6, icmp6_nsa, icmp6_nd_ell_addr, sw_if_index0); } } else // type0 = ICMP6_neighbor_advertisement { icmp6_neighbor_solicitation_or_advertisement_header_t *icmp6_nsa = (void *) icmp0; icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *icmp6_nd_ell_addr = (void *) (icmp6_nsa + 1); if ( (icmp6_nd_ell_addr->header.type == ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address) && (!ip6_address_is_unspecified (&ip6->src_address)) && (!ip6_address_is_link_local_unicast (&ip6->src_address))) { ip_neighbor_learn_t learn = { .sw_if_index = sw_if_index0, .ip = { .version = AF_IP6, .ip.ip6 = icmp6_nsa->target_address, } }; clib_memcpy (&learn.mac, icmp6_nd_ell_addr->ethernet_address, sizeof (learn.mac)); ip_neighbor_learn_dp (&learn); *next0 = ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP; } } if (b0->flags & VLIB_BUFFER_IS_TRACED) { vnet_ip6_nd_proxy_trace_t *t; t = vlib_add_trace (vm, node, b0, sizeof (t[0])); t->sw_if_index = sw_if_index0; t->is_multicast = 1; } } } } static_always_inline uword ip6_nd_proxy_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_multicast) { u32 n_left_from, *from, *to_next; u32 next_index, n_left_to_next; vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; next_index = node->cached_next_index; vlib_get_buffers (vm, from, bufs, n_left_from); while (n_left_from > 0) { vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); while (n_left_from > 4 && n_left_to_next > 2) { ip6_header_t *ip6_0, *ip6_1; u32 next0, next1; u32 bi0, bi1; /* Prefetch next iteration. */ { vlib_prefetch_buffer_header (b[2], LOAD); vlib_prefetch_buffer_header (b[3], LOAD); vlib_prefetch_buffer_data (b[2], LOAD); vlib_prefetch_buffer_data (b[3], LOAD); } /* * speculatively enqueue b0 and b1 to the current next frame */ to_next[0] = bi0 = from[0]; to_next[1] = bi1 = from[1]; to_next += 2; n_left_to_next -= 2; vnet_feature_next (&next0, b[0]); vnet_feature_next (&next1, b[1]); ip6_0 = vlib_buffer_get_current (b[0]); ip6_1 = vlib_buffer_get_current (b[1]); if (is_multicast) { ip6_nd_proxy_multicast (vm, node, b[0], ip6_0, &next0); ip6_nd_proxy_multicast (vm, node, b[1], ip6_1, &next1); } else { ip6_nd_proxy_unicast (vm, node, b[0], ip6_0, &next0); ip6_nd_proxy_unicast (vm, node, b[1], ip6_1, &next1); } vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1); b += 2; from += 2; n_left_from -= 2; } while (n_left_from > 0 && n_left_to_next > 0) { ip6_header_t *ip6_0; u32 next0, bi0; /* speculatively enqueue b0 to the current next frame */ to_next[0] = bi0 = from[0]; to_next += 1; n_left_to_next -= 1; vnet_feature_next (&next0, b[0]); ip6_0 = vlib_buffer_get_current (b[0]); if (is_multicast) ip6_nd_proxy_multicast (vm, node, b[0], ip6_0, &next0); else ip6_nd_proxy_unicast (vm, node, b[0], ip6_0, &next0); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); b += 1; from += 1; n_left_from -= 1; } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } return frame->n_vectors; } VLIB_NODE_FN (ip6_unicast_nd_proxy_node) (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) { return ip6_nd_proxy_node_inline (vm, node, frame, 0 /* is_multicast */); } VLIB_REGISTER_NODE (ip6_unicast_nd_proxy_node) = { .vector_size = sizeof (u32), .format_trace = format_ip6_nd_proxy_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = 0, .n_next_nodes = ICMP6_NEIGHBOR_SOLICITATION_N_NEXT, .next_nodes = { [ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP] = "ip6-drop", [ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY] = "interface-output", }, .name = "ip6-unicast-nd-proxy", }; VLIB_NODE_FN (ip6_multicast_nd_proxy_node) (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) { return ip6_nd_proxy_node_inline (vm, node, frame, 1 /* is_multicast */); } VLIB_REGISTER_NODE (ip6_multicast_nd_proxy_node) = { .vector_size = sizeof (u32), .format_trace = format_ip6_nd_proxy_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = 0, .n_next_nodes = ICMP6_NEIGHBOR_SOLICITATION_N_NEXT, .next_nodes = { [ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP] = "ip6-drop", [ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY] = "interface-output", }, .name = "ip6-multicast-nd-proxy", }; VNET_FEATURE_INIT (ip6_unicast_nd_proxy_node, static) = { .arc_name = "ip6-unicast", .node_name = "ip6-unicast-nd-proxy", .runs_before = VNET_FEATURES ("ip6-lookup"), }; VNET_FEATURE_INIT (ip6_multicast_nd_proxy_node, static) = { .arc_name = "ip6-multicast", .node_name = "ip6-multicast-nd-proxy", .runs_before = VNET_FEATURES ("ip6-mfib-forward-lookup"), }; /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */