def vpp_get_span_configuration_by_interface(node, dst_interface, ret_format="sw_if_index"): """Get a list of all interfaces currently being mirrored to the specified interface. :param node: DUT node. :param dst_interface: Name, sw_if_index or key of interface. :param ret_format: Optional. Desired format of returned interfaces. :type node: dict :type dst_interface: str or int :type ret_format: string :returns: List of SPAN source interfaces for the provided destination interface. :rtype: list """ data = SPAN.vpp_get_span_configuration(node) dst_interface = Topology.convert_interface_reference( node, dst_interface, "sw_if_index") src_interfaces = [] for item in data: if item["dst-if-index"] == dst_interface: src_interfaces.append(item["src-if-index"]) if ret_format != "sw_if_index": src_interfaces = [ Topology.convert_interface_reference( node, interface, ret_format ) for interface in src_interfaces] return src_interfaces
def add_locator(node, interface, locator_set, priority=1, weight=1): """Configure a new LISP locator set. :param node: Honeycomb node. :param interface: An interface on the node. :param locator_set: Name for the new locator set. :param priority: Priority parameter for the locator. :param weight. Weight parameter for the locator. :type node: dict :type interface: str :type locator_set: str :type priority: int :type weight: int :returns: Content of response. :rtype: bytearray """ interface = Topology.convert_interface_reference( node, interface, "name") path = "/lisp-feature-data/locator-sets/locator-set" \ "/{0}".format(locator_set) data = { "locator-set": { "name": locator_set, "interface": { "interface-ref": interface, "priority": priority, "weight": weight } } } return LispKeywords._set_lisp_properties(node, path, data)
def get_interface_slaac_oper_data(node, interface): """Get operational data about SLAAC table present on the node. :param node: Honeycomb node. :param interface: Interface SLAAC data are retrieved from. :type node: dict :type interface: str :returns: dict of SLAAC operational data. :rtype: dict :raises HoneycombError: If status code differs from successful. """ interface = Topology.convert_interface_reference( node, interface, 'name') interface = interface.replace('/', '%2F') path = 'interface/' + interface status_code, resp = HcUtil.\ get_honeycomb_data(node, "config_slaac", path) if status_code != HTTPCodes.OK: raise HoneycombError( "Not possible to get operational information about SLAAC. " "Status code: {0}.".format(status_code)) try: dict_of_str = resp['interface'][0][ 'hc2vpp-ietf-ipv6-unicast-routing:ipv6-router-advertisements'] return {k: str(v) for k, v in dict_of_str.items()} except (KeyError, TypeError): return {}
def configure_interface_slaac(node, interface, slaac_data=None): """Configure SLAAC on the specified interfaces. :param node: Honeycomb node. :param interface: Interface to configure SLAAC. :param slaac_data: Dictionary of configurations to apply. \ If it is None then the existing configuration is removed. :type node: dict :type interface: str :type slaac_data: dict of dicts :returns: Content of response. :rtype: bytearray :raises HoneycombError: If RA could not be configured. """ interface = Topology.convert_interface_reference( node, interface, 'name') interface = interface.replace('/', '%2F') path = 'interface/' + interface + '/ipv6/ipv6-router-advertisements' if not slaac_data: status_code, _ = HcUtil.delete_honeycomb_data( node, 'config_slaac', path) else: data = { 'ipv6-router-advertisements': slaac_data } status_code, _ = HcUtil.put_honeycomb_data( node, 'config_slaac', data, path) if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( 'Configuring SLAAC failed. Status code:{0}'.format(status_code))
def set_proxyarp_interface_config(node, interface, state): """Enable or disable the proxyARP feature on the specified interface. :param node: Honeycomb node. :param interface: Name or sw_if_index of an interface on the node. :param state: Desired proxyARP state: enable, disable. :type node: dict :type interface: str :type state: str :raises ValueError: If the state argument is incorrect. :raises HoneycombError: If the status code in response is not 200 = OK or 201 = ACCEPTED. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") path = "/interface/{0}/proxy-arp".format(interface) if state == "disable": status_code, _ = HcUtil.delete_honeycomb_data( node, "config_vpp_interfaces", path) elif state == "enable": data = {"proxy-arp": {}} status_code, _ = HcUtil.put_honeycomb_data( node, "config_vpp_interfaces", data, path) else: raise ValueError("State argument has to be enable or disable.") if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( "Interface proxyARP configuration on node {0} was not" " successful.".format(node["host"]))
def get_ipv6nd_configuration(node, interface): """Read IPv6 Neighbor Discovery proxy configuration on the specified interface. :param node: Honeycomb node. :param interface: Name of an interface on the node. :type node: dict :type interface: str :returns: Content of response. :rtype: bytearray :raises HoneycombError: If the configuration could not be read. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") path = "/interface/{0}/ietf-ip:ipv6/nd-proxies".format(interface) status_code, resp = HcUtil.get_honeycomb_data(node, "config_vpp_interfaces", path) if status_code != HTTPCodes.OK: raise HoneycombError("Could not read IPv6 ND proxy configuration. " "Status code: {0}.".format(status_code)) else: return resp
def configure_ipv6nd(node, interface, addresses=None): """Configure IPv6 Neighbor Discovery proxy on the specified interface, or remove/replace an existing configuration. :param node: Honeycomb node. :param interface: Name of an interface on the node. :param addresses: IPv6 addresses to configure ND proxy with. If no address is provided, ND proxy configuration will be removed. :type node: dict :type interface: str :type addresses: list :returns: Content of response. :rtype: bytearray :raises HoneycombError: If the operation fails. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") path = "/interface/{0}/ietf-ip:ipv6/nd-proxies".format(interface) if addresses is None: status_code, resp = HcUtil. \ delete_honeycomb_data(node, "config_vpp_interfaces", path) else: data = { "nd-proxies": { "nd-proxy": [{ "address": x } for x in addresses] } } status_code, resp = HcUtil. \ put_honeycomb_data(node, "config_vpp_interfaces", data, path, data_representation=DataRepresentation.JSON) if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError("IPv6 ND proxy configuration unsuccessful. " "Status code: {0}.".format(status_code)) else: return resp
def set_acl_plugin_interface(node, interface, acl_name, direction): """Assign an interface to an ietf-acl classify chain. :param node: Honeycomb node. :param interface: Name of an interface on the node. :param acl_name: Name of an ACL chain configured through ACL-plugin. :param direction: Classify incoming or outgoing packets. Valid options are: ingress, egress :type node: dict :type interface: str or int :type acl_name: str :type direction: str :returns: Content of response. :rtype: bytearray :raises ValueError: If the direction argument is incorrect. :raises HoneycombError: If the operation fails. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") if direction not in ("ingress", "egress"): raise ValueError( "Unknown traffic direction {0}. " "Valid options are: ingress, egress.".format(direction)) path = "/attachment-points/interface/{0}/{1}/acl-sets/".format( interface, direction) data = {"acl-sets": {"acl-set": {"name": acl_name}}} status_code, resp = HcUtil.put_honeycomb_data(node, "config_plugin_acl", data, path) if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError("Could not configure ACL on interface. " "Status code: {0}.".format(status_code)) return resp
def delete_interface_plugin_acls(node, interface): """Remove all plugin-acl assignments from an interface. :param node: Honeycomb node. :param interface: Name of an interface on the node. :type node: dict :type interface: str or int """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") path = "/interface/{0}/interface-acl:acl/".format(interface) status_code, _ = HcUtil.delete_honeycomb_data(node, "config_vpp_interfaces", path) if status_code != HTTPCodes.OK: raise HoneycombError( "Could not remove ACL assignment from interface. " "Status code: {0}.".format(status_code))
def configure_nat_on_interface(node, interface, direction, delete=False): """Configure NAT on the specified interface. :param node: Honeycomb node. :param interface: Name of an interface on the node. :param direction: NAT direction, outbound or inbound. :param delete: Delete an existing interface NAT configuration. :type node: dict :type interface: str :type direction: str :type delete: bool :returns: Content of response. :rtype: bytearray :raises HoneycombError: If the operation fails. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") path = "/interface/{0}/interface-nat:nat/{1}".format( interface, direction) data = {direction: {}} if delete: status_code, resp = HcUtil.delete_honeycomb_data( node, "config_vpp_interfaces", path) else: status_code, resp = HcUtil.put_honeycomb_data( node, "config_vpp_interfaces", data, path) if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError("Could not configure NAT on interface. " "Status code: {0}.".format(status_code)) return resp
def vpp_get_interface_ip_addresses(node, interface, ip_version): """Get list of IP addresses from an interface on a VPP node. :param node: VPP node to get data from. :param interface: Name of an interface on the VPP node. :param ip_version: IP protocol version (ipv4 or ipv6). :type node: dict :type interface: str :type ip_version: str :returns: List of dictionaries, each containing IP address, subnet prefix length and also the subnet mask for ipv4 addresses. Note: A single interface may have multiple IP addresses assigned. :rtype: list """ try: sw_if_index = Topology.convert_interface_reference( node, interface, "sw_if_index") except RuntimeError: if isinstance(interface, basestring): sw_if_index = InterfaceUtil.get_sw_if_index(node, interface) else: raise with VatTerminal(node) as vat: response = vat.vat_terminal_exec_cmd_from_template( "ip_address_dump.vat", ip_version=ip_version, sw_if_index=sw_if_index) data = response[0] if ip_version == "ipv4": for item in data: item["netmask"] = convert_ipv4_netmask_prefix( item["prefix_length"]) return data
def get_variables(node, ip_version, out_interface): out_interface = Topology.convert_interface_reference( node, out_interface, "name") ip_version = ip_version.lower() variables = {} # base network settings ipv4_base = { "dut_to_tg_if1_ip": "16.0.0.1", "dut_to_tg_if2_ip": "16.0.1.1", "src_ip": "16.0.0.2", "dst_ip": "16.0.2.1", "dst_net": "16.0.2.0", "prefix_len": 24, "next_hop": "16.0.1.2", "next_hop1": "16.0.1.3", "next_hop2": "16.0.1.4", "next_hop_mac1": "00:11:22:33:44:55", "next_hop_mac2": "11:22:33:44:55:66" } ipv6_base = { "dut_to_tg_if1_ip": "10::1", "dut_to_tg_if2_ip": "11::1", "src_ip": "10::2", "dst_ip": "12::1", "dst_net": "12::", "prefix_len": 64, "next_hop": "11::2", "next_hop1": "11::3", "next_hop2": "11::4", "next_hop_mac1": "00:11:22:33:44:55", "next_hop_mac2": "11:22:33:44:55:66" } if ip_version == "ipv4": variables.update(ipv4_base) elif ip_version == "ipv6": variables.update(ipv6_base) else: raise ValueError("IP version must be either IPv4 or IPv6.") # route configuration used in tests tables_cfg = { "table1": { "id": 1, "description": "single hop ipv4", "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "next-hop": ipv4_base["next_hop"], "outgoing-interface": out_interface, "vpp-ipv4-route": {} }, "table2": { "id": 1, "description": "multi hop ipv4", "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "next-hop-list": { "next-hop": [{ "id": 1, "address": ipv4_base["next_hop1"], "outgoing-interface": out_interface, "weight": "1" }, { "id": 2, "address": ipv4_base["next_hop2"], "outgoing-interface": out_interface, "weight": "1" }] } }, "table3": { "id": 1, "description": "blackhole ipv4", "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "special-next-hop": "receive" }, "table4": { "id": 1, "description": "single hop ipv6", "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "next-hop": ipv6_base["next_hop"], "outgoing-interface": out_interface, "vpp-ipv6-route": {} }, "table5": { "id": 1, "description": "multi hop ipv6", "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "next-hop-list": { "next-hop": [{ "id": 1, "address": ipv6_base["next_hop1"], "outgoing-interface": out_interface, "weight": "1" }, { "id": 2, "address": ipv6_base["next_hop2"], "outgoing-interface": out_interface, "weight": "1" }] } }, "table6": { "id": 1, "description": "blackhole ipv6", "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "special-next-hop": "blackhole" } } # expected route operational data tables_oper = { "table1_oper": { "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "next-hop": ipv4_base["next_hop"], "outgoing-interface": out_interface, "vpp-ipv4-route-state": {} }, "table2_oper": { "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "next-hop-list": { "next-hop": [{ "address": ipv4_base["next_hop1"], "outgoing-interface": out_interface, "weight": 1 }, { "address": ipv4_base["next_hop2"], "outgoing-interface": out_interface, "weight": 1 }] }, 'vpp-ipv4-route-state': {} }, "table3_oper": { "destination-prefix": "{0}/{1}".format(ipv4_base["dst_net"], ipv4_base["prefix_len"]), "special-next-hop": "receive", "vpp-ipv4-route-state": {} }, "table4_oper": { "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "next-hop": ipv6_base["next_hop"], "outgoing-interface": out_interface, "vpp-ipv6-route-state": {} }, "table5_oper": { "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "next-hop-list": { "next-hop": [{ "address": ipv6_base["next_hop1"], "outgoing-interface": out_interface, "weight": 1 }, { "address": ipv6_base["next_hop2"], "outgoing-interface": out_interface, "weight": 1 }] }, "vpp-ipv6-route-state": {} }, "table6_oper": { "destination-prefix": "{0}/{1}".format(ipv6_base["dst_net"], ipv6_base["prefix_len"]), "special-next-hop": "blackhole", 'vpp-ipv6-route-state': {} } } for item in tables_oper.values(): if "next-hop-list" in item.keys(): item["next-hop-list"]["next-hop"].sort() variables.update(tables_cfg) variables.update(tables_oper) return variables
def set_acl_plugin_interface(node, interface, acl_name, direction, macip=False): """Assign an interface to an ietf-acl classify chain. :param node: Honeycomb node. :param interface: Name of an interface on the node. :param acl_name: Name of an ACL chain configured through ACL-plugin. :param direction: Classify incoming or outgiong packets. Valid options are: ingress, egress :param macip: Use simple MAC+IP classifier. Optional. :type node: dict :type interface: str or int :type acl_name: str :type direction: str :type macip: bool :returns: Content of response. :rtype: bytearray :raises ValueError: If the direction argument is incorrect. :raises HoneycombError: If the operation fails. """ interface = Topology.convert_interface_reference( node, interface, "name") interface = interface.replace("/", "%2F") if direction not in ("ingress", "egress"): raise ValueError( "Unknown traffic direction {0}. " "Valid options are: ingress, egress.".format(direction)) path = "/interface/{0}/interface-acl:acl/{1}".format( interface, direction) if macip: data = { direction: { "vpp-macip-acl": { "type": "vpp-acl:vpp-macip-acl", "name": acl_name } } } else: data = { direction: { "vpp-acls": [{ "type": "vpp-acl:vpp-acl", "name": acl_name }] } } status_code, resp = HcUtil.put_honeycomb_data(node, "config_vpp_interfaces", data, path) if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError("Could not configure ACL on interface. " "Status code: {0}.".format(status_code)) return resp
def get_variables(node, interface): """Create and return a dictionary of test variables. :param node: Honeycomb node. :param interface: Name, link name or sw_if_index of an interface. :type node: dict :type interface: str or int :returns: Dictionary of test variables - settings for Honeycomb's NAT node and expected operational data. :rtype: dict """ sw_if_index = Topology.convert_interface_reference(node, interface, "sw_if_index") variables = { "nat_empty": { 'instances': { 'instance': [{ 'id': 0 }] } }, "entry1": { "mapping-entry": [{ "index": 1, "type": "static", "internal-src-address": "192.168.0.1/32", "external-src-address": "192.168.1.1/32" }] }, "entry2": { "mapping-entry": [{ "index": 2, "type": "static", "internal-src-address": "192.168.0.2/32", "external-src-address": "192.168.1.2/32" }] }, "entry1_2_oper": { "mapping-entry": [{ "index": 1, "type": "static", "internal-src-address": "192.168.0.1/32", "external-src-address": "192.168.1.1/32" }, { "index": 2, "type": "static", "internal-src-address": "192.168.0.2/32", "external-src-address": "192.168.1.2/32" }] }, "entry1_vat": [{ "local_address": "192.168.0.1", "remote_address": "192.168.1.1", "vrf": "0" }], "entry1_2_vat": [{ "local_address": "192.168.0.1", "remote_address": "192.168.1.1", "vrf": "0", "protocol": "17" }, { "local_address": "192.168.0.2", "remote_address": "192.168.1.2", "vrf": "0", "protocol": "17" }], "nat_interface_vat_in": [{ "sw_if_index": str(sw_if_index), "direction": "in" }], "nat_interface_vat_out": [{ "sw_if_index": str(sw_if_index), "direction": "out" }] } return variables