From: selias Date: Mon, 9 Oct 2017 14:36:16 +0000 (+0200) Subject: CSIT-811 HC Test: BGP functional tests X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=commitdiff_plain;h=56dd61dee872da788e578129eed48a3158a5b566 CSIT-811 HC Test: BGP functional tests Added traffic tests for Honeycomb's BGP feature. Change-Id: I5fa99908ab61d8bc9d2975e451917b98571b6aca Signed-off-by: selias --- diff --git a/resources/libraries/python/honeycomb/BGP.py b/resources/libraries/python/honeycomb/BGP.py index ca50cc3120..75dce762ff 100644 --- a/resources/libraries/python/honeycomb/BGP.py +++ b/resources/libraries/python/honeycomb/BGP.py @@ -13,6 +13,7 @@ """Keywords to manipulate BGP configuration using Honeycomb REST API.""" +from resources.libraries.python.constants import Constants as Const from resources.libraries.python.HTTPRequest import HTTPCodes from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError from resources.libraries.python.honeycomb.HoneycombUtil \ @@ -27,6 +28,7 @@ class BGPKeywords(object): """ def __init__(self): + """Initializer.""" pass @staticmethod @@ -41,7 +43,7 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not + :raises HoneycombError: If the status code in response to PUT is not 200 = OK or 201 = ACCEPTED. """ @@ -69,7 +71,7 @@ class BGPKeywords(object): :type data: dict :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the status code in response on PUT is not + :raises HoneycombError: If the status code in response to PUT is not 200 = OK or 201 = ACCEPTED. """ @@ -93,6 +95,7 @@ class BGPKeywords(object): :type node: dict :returns: BGP configuration data. :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. """ status_code, resp = HcUtil. \ @@ -104,21 +107,29 @@ class BGPKeywords(object): return resp @staticmethod - def get_bgp_peer(node, address): + def get_bgp_peer(node, address, datastore='config'): """Get BGP configuration of the specified peer from the node. :param node: Honeycomb node. :param address: IP address of the peer. + :param datastore: Get data from config or operational datastore. :type node: dict :type address: str + :type datastore; str :returns: BGP peer configuration data. :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. """ path = "bgp-openconfig-extensions:neighbors/" \ "neighbor/{0}".format(address) + if datastore != "operational": + url = "config_bgp_peer" + else: + url = "oper_bgp" + path = "peer/bgp:%2F%2F{0}".format(address) status_code, resp = HcUtil. \ - get_honeycomb_data(node, "config_bgp_peer", path) + get_honeycomb_data(node, url, path) if status_code != HTTPCodes.OK: raise HoneycombError( "Not possible to get configuration information about the BGP" @@ -211,7 +222,7 @@ class BGPKeywords(object): :type ip_version: str :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the operation fails. + :raises HoneycombError: If the status code in response is not 200 = OK. """ route_address = route_address.replace("/", "%2F") @@ -239,7 +250,7 @@ class BGPKeywords(object): def get_all_peer_routes(node, peer_address, ip_version): """Get all configured routes for the given BGP peer. - :param node: HOneycomb node. + :param node: Honeycomb node. :param peer_address: IP address of the peer. :param ip_version: IP protocol version. ipv4 or ipv6 :type node: dict @@ -247,7 +258,7 @@ class BGPKeywords(object): :type ip_version: str :returns: Content of response. :rtype: bytearray - :raises HoneycombError: If the operation fails. + :raises HoneycombError: If the status code in response is not 200 = OK. """ if ip_version.lower() == "ipv4": @@ -299,3 +310,85 @@ class BGPKeywords(object): .format(peer_address, route_address, index) return BGPKeywords._configure_bgp_route(node, path) + + @staticmethod + def get_bgp_local_rib(node): + """Get local RIB table from the Honeycomb node. + + :param node: Honeycomb node. + :type node: dict + :returns: RIB operational data. + :rtype: dict + :raises HoneycombError: If the status code in response is not 200 = OK. + """ + + path = "loc-rib" + + status_code, resp = HcUtil. \ + get_honeycomb_data(node, "oper_bgp", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational data from BGP local RIB." + " Status code: {0}.".format(status_code)) + + return resp + + @staticmethod + def configure_bgp_base(node, ip_address, port, as_number): + """Modify BGP config file. Requires a restart of Honeycomb to take + effect. + + :param node: Honeycomb node. + :param ip_address: BGP peer identifier/binding address. + :param port: BGP binding port. + :param as_number: Autonomous System ID number. + :type node: dict + :type ip_address: str + :type port: int + :type as_number: int + :raises HoneycombError: If modifying the configuration fails. + """ + + from resources.libraries.python.ssh import SSH + + config = { + '\\"bgp-binding-address\\"': '\\"{0}\\"'.format(ip_address), + '\\"bgp-port\\"': port, + '\\"bgp-as-number\\"': as_number} + + path = "{0}/config/bgp.json".format(Const.REMOTE_HC_DIR) + + for key, value in config.items(): + find = key + replace = '"{0}": "{1}",'.format(key, value) + + argument = '"/{0}/c\\ {1}"'.format(find, replace) + command = "sed -i {0} {1}".format(argument, path) + + ssh = SSH() + ssh.connect(node) + (ret_code, _, stderr) = ssh.exec_command_sudo(command) + if ret_code != 0: + raise HoneycombError("Failed to modify configuration on " + "node {0}, {1}".format(node, stderr)) + + @staticmethod + def compare_rib_tables(data, ref): + """Compare provided RIB table with reference. All reference entries must + be present in data. Data entries not present in reference are ignored. + + :param data: Data from Honeycomb node. + :param ref: Reference data to compare against. + :type data: dict + :type ref: dict + :raises HoneycombError: If the tables do not match.""" + + # Remove runtime attributes from data + for item in data: + item.pop("attributes", "") + + for item in ref: + if item not in data: + raise HoneycombError( + "RIB entry {0} not found in operational data.") diff --git a/resources/libraries/python/honeycomb/HoneycombSetup.py b/resources/libraries/python/honeycomb/HoneycombSetup.py index 7c3831ca04..d4175b13e4 100644 --- a/resources/libraries/python/honeycomb/HoneycombSetup.py +++ b/resources/libraries/python/honeycomb/HoneycombSetup.py @@ -61,12 +61,13 @@ class HoneycombSetup(object): HoneycombSetup.print_environment(nodes) - logger.console("\n(re)Starting Honeycomb service ...") - cmd = "sudo service honeycomb start" for node in nodes: if node['type'] == NodeType.DUT: + logger.console( + "\n(re)Starting Honeycomb service on node {0}".format( + node["host"])) ssh = SSH() ssh.connect(node) (ret_code, _, _) = ssh.exec_command_sudo(cmd) @@ -89,13 +90,15 @@ class HoneycombSetup(object): :type nodes: list :raises HoneycombError: If Honeycomb failed to stop. """ - logger.console("\nShutting down Honeycomb service ...") cmd = "sudo service honeycomb stop" errors = [] for node in nodes: if node['type'] == NodeType.DUT: + logger.console( + "\nShutting down Honeycomb service on node {0}".format( + node["host"])) ssh = SSH() ssh.connect(node) (ret_code, _, _) = ssh.exec_command_sudo(cmd) @@ -121,7 +124,8 @@ class HoneycombSetup(object): :raises HoneycombError: If Honeycomb fails to start. """ - logger.console("\n(re)Starting Honeycomb service ...") + logger.console( + "\n(re)Starting Honeycomb service on node {0}".format(node["host"])) cmd = "sudo service honeycomb restart" @@ -650,6 +654,26 @@ class HoneycombSetup(object): logger.info("ODL client service stopped.") + @staticmethod + def set_static_arp(node, ip_address, mac_address): + """Configure a static ARP entry using arp. + + :param node: Node in topology. + :param ip_address: IP address for the entry. + :param mac_address: MAC adddress for the entry. + :type node: dict + :type ip_address: str + :type mac_address: str + :raises RuntimeError: If the operation fails. + """ + + ssh = SSH() + ssh.connect(node) + ret_code, _, _ = ssh.exec_command_sudo("arp -s {0} {1}".format( + ip_address, mac_address)) + + if ret_code != 0: + raise RuntimeError("Failed to configure static ARP adddress.") class HoneycombStartupConfig(object): diff --git a/resources/libraries/robot/honeycomb/bgp.robot b/resources/libraries/robot/honeycomb/bgp.robot index d4c2d6b0a2..aa96cc6538 100644 --- a/resources/libraries/robot/honeycomb/bgp.robot +++ b/resources/libraries/robot/honeycomb/bgp.robot @@ -16,6 +16,24 @@ | Library | resources.libraries.python.honeycomb.HcAPIKwInterfaces.InterfaceKeywords *** Keywords *** +| Configure BGP module +| | [Documentation] | Edit Honeycomb's configuration file for the BGP feature.\ +| | ... | Honeycomb needs to be restarted for the changes to take effect. +| | ... +| | ... | *Arguments:* +| | ... | - node - information about a DUT node. Type: dictionary +| | ... | - ip_address - IP address to bind BGP listener to. Type: string +| | ... | - port - Port number to bind BGP listener to. Type: integer +| | ... | - as_number - Autonomous System (AS) ID number. Type: integer +| | ... +| | ... | *Example:* +| | ... +| | ... | \| Configure BGP module \| ${nodes['DUT1']} \| 192.168.0.1 \| ${179} \ +| | ... | \| ${65000} \| +| | ... +| | [Arguments] | ${node} | ${ip_address} | ${port} | ${as_number} +| | Configure BGP base | ${node} | ${ip_address} | ${port} | ${as_number} + | No BGP peers should be configured | | [Documentation] | Uses Honeycomb API to read BGP configuration and checks | | ... | if there ary BGP peers conffigured. @@ -50,7 +68,7 @@ | | Add BGP Peer | ${node} | ${address} | ${data} | BGP Peer From Honeycomb Should be -| | [Documentation] | Uses Honeycomb API to verify BGP peer operational data. +| | [Documentation] | Uses Honeycomb API to verify BGP peer config data. | | ... | | ... | *Arguments:* | | ... | - node - Information about a DUT node. Type: dictionary @@ -67,6 +85,24 @@ | | ${oper_data}= | Get BGP Peer | ${node} | ${address} | | Compare Data Structures | ${oper_data} | ${data} +| Peer Operational Data From Honeycomb Should be +| | [Documentation] | Uses Honeycomb API to verify BGP peer operational data. +| | ... +| | ... | *Arguments:* +| | ... | - node - Information about a DUT node. Type: dictionary +| | ... | - address - IP address of the peer. Type: string +| | ... | - data - Peer configuration data. Type: dictionary +| | ... +| | ... | *Example:* +| | ... +| | ... | \| BGP Peer From Honeycomb Should be \ +| | ... | \| ${nodes['DUT1']} \| 192.168.0.1 \| ${data} \| +| | ... +| | [Arguments] | ${node} | ${address} +| | ... +| | ${oper_data}= | Get BGP Peer | ${node} | ${address} | operational +| | Should be Equal | ${oper_data['peer'][0]['peer-id']} | bgp://${address} + | Honeycomb removes BGP peer | | [Documentation] | Uses Honeycomb API to add a BGP peer. | | ... @@ -171,3 +207,51 @@ | | ${oper_data}= | Get All Peer Routes | | ... | ${node} | ${peer_address} | ${ip_version} | | Should be Empty | ${oper_data['bgp-inet:${ip_version}-routes']} + +| BGP Loc-RIB table should include +| | [Documentation] | Uses Honeycomb API to retrieve local BGP RIB table\ +| | ... | And verifies that it contains the specified entry. +| | ... +| | ... | *Arguments:* +| | ... | - node - Information about a DUT node. Type: dictionary +| | ... | - data - RIB that should be present in operational data.\ +| | ... | Type: dictionary +| | ... +| | ... | *Example:* +| | ... +| | ... | \| BGP Loc-RIB table should include \| ${nodes['DUT1']} \| ${data} \| +| | ... +| | [Arguments] | ${node} | ${data} +| | ... +| | ${oper_data}= | Get BGP Local RIB | ${node} +| | ${oper_data}= | Set Variable | ${oper_data['loc-rib']['tables']} +| | ${data}= | Set Variable | ${data['loc-rib']['tables']} +| | Compare RIB Tables | ${oper_data} | ${data} + +| Receive BGP OPEN message +| | [Documentation] | Open a TCP listener on BGP port(179) and listen\ +| | ... | for BGP OPEN message. Verify ID and holdtime fields. +| | ... +| | ... | *Arguments:* +| | ... | - tg_node - Information about the TG node. Type: dictionary +| | ... | - rx_ip - IP address to listen on. Type: string +| | ... | - src_ip - IP address of the BGP speaker. Also acts as BGP peer ID.\ +| | ... | Type: string +| | ... | - holdtime - Expected value of HOLD_TIME field in received message.\ +| | ... | Type: integer +| | ... +| | ... | *Example:* +| | ... +| | ... | \| Receive BGP OPEN message \| ${node['TG']} \ +| | ... | \| 192.168.0.1 \| 192.168.0.2 \| ${0} +| | ... +| | [Arguments] | ${tg_node} | ${rx_ip} | ${src_ip} | ${port} | ${as_number} +| | ... | ${holdtime} +| | ... +| | ${args}= | Catenate | --rx_ip | ${rx_ip} +| | ... | --src_ip | ${src_ip} +| | ... | --rx_port | ${port} +| | ... | --as_number | ${as_number} +| | ... | --holdtime | ${holdtime} +| | Run Traffic Script On Node | honeycomb/bgp_open.py +| | ... | ${tg_node} | ${args} diff --git a/resources/test_data/honeycomb/bgp.py b/resources/test_data/honeycomb/bgp.py index f9dc4ab233..84c9431e6b 100644 --- a/resources/test_data/honeycomb/bgp.py +++ b/resources/test_data/honeycomb/bgp.py @@ -18,6 +18,7 @@ from copy import deepcopy # Internal BGP peers for CRUD tests address_internal = "192.168.0.2" address_internal2 = "192.168.0.3" +holdtime_internal = 60 peer_internal = { "bgp-openconfig-extensions:neighbor": [{ "neighbor-address": address_internal, @@ -26,13 +27,13 @@ peer_internal = { }, "timers": { "config": { - "connect-retry": 10, - "hold-time": 60 + "connect-retry": 3, + "hold-time": holdtime_internal } }, "transport": { "config": { - "remote-port": 17900, + "remote-port": 179, "passive-mode": False } }, @@ -55,12 +56,12 @@ peer_internal_update = { "timers": { "config": { "connect-retry": 5, - "hold-time": 120 + "hold-time": holdtime_internal*2 } }, "transport": { "config": { - "remote-port": 17901, + "remote-port": 180, "passive-mode": True } }, @@ -78,7 +79,7 @@ peer_internal2 = deepcopy(peer_internal) peer_internal2["bgp-openconfig-extensions:neighbor"][0]["neighbor-address"] = \ address_internal2 -# Application BGP peer for CRUD tests +# Application BGP peer for CRUD test address_application = "192.168.0.4" peer_application = { "bgp-openconfig-extensions:neighbor": [{ @@ -103,6 +104,7 @@ peer_application = { }] } +# IPv4 route for CRUD test route_address_ipv4 = "192.168.0.5/32" route_id_ipv4 = 0 route_data_ipv4 = { @@ -124,6 +126,7 @@ route_data_ipv4 = { }] } +# IPv4 route for testing Update operation route_data_ipv4_update = { "bgp-inet:ipv4-route": [{ "path-id": route_id_ipv4, @@ -143,6 +146,7 @@ route_data_ipv4_update = { }] } +# IPv4 route for testing multiple routes route_address_ipv4_2 = "192.168.0.6/32" route_id_ipv4_2 = 1 route_data_ipv4_2 = { @@ -164,6 +168,7 @@ route_data_ipv4_2 = { }] } +# IPv6 route for CRUD test route_address_ipv6 = "3ffe:62::1/64" route_id_ipv6 = 0 route_data_ipv6 = { @@ -185,8 +190,164 @@ route_data_ipv6 = { }] } +# IPv4 route operational data in routing table table1_oper = { "destination-prefix": route_address_ipv4, "next-hop": "192.168.1.1", "vpp-ipv4-route-state": {} -} \ No newline at end of file +} + +# Peer configurations for traffic test +dut1_peer = { + "bgp-openconfig-extensions:neighbor": [{ + "neighbor-address": "192.168.1.1", + "config": { + "peer-type": "INTERNAL" + }, + "timers": { + "config": { + "connect-retry": 3, + "hold-time": 60 + } + }, + "transport": { + "config": { + "remote-port": 179, + "passive-mode": False + } + }, + "afi-safis": { + "afi-safi": [ + { + "afi-safi-name": "openconfig-bgp-types:IPV4-UNICAST", + "receive": True, + "send-max": 0}, + { + "afi-safi-name": "openconfig-bgp-types:IPV6-UNICAST", + "receive": True, + "send-max": 0}, + { + "afi-safi-name": "LINKSTATE" + } + ] + } + }] +} + +dut2_peer = { + "bgp-openconfig-extensions:neighbor": [{ + "neighbor-address": "192.168.1.2", + "config": { + "peer-type": "INTERNAL" + }, + "timers": { + "config": { + "connect-retry": 3, + "hold-time": 60 + } + }, + "transport": { + "config": { + "remote-port": 179, + "passive-mode": True + } + }, + "afi-safis": { + "afi-safi": [ + { + "afi-safi-name": "openconfig-bgp-types:IPV4-UNICAST", + "receive": True, + "send-max": 0}, + { + "afi-safi-name": "openconfig-bgp-types:IPV6-UNICAST", + "receive": True, + "send-max": 0}, + { + "afi-safi-name": "LINKSTATE" + } + ] + } + }] +} + +# IPv4 route for traffic test +dut1_route_address = "192.168.0.5/32" +dut1_route_id = 1 +dut1_route = { + "bgp-inet:ipv4-route": [{ + "path-id": dut1_route_id, + "prefix": dut1_route_address, + "attributes": { + "as-path": {}, + "origin": { + "value": "igp" + }, + "local-pref": { + "pref": 100 + }, + "ipv4-next-hop": { + "global": "192.168.1.3" + } + } + }] +} + +# IPv4 route in peer operational data +rib_operational = { + "loc-rib": {"tables": [ + { + "afi": "bgp-types:ipv4-address-family", + "safi": "bgp-types:unicast-subsequent-address-family", + "bgp-inet:ipv4-routes": { + "ipv4-route": dut1_route["bgp-inet:ipv4-route"] + } + } + ]} +} + +route_operational = { + "vpp-ipv4-route-state": {}, + "next-hop": "192.168.1.3", + "destination-prefix": dut1_route_address +} + +# IPv6 route for traffic test +dut1_route_ip6_address = "3ffe:62::1/64" +dut1_route_ip6_id = 1 +dut1_route_ip6 = { + "bgp-inet:ipv6-route": [{ + "path-id": dut1_route_ip6_id, + "prefix": dut1_route_ip6_address, + "attributes": { + "as-path": {}, + "origin": { + "value": "igp" + }, + "local-pref": { + "pref": 100 + }, + "ipv6-next-hop": { + "global": "3ffe:63::1" + } + } + }] +} + +# IPv6 route in peer operational data +rib_ip6_operational = { + "loc-rib": {"tables": [ + { + "afi": "bgp-types:ipv6-address-family", + "safi": "bgp-types:unicast-subsequent-address-family", + "bgp-inet:ipv6-routes": { + "ipv6-route": dut1_route_ip6["bgp-inet:ipv6-route"] + } + } + ]} +} + +route_ip6_operational = { + "vpp-ipv6-route-state": {}, + "next-hop": "3ffe:63::1", + "destination-prefix": dut1_route_ip6_address +} diff --git a/resources/traffic_scripts/honeycomb/bgp_open.py b/resources/traffic_scripts/honeycomb/bgp_open.py new file mode 100755 index 0000000000..e7bb7d841a --- /dev/null +++ b/resources/traffic_scripts/honeycomb/bgp_open.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# 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. + +"""Traffic script that listens for incoming BGP connections and verifies +received GBP Open message.""" + +import sys +import socket + +from scapy.main import load_contrib +from scapy.layers.inet import Raw +from scapy.contrib.bgp import BGPHeader, BGPOpen + +from resources.libraries.python.TrafficScriptArg import TrafficScriptArg + + +def main(): + """Open a TCP listener socket on the default BGP port. Accept an incoming + connection, receive data and verify if data is a valid BGP Open message.""" + args = TrafficScriptArg(['rx_ip', 'src_ip', 'rx_port', 'as_number', + 'holdtime']) + + rx_ip = args.get_arg('rx_ip') + src_ip = args.get_arg('src_ip') + rx_port = int(args.get_arg('rx_port')) + as_number = int(args.get_arg('as_number')) + holdtime = int(args.get_arg('holdtime')) + + load_contrib("bgp") + + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.bind((rx_ip, rx_port)) + soc.listen(1) + + print "Listener active, awaiting connection..." + soc.settimeout(8) + conn, addr = soc.accept() + print 'Connection established with peer:', addr + + data = conn.recv(256) + conn.close() + soc.close() + + bgp_layer = (BGPHeader(Raw(data).load)) + bgp_layer.show() + + if not bgp_layer.haslayer(BGPOpen): + raise RuntimeError("Received data is not a BGP OPEN message.") + bgp_open = bgp_layer.getlayer(BGPOpen) + if bgp_open.bgp_id != src_ip: + raise RuntimeError( + "BGP ID mismatch. Received {0} but should be {1}". + format(bgp_open.bgp_id, src_ip)) + else: + print "BGP ID matched." + + if bgp_open.AS != as_number: + raise RuntimeError( + "BGP AS number mismatch. Received {0} but should be {1}". + format(bgp_open.AS, as_number)) + else: + print "BGP AS number matched." + + if bgp_open.hold_time != holdtime: + raise RuntimeError( + "Hold Time parameter mismatch. Received {0} but should be {1}.". + format(bgp_layer.getlayer(BGPOpen).holdtime, holdtime)) + else: + print "BGP Hold Time parameter matched." + + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-apivat-func.robot b/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-apivat-func.robot deleted file mode 100644 index 290725e309..0000000000 --- a/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-apivat-func.robot +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2017 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 *** -# Interface to run tests on. -| ${interface}= | ${node['interfaces']['port1']['name']} - -*** Settings *** -| Resource | resources/libraries/robot/shared/default.robot -| Resource | resources/libraries/robot/honeycomb/honeycomb.robot -| Resource | resources/libraries/robot/honeycomb/interfaces.robot -| Resource | resources/libraries/robot/honeycomb/bgp.robot -| Resource | resources/libraries/robot/honeycomb/routing.robot -| Variables | resources/test_data/honeycomb/bgp.py -| ... -| Suite Setup | Run Keywords -| ... | Enable Honeycomb Feature | ${node} | BGP | AND -| ... | Set Up Honeycomb Functional Test Suite | ${node} -| ... -| Suite Teardown | Run Keywords -| ... | Tear Down Honeycomb Functional Test Suite | ${node} | AND -| ... | Disable Honeycomb Feature | ${node} | BGP -| ... -# HONEYCOMB-409: ODL client fails to parse requests to BGP instance node -| Force Tags | HC_FUNC | EXPECTED_FAILING -| ... -| Documentation | *Honeycomb BGP management test suite.* - -*** Test Cases *** -| TC01: Honeycomb configures BGP peer - Internal -| | [Documentation] | Check if Honeycomb can configure an internal BGP peer. -| | ... -| | When Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | Then BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} - -| TC03: Honeycomb removes peer configuration -| | [Documentation] | Check if Honeycomb can remove a configured BGP peer. -| | ... -| | Given BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | When Honeycomb removes BGP peer | ${node} | ${address_internal} -| | Then No BGP peers should be configured | ${node} - -| TC02: Honeycomb updates existing BGP peer - Internal -| | [Documentation] | Check if Honeycomb can update an existing BGP peer. -| | ... -| | [Teardown] | Honeycomb removes BGP peer | ${node} | ${address_internal} -| | ... -| | Given No BGP peers should be configured | ${node} -| | When Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | And Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal} | ${peer_internal_update} -| | Then BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal_update} - -| TC04: Honeycomb configures BGP peer - Application -| | [Documentation] | Check if Honeycomb can configure an application BGP peer. -| | ... -| | [Teardown] | Honeycomb removes BGP peer | ${node} | ${address_application} -| | ... -| | Given No BGP peers should be configured | ${node} -| | When Honeycomb adds BGP peer -| | ... | ${node} | ${address_application} | ${peer_application} -| | Then BGP peer from Honeycomb should be -| | ... | ${node} | ${address_application} | ${peer_application} - -| TC05: Honeycomb configures a second BGP peer -| | [Documentation] | Check if Honeycomb can configure more than one BGP peer. -| | ... -| | [Teardown] | Run Keywords -| | ... | Honeycomb removes BGP peer | ${node} | ${address_internal} | AND -| | ... | Honeycomb removes BGP peer | ${node} | ${address_internal2} -| | ... -| | Given No BGP peers should be configured | ${node} -| | When Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | And Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal2} | ${peer_internal2} -| | Then BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | And BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal2} | ${peer_internal2} - -| TC06: Honeycomb configures IPv4 route using BGP -| | [Documentation] | Check if Honeycomb can configure a BGP route under a peer. -| | ... -| | Given Honeycomb adds BGP peer -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | When Honeycomb configures BGP route -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | Then BGP Route from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 - -| TC08: Honeycomb removes IPv4 route configuration -| | [Documentation] | Check if Honeycomb can remove a configured BGP route. -| | ... -| | Given BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | And BGP Route from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | When Honeycomb removes BGP route | ${node} | ${address_internal} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | Then No BGP Routes Should be Configured -| | ... | ${node} | ${address_internal} | ipv4 - -| TC07: Honeycomb updates existing IPv4 route using BGP -| | [Documentation] | Check if Honeycomb can update an existing BGP route. -| | ... -| | [Teardown] | Honeycomb removes BGP route | ${node} | ${address_internal} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | ... -| | Given BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | And No BGP Routes Should be Configured -| | ... | ${node} | ${address_internal} | ipv4 -| | When Honeycomb configures BGP route -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | And Honeycomb configures BGP route -| | ... | ${node} | ${address_internal} | ${route_data_ipv4_update} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | Then BGP Route from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${route_data_ipv4_update} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 - -| TC09: Honeycomb configures a second IPv4 route -| | [Documentation] | Check if Honeycomb can configure more than one BGP route. -| | ... -| | [Teardown] | Run Keywords -| | ... | Honeycomb removes BGP route | ${node} | ${address_internal} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 | AND -| | ... | Honeycomb removes BGP route | ${node} | ${address_internal} -| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 -| | ... -| | Given BGP peer from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${peer_internal} -| | When Honeycomb configures BGP route -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | And Honeycomb configures BGP route -| | ... | ${node} | ${address_internal} | ${route_data_ipv4_2} -| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 -| | Then BGP Route from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${route_data_ipv4} -| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 -| | And BGP Route from Honeycomb should be -| | ... | ${node} | ${address_internal} | ${route_data_ipv4_2} -| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 diff --git a/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-func.robot b/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-func.robot new file mode 100644 index 0000000000..8f74280610 --- /dev/null +++ b/tests/vpp/func/honeycomb/mgmt-cfg-bgp-apihc-func.robot @@ -0,0 +1,365 @@ +# Copyright (c) 2017 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 *** +# Interface to run tests on. +| ${interface}= | ${node['interfaces']['port1']['name']} +| ${dut1_to_tg_ip}= | 192.168.0.1 +| ${tg_to_dut1_ip}= | 192.168.0.2 +| ${dut1_to_dut2_ip}= | 192.168.1.1 +| ${dut2_to_dut1_ip}= | 192.168.1.2 +| ${bgp_port}= | ${179} +| ${bgp_as_number}= | ${37} +| ${prefix}= | ${24} + +*** Settings *** +| Library | resources.libraries.python.honeycomb.IPv6Management +| Resource | resources/libraries/robot/shared/default.robot +| Resource | resources/libraries/robot/honeycomb/honeycomb.robot +| Resource | resources/libraries/robot/honeycomb/interfaces.robot +| Resource | resources/libraries/robot/honeycomb/bgp.robot +| Resource | resources/libraries/robot/honeycomb/routing.robot +| Resource | resources/libraries/robot/shared/testing_path.robot +| Resource | resources/libraries/robot/honeycomb/ipv6_control.robot +| Variables | resources/test_data/honeycomb/bgp.py +| ... +| Suite Setup | Run Keywords +| ... | Enable Honeycomb Feature | ${node} | BGP | AND +| ... | Configure BGP Module | ${node} | ${dut1_to_tg_ip} +| ... | ${bgp_port} | ${bgp_as_number} | AND +| ... | Set Up Honeycomb Functional Test Suite | ${node} +| ... +| Suite Teardown | Run Keywords +| ... | Tear Down Honeycomb Functional Test Suite | ${nodes['DUT1']} | AND +| ... | Stop Honeycomb service on DUTs | ${nodes['DUT2']} | AND +| ... | Unconfigure IPv4 Management Interfaces | AND +| ... | Disable Honeycomb Feature | ${node} | BGP | AND +| ... | Disable Honeycomb Feature | ${nodes['DUT2']} | BGP +| ... +| Force Tags | HC_FUNC +| ... +| Documentation | *Honeycomb BGP management test suite.* + +*** Test Cases *** +| TC01: Honeycomb configures BGP peer - Internal +| | [Documentation] | Check if Honeycomb can configure an internal BGP peer. +| | ... +| | When Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | Then BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} + +| TC02: Honeycomb removes peer configuration +| | [Documentation] | Check if Honeycomb can remove a configured BGP peer. +| | ... +| | Given BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | When Honeycomb removes BGP peer | ${node} | ${address_internal} +| | Then No BGP peers should be configured | ${node} + +| TC03: Honeycomb updates existing BGP peer - Internal +| | [Documentation] | Check if Honeycomb can update an existing BGP peer. +| | ... +| | [Teardown] | Honeycomb removes BGP peer | ${node} | ${address_internal} +| | ... +| | Given No BGP peers should be configured | ${node} +| | When Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | And Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal} | ${peer_internal_update} +| | Then BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal_update} + +| TC04: Honeycomb configures BGP peer - Application +| | [Documentation] | Check if Honeycomb can configure an application BGP peer. +| | ... +| | [Teardown] | Honeycomb removes BGP peer | ${node} | ${address_application} +| | ... +| | Given No BGP peers should be configured | ${node} +| | When Honeycomb adds BGP peer +| | ... | ${node} | ${address_application} | ${peer_application} +| | Then BGP peer from Honeycomb should be +| | ... | ${node} | ${address_application} | ${peer_application} + +| TC05: Honeycomb configures a second BGP peer +| | [Documentation] | Check if Honeycomb can configure more than one BGP peer. +| | ... +| | [Teardown] | Run Keywords +| | ... | Honeycomb removes BGP peer | ${node} | ${address_internal} | AND +| | ... | Honeycomb removes BGP peer | ${node} | ${address_internal2} +| | ... +| | Given No BGP peers should be configured | ${node} +| | When Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | And Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal2} | ${peer_internal2} +| | Then BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | And BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal2} | ${peer_internal2} + +| TC06: Honeycomb configures IPv4 route using BGP +| | [Documentation] | Check if Honeycomb can configure a BGP route under a peer. +| | ... +| | Given Honeycomb adds BGP peer +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | When Honeycomb configures BGP route +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | Then BGP Route from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 + +| TC07: Honeycomb removes IPv4 route configuration +| | [Documentation] | Check if Honeycomb can remove a configured BGP route. +| | ... +| | Given BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | And BGP Route from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | When Honeycomb removes BGP route | ${node} | ${address_internal} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | Then No BGP Routes Should be Configured +| | ... | ${node} | ${address_internal} | ipv4 + +| TC08: Honeycomb updates existing IPv4 route using BGP +| | [Documentation] | Check if Honeycomb can update an existing BGP route. +| | ... +| | [Teardown] | Honeycomb removes BGP route | ${node} | ${address_internal} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | ... +| | Given BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | And No BGP Routes Should be Configured +| | ... | ${node} | ${address_internal} | ipv4 +| | When Honeycomb configures BGP route +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | And Honeycomb configures BGP route +| | ... | ${node} | ${address_internal} | ${route_data_ipv4_update} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | Then BGP Route from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${route_data_ipv4_update} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 + +| TC09: Honeycomb configures a second IPv4 route +| | [Documentation] | Check if Honeycomb can configure more than one BGP route. +| | ... +| | [Teardown] | Run Keywords +| | ... | Honeycomb removes BGP route | ${node} | ${address_internal} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 | AND +| | ... | Honeycomb removes BGP route | ${node} | ${address_internal} +| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 | AND +| | ... | Honeycomb removes BGP peer | ${node} | ${address_internal} +| | ... +| | Given BGP peer from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${peer_internal} +| | When Honeycomb configures BGP route +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | And Honeycomb configures BGP route +| | ... | ${node} | ${address_internal} | ${route_data_ipv4_2} +| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 +| | Then BGP Route from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${route_data_ipv4} +| | ... | ${route_address_ipv4} | ${route_id_ipv4} | ipv4 +| | And BGP Route from Honeycomb should be +| | ... | ${node} | ${address_internal} | ${route_data_ipv4_2} +| | ... | ${route_address_ipv4_2} | ${route_id_ipv4_2} | ipv4 + +| TC10: Honeycomb sends BGP OPEN messages to configured peer +| | [Documentation] +| | ... | [top] TG-DUT1-TG. +| | ... | [enc] Eth-IPv4-TCP-BGP. +| | ... | [cfg] On DUT1 give Honeycomb control over the data-plane interface +| | ... | connected to TG. Configure a BGP peer with the address of TG. +| | ... | [ver] Open a TCP listener on TG on the BGP port and listen for BGP +| | ... | OPEN message. On receive, verify message fields. +| | ... +| | [Setup] | Run Keywords +| | ... | Configure BGP Module | ${node} | ${dut1_to_dut2_ip} +| | ... | ${bgp_port} | ${bgp_as_number} | AND +| | ... | Configure IPv4 Management Interface +| | [Teardown] | Honeycomb removes BGP peer | ${dut1_node} | ${address_internal} +| | When Honeycomb adds BGP peer +| | ... | ${dut1_node} | ${address_internal} | ${peer_internal} +| | Then Receive BGP OPEN message +| | ... | ${tg_node} | ${tg_to_dut1_ip} | ${dut1_to_dut2_ip} +| | ... | ${bgp_port} | ${bgp_as_number} | ${holdtime_internal} + +| TC11: Honeycomb shows connected peer in operational data +| | [Documentation] +| | ... | [top] TG-DUT1-DUT2-TG. +| | ... | [enc] Eth-IPv4-TCP-BGP. +| | ... | [cfg] On DUT1 and DUT2 give Honeycomb control over the data-plane +| | ... | interfaces connecting DUT1 ad DUT2. Configure BGP peers on DUT1 +| | ... | and DUT2 with each other's IP address. +| | ... | [ver] Using Restconf, verify that Honeycomb on each DUT has the +| | ... | other DUT's entry in operational data. +| | ... +| | When Honeycomb adds BGP peer +| | ... | ${dut1_node} | ${dut2_to_dut1_ip} | ${dut2_peer} +| | And Honeycomb adds BGP peer +| | ... | ${dut2_node} | ${dut1_to_dut2_ip} | ${dut1_peer} +| | Sleep | 5s | Wait for BGP connection. Retry timer is 5 seconds. +| | Then Peer operational data from Honeycomb should be +| | ... | ${dut1_node} | ${dut2_to_dut1_ip} +| | And Peer operational data from Honeycomb should be +| | ... | ${dut2_node} | ${dut1_to_dut2_ip} + +| TC12: Honeycomb sends IPv4 BGP route to connected peer +| | [Documentation] +| | ... | [top] TG-DUT1-DUT2-TG. +| | ... | [enc] Eth-IPv4-TCP-BGP. +| | ... | [cfg] On DUT1 and DUT2 give Honeycomb control over the data-plane +| | ... | interfaces connecting DUT1 ad DUT2. Configure BGP peers on DUT1 +| | ... | and DUT2 with each other's IP address. On DUT2 configure a static +| | ... | IPv4 route using Honeycomb's BGP module. +| | ... | [ver] Verify that the route is present in BGP +| | ... | local RIB and VPP's routing table on each DUT. +| | ... +| | Given Peer operational data from Honeycomb should be +| | ... | ${dut1_node} | ${dut2_to_dut1_ip} +| | And Peer operational data from Honeycomb should be +| | ... | ${dut2_node} | ${dut1_to_dut2_ip} +| | When Honeycomb adds BGP peer +| | ... | ${dut2_node} | ${address_application} | ${peer_application} +| | And Honeycomb configures BGP route +| | ... | ${dut2_node} | ${address_application} | ${dut1_route} +| | ... | ${dut1_route_address} | ${dut1_route_id} | ipv4 +| | And Sleep | 5s | Wait for route advertisement. Retry timer is 5 seconds. +| | Then Routing data from Honeycomb should contain +| | ... | ${dut1_node} | learned-protocol-0 | ipv4 | ${route_operational} +| | And Routing data from Honeycomb should contain +| | ... | ${dut2_node} | learned-protocol-0 | ipv4 | ${route_operational} +| | And BGP Loc-RIB table should include | ${dut1_node} | ${rib_operational} +| | And BGP Loc-RIB table should include | ${dut2_node} | ${rib_operational} + +| TC13: Honeycomb sends IPv6 BGP route to connected peer +| | [Documentation] +| | ... | [top] TG-DUT1-DUT2-TG. +| | ... | [enc] Eth-IPv4-TCP-BGP. +| | ... | [cfg] On DUT1 and DUT2 give Honeycomb control over the data-plane +| | ... | interfaces connecting DUT1 ad DUT2. Configure BGP peers on DUT1 +| | ... | and DUT2 with each other's IP address. On DUT2 configure a static +| | ... | IPv6 route using Honeycomb's BGP module. +| | ... | [ver] Verify that the route is present in BGP +| | ... | local RIB and VPP's routing table on each DUT. +| | ... +# HONEYCOMB-403: Missing writers for IPv6 BGP route +| | [Tags] | EXPECTED_FAILING +| | Given Peer operational data from Honeycomb should be +| | ... | ${dut1_node} | ${dut2_to_dut1_ip} +| | And Peer operational data from Honeycomb should be +| | ... | ${dut2_node} | ${dut1_to_dut2_ip} +| | And Honeycomb adds BGP peer +| | ... | ${dut2_node} | ${address_application} | ${peer_application} +| | And Honeycomb configures BGP route +| | ... | ${dut2_node} | ${address_application} | ${dut1_route_ip6} +| | ... | ${dut1_route_ip6_address} | ${dut1_route_ip6_id} | ipv6 +| | And Sleep | 5s | Wait for route advertisement. Retry timer is 5 seconds. +| | Then Routing data from Honeycomb should contain +| | ... | ${dut1_node} | learned-protocol-0 | ipv6 | ${route_ip6_operational} +| | And Routing data from Honeycomb should contain +| | ... | ${dut2_node} | learned-protocol-0 | ipv6 | ${route_ip6_operational} +| | And BGP Loc-RIB table should include | ${dut1_node} | ${rib_ip6_operational} +| | And BGP Loc-RIB table should include | ${dut2_node} | ${rib_ip6_operational} + +#TODO: Add tests once implemented in HC: +# IPv6 neighbor, L2VPN, L3VPN, linkstate, route reflector, and more + +*** Keywords *** +| Configure IPv4 Management Interface +| | [Documentation] | Change one of VPP's data-plane interfaces on DUT into\ +| | ... | a control-plane interface that Honeycomb can listen on. Setup IP\ +| | ... | addresses on the link, create suite variables for traffic trests, set +| | ... | static ARP entries, then restart VPP and Honeycomb to apply changes. +| | ... +| | Configure path in 3-node circular topology +| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']} +| | ${interface}= | Get Interface Name | ${dut1_node} | ${dut1_to_tg} +| | Set Suite Variable | ${interface} +| | Set Suite Variable | ${tg_node} +| | Set Suite Variable | ${dut1_node} +| | Set Suite Variable | ${dut2_node} +| | Set Suite Variable | ${dut1_to_tg} +| | Stop VPP service on DUT | ${dut1_node} +| | Stop VPP service on DUT | ${dut2_node} +| | Stop Honeycomb Service on DUTs | ${dut1_node} +| | Stop Honeycomb Service on DUTs | ${dut2_node} +| | Convert data-plane interface to control-plane +| | ... | ${dut1_node} | ${dut1_to_tg} +| | Convert data-plane interface to control-plane +| | ... | ${dut1_node} | ${dut1_to_dut2} +| | Convert data-plane interface to control-plane +| | ... | ${dut2_node} | ${dut2_to_dut1} +| | Sleep | 5sec | Wait until OS reclaims the interfaces. +| | ${tg_to_dut1_name}= | Get Interface Name by MAC +| | ... | ${tg_node} | ${tg_to_dut1_mac} +| | ${dut1_to_tg_name}= | Get Interface Name by MAC +| | ... | ${dut1_node} | ${dut1_to_tg_mac} +| | ${dut1_to_dut2_name}= | Get Interface Name by MAC +| | ... | ${dut1_node} | ${dut1_to_dut2_mac} +| | ${dut2_to_dut1_name}= | Get Interface Name by MAC +| | ... | ${dut2_node} | ${dut2_to_dut1_mac} +| | Set Suite Variable | ${dut1_to_tg_name} +| | Set Suite Variable | ${tg_to_dut1_name} +| | Set Suite Variable | ${dut1_to_dut2_name} +| | Set Suite Variable | ${dut2_to_dut1_name} +| | Set management interface address +| | ... | ${tg_node} | ${tg_to_dut1_name} +| | ... | ${tg_to_dut1_ip} | ${prefix} +| | Set management interface address +| | ... | ${dut1_node} | ${dut1_to_tg_name} +| | ... | ${dut1_to_tg_ip} | ${prefix} +| | Set management interface address +| | ... | ${dut1_node} | ${dut1_to_dut2_name} +| | ... | ${dut1_to_dut2_ip} | ${prefix} +| | Set management interface address +| | ... | ${dut2_node} | ${dut2_to_dut1_name} +| | ... | ${dut2_to_dut1_ip} | ${prefix} +| | Set Static ARP | ${tg_node} | ${dut1_to_tg_ip} | ${dut1_to_tg_mac} +| | Set Static ARP | ${dut1_node} | ${tg_to_dut1_ip} | ${tg_to_dut1_mac} +| | Set Static ARP | ${dut1_node} | ${dut2_to_dut1_ip} | ${dut2_to_dut1_mac} +| | Set Static ARP | ${dut2_node} | ${dut1_to_dut2_ip} | ${dut1_to_dut2_mac} +| | Enable Honeycomb Feature | ${dut2_node} | BGP +| | Configure BGP Module | ${dut1_node} | ${dut1_to_dut2_ip} +| | ... | ${bgp_port} | ${bgp_as_number} +| | Configure BGP Module | ${dut2_node} | ${dut2_to_dut1_ip} +| | ... | ${bgp_port} | ${bgp_as_number} +| | Start VPP service on DUT | ${dut1_node} +| | Start VPP service on DUT | ${dut2_node} +| | Configure Honeycomb service on DUTs | ${dut1_node} +| | Set Up Honeycomb Functional Test Suite | ${dut2_node} + +| Unconfigure IPv4 Management Interfaces +| | [Documentation] | Remove all IP addresses from the interface. +| | ... +| | Clear Interface Configuration | ${tg_node} | ${tg_to_dut1_name} +| | Clear Interface Configuration | ${dut1_node} | ${dut1_to_tg_name} +| | Clear Interface Configuration | ${dut1_node} | ${dut1_to_dut2_name} +| | Clear Interface Configuration | ${dut2_node} | ${dut2_to_dut1_name} + +| Set BGP Suite Variables +| | Configure path in 3-node circular topology +| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']} +| | Set Suite Variable | ${interface} +| | Set Suite Variable | ${tg_node} +| | Set Suite Variable | ${dut1_node} +| | Set Suite Variable | ${dut2_node} +| | Set Suite Variable | ${dut1_to_tg} +| | Set Suite Variable | ${dut1_to_tg_name} +| | Set Suite Variable | ${tg_to_dut1_name} +| | Set Suite Variable | ${dut1_to_dut2_name} +| | Set Suite Variable | ${dut2_to_dut1_name}