def update_vpp_interface_data_on_node(node): """Update vpp generated interface data for a given node in DICT__nodes. Updates interface names, software if index numbers and any other details generated specifically by vpp that are unknown before testcase run. It does this by dumping interface list to JSON output from all devices using vpp_api_test, and pairing known information from topology (mac address/pci address of interface) to state from VPP. :param node: Node selected from DICT__nodes. :type node: dict """ vat_executor = VatExecutor() vat_executor.execute_script_json_out("dump_interfaces.vat", node) interface_dump_json = vat_executor.get_script_stdout() VatJsonUtil.update_vpp_interface_data_from_json( node, interface_dump_json)
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_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_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 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_idx = 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_idx) if_key = Topology.add_new_port(node, "gre_tunnel") Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) Topology.update_interface_name(node, if_key, name) return name, sw_if_idx else: raise RuntimeError( 'Unable to create GRE tunnel on node {}.'.format(node))
def vpp_ipsec_spd_add_entry(node, spd_id, priority, action, inbound=True, sa_id=None, laddr_range=None, raddr_range=None, proto=None, lport_range=None, rport_range=None): """Create Security Policy Database entry on the VPP node. :param node: VPP node to add SPD entry on. :param spd_id: SPD ID to add entry on. :param priority: SPD entry priority, higher number = higher priority. :param action: Policy action. :param inbound: If True policy is for inbound traffic, otherwise outbound. :param sa_id: SAD entry ID for protect action. :param laddr_range: Policy selector local IPv4 or IPv6 address range in format IP/prefix or IP/mask. If no mask is provided, it's considered to be /32. :param raddr_range: Policy selector remote IPv4 or IPv6 address range in format IP/prefix or IP/mask. If no mask is provided, it's considered to be /32. :param proto: Policy selector next layer protocol number. :param lport_range: Policy selector local TCP/UDP port range in format <port_start>-<port_end>. :param rport_range: Policy selector remote TCP/UDP port range in format <port_start>-<port_end>. :type node: dict :type spd_id: int :type priority: int :type action: PolicyAction :type inbound: bool :type sa_id: int :type laddr_range: string :type raddr_range: string :type proto: int :type lport_range: string :type rport_range: string """ direction = 'inbound' if inbound else 'outbound' act_str = action.value if PolicyAction.PROTECT == action and sa_id is not None: act_str += 'sa_id {0}'.format(sa_id) selector = '' if laddr_range is not None: net = ip_network(unicode(laddr_range), strict=False) selector += 'laddr_start {0} laddr_stop {1} '.format( net.network_address, net.broadcast_address) if raddr_range is not None: net = ip_network(unicode(raddr_range), strict=False) selector += 'raddr_start {0} raddr_stop {1} '.format( net.network_address, net.broadcast_address) if proto is not None: selector += 'protocol {0} '.format(proto) if lport_range is not None: selector += 'lport_start {p[0]} lport_stop {p[1]} '.format( p=lport_range.split('-')) if rport_range is not None: selector += 'rport_start {p[0]} rport_stop {p[1]} '.format( p=rport_range.split('-')) out = VatExecutor.cmd_from_template(node, "ipsec/ipsec_spd_add_entry.vat", spd_id=spd_id, priority=priority, action=act_str, direction=direction, selector=selector) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add entry to SPD {0} failed on {1}'.format( spd_id, node['host']))
def vpp_ipsec_policy_add(node, spd_id, priority, action, inbound=True, sa_id=None, laddr_range=None, raddr_range=None, proto=None, lport_range=None, rport_range=None, is_ipv6=False): """Create Security Policy Database entry on the VPP node. :param node: VPP node to add SPD entry on. :param spd_id: SPD ID to add entry on. :param priority: SPD entry priority, higher number = higher priority. :param action: Policy action. :param inbound: If True policy is for inbound traffic, otherwise outbound. :param sa_id: SAD entry ID for protect action. :param laddr_range: Policy selector local IPv4 or IPv6 address range in format IP/prefix or IP/mask. If no mask is provided, it's considered to be /32. :param raddr_range: Policy selector remote IPv4 or IPv6 address range in format IP/prefix or IP/mask. If no mask is provided, it's considered to be /32. :param proto: Policy selector next layer protocol number. :param lport_range: Policy selector local TCP/UDP port range in format <port_start>-<port_end>. :param rport_range: Policy selector remote TCP/UDP port range in format <port_start>-<port_end>. :param is_ipv6: True in case of IPv6 policy when IPv6 address range is not defined so it will default to address ::/0, otherwise False. :type node: dict :type spd_id: int :type priority: int :type action: PolicyAction :type inbound: bool :type sa_id: int :type laddr_range: string :type raddr_range: string :type proto: int :type lport_range: string :type rport_range: string :type is_ipv6: bool """ direction = 'inbound' if inbound else 'outbound' if laddr_range is None and is_ipv6: laddr_range = '::/0' if raddr_range is None and is_ipv6: raddr_range = '::/0' act_str = action.value if PolicyAction.PROTECT == action and sa_id is not None: act_str += ' sa {0}'.format(sa_id) selector = '' if laddr_range is not None: net = ip_network(unicode(laddr_range), strict=False) selector += 'local-ip-range {0} - {1} '.format( net.network_address, net.broadcast_address) if raddr_range is not None: net = ip_network(unicode(raddr_range), strict=False) selector += 'remote-ip-range {0} - {1} '.format( net.network_address, net.broadcast_address) if proto is not None: selector += 'protocol {0} '.format(proto) if lport_range is not None: selector += 'local-port-range {0} '.format(lport_range) if rport_range is not None: selector += 'remote-port-range {0} '.format(rport_range) out = VatExecutor.cmd_from_template(node, 'ipsec/ipsec_policy_add.vat', json_param=False, spd_id=spd_id, priority=priority, action=act_str, direction=direction, selector=selector) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add IPsec policy ID {0} failed on {1}'.format( spd_id, node['host']))
def policer_set_configuration(self): """Configure policer on VPP node. ...note:: First set all required parameters. """ node = self._node # create policer color_aware = 'color-aware' if self._color_aware else '' # pylint: disable=no-member conform_action = self._conform_action.value if PolicerAction.MARK_AND_TRANSMIT == self._conform_action: conform_action += ' {0}'.format(self._conform_dscp.string) exceed_action = self._exceed_action.value if PolicerAction.MARK_AND_TRANSMIT == self._exceed_action: exceed_action += ' {0}'.format(self._exceed_dscp.string) violate_action = self._violate_action.value if PolicerAction.MARK_AND_TRANSMIT == self._violate_action: violate_action += ' {0}'.format(self._violate_dscp.string) out = VatExecutor.cmd_from_template(node, "policer/policer_add_3c.vat", name=self._policer_name, cir=self._cir, eir=self._eir, cb=self._cb, eb=self._eb, rate_type=self._rate_type.value, round_type=self._round_type.value, p_type=self._policer_type.value, conform_action=conform_action, exceed_action=exceed_action, violate_action=violate_action, color_aware=color_aware) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add policer {0} failed on {1}'.format(self._policer_name, node['host'])) policer_index = out[0].get('policer_index') # create classify table direction = 'src' if self._classify_match_is_src else 'dst' if ip_address(unicode(self._classify_match_ip)).version == 6: ip_version = 'ip6' table_type = PolicerClassifyTableType.IP6_TABLE else: ip_version = 'ip4' table_type = PolicerClassifyTableType.IP4_TABLE out = VatExecutor.cmd_from_template(node, "classify_add_table.vat", ip_version=ip_version, direction=direction) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add classify table failed on {0}'.format(node['host'])) new_table_index = out[0].get('new_table_index') skip_n_vectors = out[0].get('skip_n_vectors') match_n_vectors = out[0].get('match_n_vectors') # create classify session match = 'l3 {0} {1} {2}'.format(ip_version, direction, self._classify_match_ip) out = VatExecutor.cmd_from_template( node, "policer/policer_classify_add_session.vat", policer_index=policer_index, pre_color=self._classify_precolor.value, # pylint: disable=no-member table_index=new_table_index, skip_n=skip_n_vectors, match_n=match_n_vectors, match=match) VatJsonUtil.verify_vat_retval( out[0], err_msg='Add classify session failed on {0}'.format(node['host'])) # set classify interface out = VatExecutor.cmd_from_template( node, "policer/policer_classify_set_interface.vat", sw_if_index=self._sw_if_index, table_type=table_type.value, # pylint: disable=no-member table_index=new_table_index) VatJsonUtil.verify_vat_retval( out[0], err_msg='Set classify interface failed on {0}'.format(node['host']))
def configure_sr_localsid(node, local_sid, behavior, interface=None, next_hop=None, fib_table=None): """Create SRv6 LocalSID and binds it to a particular behaviour on the given node. :param node: Given node to create localSID on. :param local_sid: LocalSID IPv6 address. :param behavior: SRv6 LocalSID function. :param interface: Interface name (Optional, required for L2/L3 xconnects). :param next_hop: Next hop IPv4/IPv6 address (Optional, required for L3 xconnects). :param fib_table: FIB table for IPv4/IPv6 lookup (Optional, required for L3 routing). :type node: dict :type local_sid: str :type behavior: str :type interface: str :type next_hop: int :type fib_table: str :raises ValueError: If unsupported SRv6 LocalSID function used or required parameter is missing. """ if behavior == SRv6Behaviour.END: params = '' elif behavior in [ SRv6Behaviour.END_X, SRv6Behaviour.END_DX4, SRv6Behaviour.END_DX6 ]: if interface is None or next_hop is None: raise ValueError('Required data missing.\ninterface:{0}\n' 'next_hop:{1}'.format(interface, next_hop)) interface_name = Topology.get_interface_name(node, interface) params = '{0} {1}'.format(interface_name, next_hop) elif behavior == SRv6Behaviour.END_DX2: if interface is None: raise ValueError( 'Required data missing.\ninterface:{0}\n'.format( interface)) params = '{0}'.format(interface) elif behavior in [SRv6Behaviour.END_DT4, SRv6Behaviour.END_DT6]: if fib_table is None: raise ValueError( 'Required data missing.\nfib_table:{0}\n'.format( fib_table)) params = '{0}'.format(fib_table) else: raise ValueError( 'Unsupported SRv6 LocalSID function: {0}'.format(behavior)) with VatTerminal(node) as vat: resp = vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_localsid_add.vat', local_sid=local_sid, behavior=behavior, params=params) VatJsonUtil.verify_vat_retval( resp[0], err_msg='Create SRv6 LocalSID {0} failed on node {1}'.format( local_sid, node['host']))