def vpp_creates_classify_table_l2(node, direction): """Create classify table for MAC address filtering. :param node: VPP node to create classify table. :param direction: Direction of traffic - src/dst. :type node: dict :type direction: str :returns: (table_index, skip_n, match_n) table_index: Classify table index. skip_n: Number of skip vectors. match_n: Number of match vectors. :rtype: tuple(int, int, int) :raises RuntimeError: If VPP can't create table. """ output = VatExecutor.cmd_from_template(node, "classify_add_table_l2.vat", direction=direction) if output[0]["retval"] == 0: table_index = output[0]["new_table_index"] skip_n = output[0]["skip_n_vectors"] match_n = output[0]["match_n_vectors"] logger.trace( 'Classify table with table_index {} created on node {}'.format( table_index, node['host'])) else: raise RuntimeError( 'Unable to create classify table on node {}'.format( node['host'])) return table_index, skip_n, match_n
def vpp_ra_send_after_interval(node, interface, interval=2): """Setup vpp router advertisement(RA) in such way it sends RA packet after and every interval value. :param node: VPP node. :param interface: Interface name. :param interval: Interval for RA resend :type node: dict :type interface: str :type interval: int """ sw_if_index = Topology.get_interface_sw_index(node, interface) VatExecutor.cmd_from_template(node, 'sw_interface_ip6nd_ra_config.vat', sw_if_id=sw_if_index, param='interval {0}'.format(interval))
def vpp_creates_classify_table_hex(node, hex_mask): """Create classify table with hex mask. :param node: VPP node to create classify table based on hex mask. :param hex_mask: Classify hex mask. :type node: dict :type hex_mask: str :returns: (table_index, skip_n, match_n) table_index: Classify table index. skip_n: Number of skip vectors. match_n: Number of match vectors. :rtype: tuple(int, int, int) :raises RuntimeError: If VPP can't create table. """ output = VatExecutor.cmd_from_template(node, "classify_add_table_hex.vat", hex_mask=hex_mask) if output[0]["retval"] == 0: table_index = output[0]["new_table_index"] skip_n = output[0]["skip_n_vectors"] match_n = output[0]["match_n_vectors"] logger.trace( 'Classify table with table_index {} created on node {}'.format( table_index, node['host'])) else: raise RuntimeError( 'Unable to create classify table on node {}'.format( node['host'])) return table_index, skip_n, match_n
def create_vxlan_interface(node, vni, source_ip, destination_ip): """Create VXLAN interface and return sw if index of created interface. Executes "vxlan_add_del_tunnel src {src} dst {dst} vni {vni}" VAT command on the node. :param node: Node where to create VXLAN interface. :param vni: VXLAN Network Identifier. :param source_ip: Source IP of a VXLAN Tunnel End Point. :param destination_ip: Destination IP of a VXLAN Tunnel End Point. :type node: dict :type vni: int :type source_ip: str :type destination_ip: str :returns: SW IF INDEX of created interface. :rtype: int :raises RuntimeError: if it is unable to create VxLAN interface on the node. """ output = VatExecutor.cmd_from_template(node, "vxlan_create.vat", src=source_ip, dst=destination_ip, vni=vni) output = output[0] if output["retval"] == 0: return output["sw_if_index"] else: raise RuntimeError('Unable to create VXLAN interface on node {0}' .format(node))
def map_add_rule(vpp_node, index, psid, dst, delete=False): """Add or delete map rule on node. :param vpp_node: VPP node to add map rule on. :param index: Map domain index to add rule to. :param psid: Port Set Identifier. :param dst: MAP CE IPv6 address. :param delete: If set to True, delete rule. Default False. :type vpp_node: dict :type index: int :type psid: int :type dst: str :type delete: bool :raises RuntimeError: If unable to add map rule. """ output = VatExecutor.cmd_from_template(vpp_node, "map_add_del_rule.vat", index=index, psid=psid, dst=dst, delete='del' if delete else '') if output[0]["retval"] != 0: raise RuntimeError('Unable to add map rule on node {}'.format( vpp_node['host']))
def create_gre_tunnel_interface(node, source_ip, destination_ip): """Create GRE tunnel interface on node. :param node: VPP node to add tunnel interface. :param source_ip: Source of the GRE tunnel. :param destination_ip: Destination of the GRE tunnel. :type node: dict :type source_ip: str :type destination_ip: str :returns: Name and index of created GRE tunnel interface. :rtype: tuple :raises RuntimeError: If unable to create GRE tunnel interface. """ output = VatExecutor.cmd_from_template(node, "create_gre.vat", src=source_ip, dst=destination_ip) output = output[0] if output["retval"] == 0: sw_if_index = output["sw_if_index"] vat_executor = VatExecutor() vat_executor.execute_script_json_out("dump_interfaces.vat", node) interface_dump_json = vat_executor.get_script_stdout() name = VatJsonUtil.get_interface_name_from_json( interface_dump_json, sw_if_index) return name, sw_if_index else: raise RuntimeError('Unable to create GRE tunnel on node {}.' .format(node))
def create_vlan_subinterface(node, interface, vlan): """Create VLAN subinterface on node. :param node: Node to add VLAN subinterface on. :param interface: Interface name on which create VLAN subinterface. :param vlan: VLAN ID of the subinterface to be created. :type node: dict :type interface: str :type vlan: int :returns: Name and index of created subinterface. :rtype: tuple :raises RuntimeError: if it is unable to create VLAN subinterface on the node. """ iface_key = Topology.get_interface_by_name(node, interface) sw_if_index = Topology.get_interface_sw_index(node, iface_key) output = VatExecutor.cmd_from_template(node, "create_vlan_subif.vat", sw_if_index=sw_if_index, vlan=vlan) if output[0]["retval"] == 0: sw_subif_index = output[0]["sw_if_index"] logger.trace('VLAN subinterface with sw_if_index {} and VLAN ID {} ' 'created on node {}'.format(sw_subif_index, vlan, node['host'])) else: raise RuntimeError('Unable to create VLAN subinterface on node {}' .format(node['host'])) with VatTerminal(node, False) as vat: vat.vat_terminal_exec_cmd('exec show interfaces') return '{}.{}'.format(interface, vlan), sw_subif_index
def create_subinterface(node, interface, sub_id, outer_vlan_id=None, inner_vlan_id=None, type_subif=None): """Create sub-interface on node. It is possible to set required sub-interface type and VLAN tag(s). :param node: Node to add sub-interface. :param interface: Interface name on which create sub-interface. :param sub_id: ID of the sub-interface to be created. :param outer_vlan_id: Optional outer VLAN ID. :param inner_vlan_id: Optional inner VLAN ID. :param type_subif: Optional type of sub-interface. Values supported by VPP: [no_tags] [one_tag] [two_tags] [dot1ad] [exact_match] [default_sub] :type node: dict :type interface: str or int :type sub_id: int :type outer_vlan_id: int :type inner_vlan_id: int :type type_subif: str :returns: Name and index of created sub-interface. :rtype: tuple :raises RuntimeError: If it is not possible to create sub-interface. """ outer_vlan_id = 'outer_vlan_id {0}'.format(outer_vlan_id)\ if outer_vlan_id else '' inner_vlan_id = 'inner_vlan_id {0}'.format(inner_vlan_id)\ if inner_vlan_id else '' if type_subif is None: type_subif = '' if isinstance(interface, basestring): iface_key = Topology.get_interface_by_name(node, interface) sw_if_index = Topology.get_interface_sw_index(node, iface_key) else: sw_if_index = interface output = VatExecutor.cmd_from_template(node, "create_sub_interface.vat", sw_if_index=sw_if_index, sub_id=sub_id, outer_vlan_id=outer_vlan_id, inner_vlan_id=inner_vlan_id, type_subif=type_subif) if output[0]["retval"] == 0: sw_subif_index = output[0]["sw_if_index"] logger.trace('Created subinterface with index {}' .format(sw_subif_index)) else: raise RuntimeError('Unable to create sub-interface on node {}' .format(node['host'])) with VatTerminal(node, json_param=False) as vat: vat.vat_terminal_exec_cmd('exec show interfaces') name = '{}.{}'.format(interface, sub_id) return name, sw_subif_index
def add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg=0): """Add interface with sw_if_index to l2 bridge domain. Execute the "sw_interface_set_l2_bridge sw_if_index {sw_if_index} bd_id {bd_id} shg {shg} enable" VAT command on the given node. :param node: Node where we want to execute the command that does this. :param sw_if_index: Interface index. :param bd_id: Bridge domain index number to add SW IF ID to. :param shg: Split horizon group. :type node: dict :type sw_if_index: int :type bd_id: int :type shg: int """ VatExecutor.cmd_from_template(node, "l2_bd_add_sw_if_index.vat", bd_id=bd_id, sw_if_index=sw_if_index, shg=shg)
def enable_disable_macswap_vat_exec(node, interface_name): """Enable/Disable macswap on interface. Function can be used on a VPP node with macswap plugin. :param node: Node where the interface is. :param interface_name: Interface name. :type node: dict :type interface_name: str or int :return: nothing """ if node['type'] == NodeType.DUT: VatExecutor.cmd_from_template(node, 'macswap_exec.vat', if_name=interface_name) else: raise ValueError('Node {} has not DUT NodeType: "{}"'. format(node['host'], node['type']))
def vpp_add_l2fib_entry(node, mac, interface, bd_id): """ Create a static L2FIB entry on a vpp node. :param node: Node to add L2FIB entry on. :param mac: Destination mac address. :param interface: Interface name or sw_if_index. :param bd_id: Bridge domain id. :type node: dict :type mac: str :type interface: str or int :type bd_id: int """ if isinstance(interface, basestring): sw_if_index = Topology.get_interface_sw_index(node, interface) else: sw_if_index = interface VatExecutor.cmd_from_template(node, "add_l2_fib_entry.vat", mac=mac, bd=bd_id, interface=sw_if_index)
def enable_disable_macswap_vat(node, interface): """Enable/Disable macswap on interface. Function can be used on a VPP node with macswap plugin. :param node: Node where the interface is. :param interface: Interface id. :type node: dict :type interface: str or int :return: nothing """ if node['type'] == NodeType.DUT: sw_if_index = Topology.get_interface_sw_index(node, interface) VatExecutor.cmd_from_template(node, 'macswap.vat', sw_if_index=sw_if_index) else: raise ValueError('Node {} has not DUT NodeType: "{}"'. format(node['host'], node['type']))
def vpp_add_lisp_remote_mapping(node, vni, deid, deid_prefix, seid, seid_prefix, rloc, is_mac=False): """Add lisp remote mapping on the VPP node in topology. :param node: VPP node. :param vni: Vni. :param deid: Destination eid address. :param deid_prefix: Destination eid address prefix_len. :param seid: Source eid address. :param seid_prefix: Source eid address prefix_len. :param rloc: Receiver locator. :param is_mac: Set to True if the deid/seid is MAC address. :type node: dict :type vni: int :type deid: str :type deid_prefix: int :type seid: str :type seid_prefix: int :type rloc: str :type is_mac: bool """ if is_mac: deid_prefix = '' seid_prefix = '' else: deid_prefix = '/{}'.format(deid_prefix) seid_prefix = '/{}'.format(seid_prefix) VatExecutor.cmd_from_template(node, 'lisp/add_lisp_remote_mapping.vat', vni=vni, deid=deid, deid_prefix=deid_prefix, seid=seid, seid_prefix=seid_prefix, rloc=rloc)
def vpp_lisp_eid_table_mapping(node, vni, bd_id=None, vrf=None): """ Map LISP VNI to either bridge domain ID, or VRF ID. :param node: VPP node. :param vni: Lisp VNI. :param bd_id: Bridge domain ID. :param vrf: VRF id. :type node: dict :type vni: int :type bd_id: int :type vrf: int """ if bd_id: bd_or_vrf = 'bd_index {}'.format(bd_id) else: bd_or_vrf = 'vrf {}'.format(vrf) VatExecutor.cmd_from_template(node, 'lisp/lisp_eid_table_add_del_map.vat', vni=vni, bd_or_vrf=bd_or_vrf)
def vpp_del_lisp_locator(node, locator_name, sw_if_index, priority, weight): """Unset lisp locator on the VPP node in topology. :param node: VPP node. :param locator_name: Name of the locator_set. :param sw_if_index: sw_if_index if the interface. :param priority: priority of the locator. :param weight: weight of the locator. :type node: dict :type locator_name: str :type sw_if_index: int :type priority: int :type weight: int """ VatExecutor.cmd_from_template(node, 'lisp/del_lisp_locator.vat', lisp_name=locator_name, sw_if_index=sw_if_index, priority=priority, weight=weight)
def vpp_add_l2_bridge_domain(node, bd_id, port_1, port_2, learn=True): """Add L2 bridge domain with 2 interfaces to the VPP node. :param node: Node to add L2BD on. :param bd_id: Bridge domain ID. :param port_1: First interface name added to L2BD. :param port_2: Second interface name added to L2BD. :param learn: Enable/disable MAC learn. :type node: dict :type bd_id: int :type port_1: str :type port_2: str :type learn: bool """ sw_if_index1 = Topology.get_interface_sw_index(node, port_1) sw_if_index2 = Topology.get_interface_sw_index(node, port_2) VatExecutor.cmd_from_template(node, 'l2_bridge_domain.vat', sw_if_id1=sw_if_index1, sw_if_id2=sw_if_index2, bd_id=bd_id, learn=int(learn))
def vpp_ipsec_add_spd(node, spd_id): """Create Security Policy Database on the VPP node. :param node: VPP node to add SPD on. :param spd_id: SPD ID. :type node: dict :type spd_id: int """ out = VatExecutor.cmd_from_template(node, "ipsec/ipsec_spd_add.vat", spd_id=spd_id) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add SPD {0} failed on {1}'.format(spd_id, node['host']))
def vpp_get_dhcp_proxy(node, ip_version): """Retrieve DHCP relay configuration. :param node: VPP node. :param ip_version: IP protocol version: ipv4 or ipv6. :type node: dict :type ip_version: str :returns: DHCP relay data. :rtype: list """ return VatExecutor.cmd_from_template( node, "dhcp_proxy_dump.vat", ipv6="ipv6" if ip_version == "ipv6" else "")
def map_del_domain(vpp_node, index): """Delete map domain on node. :param vpp_node: VPP node to delete map domain on. :param index: Index of the map domain. :type vpp_node: dict :type index: int :raises RuntimeError: If unable to delete map domain. """ output = VatExecutor.cmd_from_template(vpp_node, "map_del_domain.vat", index=index) if output[0]["retval"] != 0: raise RuntimeError('Unable to delete map domain {} on node {}' .format(index, vpp_node['host']))
def create_l2_bd(node, bd_id, flood=1, uu_flood=1, forward=1, learn=1, arp_term=0): """Create a l2 bridge domain on the chosen VPP node Execute "bridge_domain_add_del bd_id {bd_id} flood {flood} uu-flood 1 forward {forward} learn {learn} arp-term {arp_term}" VAT command on the node. :param node: Node where we wish to crate the l2 bridge domain. :param bd_id: Bridge domain index number. :param flood: Enable flooding. :param uu_flood: Enable uu_flood. :param forward: Enable forwarding. :param learn: Enable mac address learning to fib. :param arp_term: Enable arp_termination. :type node: dict :type bd_id: int :type flood: bool :type uu_flood: bool :type forward: bool :type learn: bool :type arp_term:bool """ VatExecutor.cmd_from_template(node, "l2_bd_create.vat", bd_id=bd_id, flood=flood, uu_flood=uu_flood, forward=forward, learn=learn, arp_term=arp_term)
def vpp_ipsec_add_sad_entry(node, sad_id, spi, crypto_alg, crypto_key, integ_alg, integ_key, tunnel_src=None, tunnel_dst=None): """Create Security Association Database entry on the VPP node. :param node: VPP node to add SAD entry on. :param sad_id: SAD entry ID. :param spi: Security Parameter Index of this SAD entry. :param crypto_alg: The encryption algorithm name. :param crypto_key: The encryption key string. :param integ_alg: The integrity algorithm name. :param integ_key: The integrity key string. :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not specified ESP transport mode is used. :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If not specified ESP transport mode is used. :type node: dict :type sad_id: int :type spi: int :type crypto_alg: CryptoAlg :type crypto_key: str :type integ_alg: str :type integ_key: str :type tunnel_src: str :type tunnel_dst: str """ ckey = crypto_key.encode('hex') ikey = integ_key.encode('hex') tunnel = 'tunnel_src {0} tunnel_dst {1}'.format(tunnel_src, tunnel_dst)\ if tunnel_src is not None and tunnel_dst is not None else '' out = VatExecutor.cmd_from_template(node, "ipsec/ipsec_sad_add_entry.vat", sad_id=sad_id, spi=spi, calg=crypto_alg.alg_name, ckey=ckey, ialg=integ_alg.alg_name, ikey=ikey, tunnel=tunnel) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add SAD entry failed on {0}'.format(node['host']))
def vpp_create_loopback(node): """Create loopback interface on VPP node. :param node: Node to create loopback interface on. :type node: dict :returns: SW interface index. :rtype: int :raises RuntimeError: If it is not possible to create loopback on the node. """ out = VatExecutor.cmd_from_template(node, "create_loopback.vat") if out[0].get('retval') == 0: return out[0].get('sw_if_index') else: raise RuntimeError('Create loopback failed on node "{}"' .format(node['host']))
def map_add_domain(vpp_node, ip4_pfx, ip6_pfx, ip6_src, ea_bits_len, psid_offset, psid_len, map_t=False): """Add map domain on node. :param vpp_node: VPP node to add map domain on. :param ip4_pfx: Rule IPv4 prefix. :param ip6_pfx: Rule IPv6 prefix. :param ip6_src: MAP domain IPv6 BR address / Tunnel source. :param ea_bits_len: Embedded Address bits length. :param psid_offset: Port Set Identifier (PSID) offset. :param psid_len: Port Set Identifier (PSID) length. :param map_t: Mapping using translation instead of encapsulation. Default False. :type vpp_node: dict :type ip4_pfx: str :type ip6_pfx: str :type ip6_src: str :type ea_bits_len: int :type psid_offset: int :type psid_len: int :type map_t: bool :returns: Index of created map domain. :rtype: int :raises RuntimeError: If unable to add map domain. """ translate = 'map-t' if map_t else '' output = VatExecutor.cmd_from_template(vpp_node, "map_add_domain.vat", ip4_pfx=ip4_pfx, ip6_pfx=ip6_pfx, ip6_src=ip6_src, ea_bits_len=ea_bits_len, psid_offset=psid_offset, psid_len=psid_len, map_t=translate) if output[0]["retval"] == 0: return output[0]["index"] else: raise RuntimeError('Unable to add map domain on node {}'.format( vpp_node['host']))
def vpp_create_vhost_user_interface(node, socket): """Create Vhost-user interface on VPP node. :param node: Node to create Vhost-user interface on. :param socket: Vhost-user interface socket path. :type node: dict :type socket: str :return: SW interface index. :rtype: int """ out = VatExecutor.cmd_from_template(node, "create_vhost_user_if.vat", sock=socket) if out[0].get('retval') == 0: return out[0].get('sw_if_index') else: raise RuntimeError('Create Vhost-user interface failed on node ' '"{}"'.format(node['host']))
def vpp_ipsec_spd_add_if(node, spd_id, interface): """Add interface to the Security Policy Database. :param node: VPP node. :param spd_id: SPD ID to add interface on. :param interface: Interface name or sw_if_index. :type node: dict :type spd_id: int :type interface: str or int """ sw_if_index = Topology.get_interface_sw_index(node, interface)\ if isinstance(interface, basestring) else interface out = VatExecutor.cmd_from_template(node, "ipsec/ipsec_interface_add_spd.vat", spd_id=spd_id, sw_if_id=sw_if_index) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add interface {0} to SPD {1} failed on {2}'.format( interface, spd_id, node['host']))
def vpp_create_loopback(node): """Create loopback interface on VPP node. :param node: Node to create loopback interface on. :type node: dict :returns: SW interface index. :rtype: int :raises RuntimeError: If it is not possible to create loopback on the node. """ out = VatExecutor.cmd_from_template(node, "create_loopback.vat") if out[0].get('retval') == 0: sw_if_idx = out[0].get('sw_if_index') if_key = Topology.add_new_port(node, "loopback") Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx) Topology.update_interface_name(node, if_key, ifc_name) return sw_if_idx else: raise RuntimeError('Create loopback failed on node "{}"' .format(node['host']))
def dhcp_proxy_config(vpp_node, server_address, source_address): """Set DHCP proxy. :param vpp_node: VPP node to set DHCP proxy. :param server_address: DHCP server IP address. :param source_address: DHCP proxy address. :type vpp_node: dict :type server_address: str :type source_address: str :raises RuntimeError: If unable to set DHCP proxy. """ output = VatExecutor.cmd_from_template(vpp_node, "dhcp_proxy_config.vat", server_address=server_address, source_address=source_address) output = output[0] if output["retval"] != 0: raise RuntimeError('Unable to set DHCP proxy on node {}' .format(vpp_node))
def vpp_ipsec_sa_set_key(node, sa_id, crypto_key, integ_key): """Update Security Association (SA) keys. :param node: VPP node to update SA keys. :param sa_id: SAD entry ID. :param crypto_key: The encryption key string. :param integ_key: The integrity key string. :type node: dict :type sa_id: int :type crypto_key: str :type integ_key: str """ ckey = crypto_key.encode('hex') ikey = integ_key.encode('hex') out = VatExecutor.cmd_from_template(node, "ipsec/ipsec_sa_set_key.vat", sa_id=sa_id, ckey=ckey, ikey=ikey) VatJsonUtil.verify_vat_retval( out[0], err_msg='Update SA key failed on {0}'.format(node['host']))
def vpp_enslave_physical_interface(node, interface, bond_interface): """Enslave physical interface to bond interface on VPP node. :param node: DUT node from topology. :param interface: Physical interface key from topology file. :param bond_interface: Load balance :type node: dict :type interface: str :type bond_interface: str :raises RuntimeError: If it is not possible to enslave physical interface to bond interface on the node. """ ifc = Topology.get_interface_sw_index(node, interface) bond_ifc = Topology.get_interface_sw_index(node, bond_interface) output = VatExecutor.cmd_from_template( node, 'enslave_physical_interface.vat', p_int=ifc, b_int=bond_ifc) retval = output[0].get('retval', None) if retval is None or int(retval) != 0: raise RuntimeError('Enslave physical interface {ifc} to bond ' 'interface {bond} failed on node "{n}"' .format(ifc=interface, bond=bond_interface, n=node['host']))
def vpp_create_bond_interface(node, mode, load_balance=None, mac=None): """Create bond interface on VPP node. :param node: DUT node from topology. :param mode: Link bonding mode. :param load_balance: Load balance (optional, valid for xor and lacp modes, otherwise ignored). :param mac: MAC address to assign to the bond interface (optional). :type node: dict :type mode: str :type load_balance: str :type mac: str :returns: Interface key (name) in topology. :rtype: str :raises RuntimeError: If it is not possible to create bond interface on the node. """ hw_addr = '' if mac is None else 'hw-addr {mac}'.format(mac=mac) lb = '' if load_balance is None \ else 'lb {lb}'.format(lb=load_balance) output = VatExecutor.cmd_from_template(node, 'create_bond_interface.vat', mode=mode, lb=lb, mac=hw_addr) if output[0].get('retval') == 0: sw_if_idx = output[0].get('sw_if_index') InterfaceUtil.add_bond_eth_interface(node, sw_if_idx=sw_if_idx) if_key = Topology.get_interface_by_sw_index(node, sw_if_idx) return if_key else: raise RuntimeError( 'Create bond interface failed on node "{n}"'.format( n=node['host']))