def create_eid(eid, prefix_len): """Create lisp eid object. :param eid: Eid value. :param prefix_len: Prefix len if the eid is IP address. :type eid: str :type prefix_len: int """ eid_addr = dict(prefix=IPUtil.create_prefix_object( ip_address(eid), prefix_len)) if prefix_len else dict(mac=str(eid)) return dict(type=getattr(EidType, u"PREFIX" if prefix_len else u"MAC").value, address=eid_addr)
def _get_sr_steer_policy_args(node, mode, interface=None, ip_addr=None, prefix=None): """Return values of sw_if_index, mask_width, prefix_addr and traffic_type for sr_steering_add_del API. :param node: Given node to create/delete steering policy on. :param mode: Mode of operation - L2 or L3. :param interface: Interface name (Optional, required in case of L2 mode). :param ip_addr: IPv4/IPv6 address (Optional, required in case of L3 mode). :param prefix: IP address prefix (Optional, required in case of L3 mode). :type node: dict :type mode: str :type interface: str :type ip_addr: str :type prefix: int :returns: Values for sw_if_index, prefix and traffic_type :rtype: tuple :raises ValueError: If unsupported mode used or required parameter is missing. """ if mode.lower() == u"l2": if interface is None: raise ValueError(f"Required data missing.\n" f"interface: {interface}") sw_if_index = InterfaceUtil.get_interface_index(node, interface) prefix = 0 traffic_type = getattr(SRv6PolicySteeringTypes, u"SR_STEER_L2").value elif mode.lower() == u"l3": if ip_addr is None or prefix is None: raise ValueError(f"Required data missing.\n" f"IP address:{ip_addr}\n" f"mask:{prefix}") sw_if_index = Constants.BITWISE_NON_ZERO ip_addr = ip_address(ip_addr) prefix = IPUtil.create_prefix_object(ip_addr, int(prefix)) traffic_type = getattr( SRv6PolicySteeringTypes, u"SR_STEER_IPV4").value if ip_addr.version == 4 else getattr( SRv6PolicySteeringTypes, u"SR_STEER_IPV6").value else: raise ValueError(f"Unsupported mode: {mode}") return sw_if_index, prefix, traffic_type
def vpp_all_ra_suppress_link_layer(nodes): """Suppress ICMPv6 router advertisement message for link scope address on all VPP nodes in the topology. :param nodes: Nodes of the test topology. :type nodes: dict """ for node in nodes.values(): if node[u"type"] == NodeType.TG: continue for port_k in node[u"interfaces"].keys(): ip6_addr_list = IPUtil.vpp_get_interface_ip_addresses( node, port_k, u"ipv6") if ip6_addr_list: IPv6Util.vpp_ra_suppress_link_layer(node, port_k)
def vpp_interfaces_ra_suppress_on_all_nodes(nodes): """Disable sending ICMPv6 router-advertisement messages on all IPv6 enabled interfaces on all VPP nodes in the topology. :param nodes: Nodes of the test topology. :type nodes: dict """ for node in nodes.values(): if node[u"type"] == NodeType.TG: continue for port_k in node[u"interfaces"].keys(): ip6_addr_list = IPUtil.vpp_get_interface_ip_addresses( node, port_k, u"ipv6") if ip6_addr_list: IPv6Util.vpp_interface_ra_suppress(node, port_k)
def add_macip_acl_multi_entries(node, rules=u""): """Add a new MACIP ACL. :param node: VPP node to set MACIP ACL on. :param rules: Required MACIP rules. :type node: dict :type rules: str """ reg_ex_ip = re.compile(r"(ip [0-9a-fA-F.:/\d{1,2}]*)") reg_ex_mac = re.compile(r"(mac \S\S:\S\S:\S\S:\S\S:\S\S:\S\S)") reg_ex_mask = re.compile(r"(mask \S\S:\S\S:\S\S:\S\S:\S\S:\S\S)") acl_rules = list() for rule in rules.split(u", "): acl_rule = dict(is_permit=2 if u"permit+reflect" in rule else 1 if u"permit" in rule else 0, src_mac=6 * b'0', src_mac_mask=6 * b'0', prefix=0) groups = re.search(reg_ex_mac, rule) if groups: mac = groups.group(1).split(u" ")[1].replace(u":", u"") acl_rule[u"src_mac"] = bytes.fromhex(mac) groups = re.search(reg_ex_mask, rule) if groups: mask = groups.group(1).split(u" ")[1].replace(u":", u"") acl_rule[u"src_mac_mask"] = bytes.fromhex(mask) groups = re.search(reg_ex_ip, rule) if groups: grp = groups.group(1).split(u" ")[1].split(u"/") acl_rule[u"src_prefix"] = IPUtil.create_prefix_object( ip_address((grp[0])), int(grp[1])) acl_rules.append(acl_rule) Classify._macip_acl_add(node=node, rules=acl_rules)
def vpp_create_vxlan_and_vlan_interfaces( node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start, src_ip_start, dst_ip_start, ip_step): """ Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP node. :param node: VPP node. :param node_vxlan_if: VPP node interface key to create VXLAN tunnel interfaces. :param node_vlan_if: VPP node interface key to create VLAN sub-interface. :param vxlan_count: Number of tunnel interfaces to create. :param vni_start: VNI start ID. :param src_ip_start: VXLAN tunnel source IP address start. :param dst_ip_start: VXLAN tunnel destination IP address start. :param ip_step: IP address incremental step. :type node: dict :type node_vxlan_if: str :type node_vlan_if: str :type vxlan_count: int :type vni_start: int :type src_ip_start: str :type dst_ip_start: str :type ip_step: int :returns: Number of created VXLAN interfaces. :rtype: int """ src_ip_start = ip_address(src_ip_start) dst_ip_start = ip_address(dst_ip_start) if vxlan_count > 10: commands = list() for i in range(0, vxlan_count): try: src_ip = src_ip_start + i * ip_step dst_ip = dst_ip_start + i * ip_step except AddressValueError: logger.warn( u"Can't do more iterations - IP address limit " u"has been reached." ) vxlan_count = i break commands.append( f"sw_interface_add_del_address sw_if_index " f"{Topology.get_interface_sw_index(node, node_vxlan_if)} " f"{src_ip}/{128 if src_ip.version == 6 else 32}\n" ) commands.append( f"vxlan_add_del_tunnel src {src_ip} dst {dst_ip} " f"vni {vni_start + i}\n" ) commands.append( f"create_vlan_subif sw_if_index " f"{Topology.get_interface_sw_index(node, node_vlan_if)} " f"vlan {i + 1}\n" ) VatExecutor().write_and_execute_script( node, u"/tmp/create_vxlan_interfaces.config", commands ) return vxlan_count cmd1 = u"sw_interface_add_del_address" args1 = dict( sw_if_index=InterfaceUtil.get_interface_index(node, node_vxlan_if), is_add=True, del_all=False, prefix=None ) cmd2 = u"vxlan_add_del_tunnel_v3" args2 = dict( is_add=True, instance=Constants.BITWISE_NON_ZERO, src_address=None, dst_address=None, mcast_sw_if_index=Constants.BITWISE_NON_ZERO, encap_vrf_id=0, decap_next_index=Constants.BITWISE_NON_ZERO, vni=None ) cmd3 = u"create_vlan_subif" args3 = dict( sw_if_index=InterfaceUtil.get_interface_index( node, node_vlan_if), vlan_id=None ) with PapiSocketExecutor(node) as papi_exec: for i in range(0, vxlan_count): try: src_ip = src_ip_start + i * ip_step dst_ip = dst_ip_start + i * ip_step except AddressValueError: logger.warn( u"Can't do more iterations - IP address limit " u"has been reached." ) vxlan_count = i break args1[u"prefix"] = IPUtil.create_prefix_object( src_ip, 128 if src_ip_start.version == 6 else 32 ) args2[u"src_address"] = IPAddress.create_ip_address_object( src_ip ) args2[u"dst_address"] = IPAddress.create_ip_address_object( dst_ip ) args2[u"vni"] = int(vni_start) + i args3[u"vlan_id"] = i + 1 history = bool(not 1 < i < vxlan_count - 1) papi_exec.add(cmd1, history=history, **args1).\ add(cmd2, history=history, **args2).\ add(cmd3, history=history, **args3) papi_exec.get_replies() return vxlan_count
def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, ip_step, bd_id_start): """ Configure ARPs and routes for VXLAN interfaces and put each pair of VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain. :param node: VPP node. :param node_vxlan_if: VPP node interface key where VXLAN tunnel interfaces have been created. :param vxlan_count: Number of tunnel interfaces. :param op_node: Opposite VPP node for VXLAN tunnel interfaces. :param op_node_if: Opposite VPP node interface key for VXLAN tunnel interfaces. :param dst_ip_start: VXLAN tunnel destination IP address start. :param ip_step: IP address incremental step. :param bd_id_start: Bridge-domain ID start. :type node: dict :type node_vxlan_if: str :type vxlan_count: int :type op_node: dict :type op_node_if: :type dst_ip_start: str :type ip_step: int :type bd_id_start: int """ dst_ip_start = ip_address(dst_ip_start) if vxlan_count > 1: idx_vxlan_if = Topology.get_interface_sw_index(node, node_vxlan_if) commands = list() for i in range(0, vxlan_count): dst_ip = dst_ip_start + i * ip_step commands.append( f"exec ip neighbor " f"{Topology.get_interface_name(node, node_vxlan_if)} " f"{dst_ip} " f"{Topology.get_interface_mac(op_node, op_node_if)} static " f"\n" ) commands.append( f"ip_route_add_del " f"{dst_ip}/{128 if dst_ip.version == 6 else 32} count 1 " f"via {dst_ip} sw_if_index {idx_vxlan_if}\n" ) sw_idx_vxlan = Topology.get_interface_sw_index( node, f"vxlan_tunnel{i + 1}" ) commands.append( f"sw_interface_set_l2_bridge sw_if_index {sw_idx_vxlan} " f"bd_id {bd_id_start + i} shg 0 enable\n" ) sw_idx_vlan = Topology.get_interface_sw_index( node, f"vlan_subif{i + 1}" ) commands.append( f"sw_interface_set_l2_bridge sw_if_index {sw_idx_vlan} " f"bd_id {bd_id_start + i} shg 0 enable\n" ) VatExecutor().write_and_execute_script( node, u"/tmp/configure_routes_and_bridge_domains.config", commands ) return cmd1 = u"ip_neighbor_add_del" neighbor = dict( sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if), flags=0, mac_address=Topology.get_interface_mac(op_node, op_node_if), ip_address=u"" ) args1 = dict( is_add=1, neighbor=neighbor ) cmd2 = u"ip_route_add_del" kwargs = dict( interface=node_vxlan_if, gateway=str(dst_ip_start) ) route = IPUtil.compose_vpp_route_structure( node, str(dst_ip_start), 128 if dst_ip_start.version == 6 else 32, **kwargs ) args2 = dict( is_add=1, is_multipath=0, route=route ) cmd3 = u"sw_interface_set_l2_bridge" args3 = dict( rx_sw_if_index=None, bd_id=None, shg=0, port_type=0, enable=1 ) args4 = dict( rx_sw_if_index=None, bd_id=None, shg=0, port_type=0, enable=1 ) with PapiSocketExecutor(node) as papi_exec: for i in range(0, vxlan_count): args1[u"neighbor"][u"ip_address"] = \ str(dst_ip_start + i * ip_step) args2[u"route"][u"prefix"][u"address"][u"un"] = \ IPAddress.union_addr(dst_ip_start + i * ip_step) args2[u"route"][u"paths"][0][u"nh"][u"address"] = \ IPAddress.union_addr(dst_ip_start + i * ip_step) args3[u"rx_sw_if_index"] = Topology.get_interface_sw_index( node, f"vxlan_tunnel{i+1}" ) args3[u"bd_id"] = int(bd_id_start+i) args4[u"rx_sw_if_index"] = Topology.get_interface_sw_index( node, f"vlan_subif{i+1}" ) args4[u"bd_id"] = int(bd_id_start+i) history = bool(not 1 < i < vxlan_count - 1) papi_exec.add(cmd1, history=history, **args1). \ add(cmd2, history=history, **args2). \ add(cmd3, history=history, **args3). \ add(cmd3, history=history, **args4) papi_exec.get_replies()
def add_replace_acl_multi_entries(node, acl_idx=None, rules=None, tag=u""): """Add a new ACL or replace the existing one. To replace an existing ACL, pass the ID of this ACL. :param node: VPP node to set ACL on. :param acl_idx: ID of ACL. (Optional) :param rules: Required rules. (Optional) :param tag: ACL tag (Optional). :type node: dict :type acl_idx: int :type rules: str :type tag: str """ reg_ex_src_ip = re.compile(r"(src [0-9a-fA-F.:/\d{1,2}]*)") reg_ex_dst_ip = re.compile(r"(dst [0-9a-fA-F.:/\d{1,2}]*)") reg_ex_sport = re.compile(r"(sport \d{1,5})") reg_ex_dport = re.compile(r"(dport \d{1,5})") reg_ex_proto = re.compile(r"(proto \d{1,5})") acl_rules = list() for rule in rules.split(u", "): acl_rule = dict(is_permit=2 if u"permit+reflect" in rule else 1 if u"permit" in rule else 0, src_prefix=0, dst_prefix=0, proto=0, srcport_or_icmptype_first=0, srcport_or_icmptype_last=65535, dstport_or_icmpcode_first=0, dstport_or_icmpcode_last=65535, tcp_flags_mask=0, tcp_flags_value=0) groups = re.search(reg_ex_src_ip, rule) if groups: grp = groups.group(1).split(u" ")[1].split(u"/") acl_rule[u"src_prefix"] = IPUtil.create_prefix_object( ip_address(grp[0]), int(grp[1])) groups = re.search(reg_ex_dst_ip, rule) if groups: grp = groups.group(1).split(u" ")[1].split(u"/") acl_rule[u"dst_prefix"] = IPUtil.create_prefix_object( ip_address(grp[0]), int(grp[1])) groups = re.search(reg_ex_sport, rule) if groups: port = int(groups.group(1).split(u" ")[1]) acl_rule[u"srcport_or_icmptype_first"] = port acl_rule[u"srcport_or_icmptype_last"] = port groups = re.search(reg_ex_dport, rule) if groups: port = int(groups.group(1).split(u" ")[1]) acl_rule[u"dstport_or_icmpcode_first"] = port acl_rule[u"dstport_or_icmpcode_last"] = port groups = re.search(reg_ex_proto, rule) if groups: proto = int(groups.group(1).split(' ')[1]) acl_rule[u"proto"] = proto acl_rules.append(acl_rule) Classify._acl_add_replace(node, acl_idx=acl_idx, rules=acl_rules, tag=tag)
def initialize_iperf_server(self, node, pf_key, interface, bind, bind_gw, bind_mask, namespace=None, cpu_skip_cnt=0, cpu_cnt=1, instances=1): """iPerf3 initialization. :param node: Topology node running iPerf3 server. :param pf_key: First TG's interface (To compute numa location). :param interface: Name of TG bind interface. :param bind: Bind to host, one of node's addresses. :param bind_gw: Bind gateway (required for default route). :param bind_mask: Bind address mask. :param namespace: Name of TG namespace to execute. :param cpu_skip_cnt: Amount of CPU cores to skip. :param cpu_cnt: iPerf3 main thread count. :param instances: Number of simultaneous iPerf3 instances. :type node: dict :type pf_key: str :type interface: str :type bind: str :type bind_gw: str :type bind_mask: str :type namespace: str :type cpu_skip_cnt: int :type cpu_cnt: int :type instances: int """ if Iperf3.is_iperf_running(node): Iperf3.teardown_iperf(node) if namespace: IPUtil.set_linux_interface_ip(node, interface=interface, ip_addr=bind, prefix=bind_mask, namespace=namespace) IPUtil.set_linux_interface_up(node, interface=interface, namespace=namespace) Namespaces.add_default_route_to_namespace(node, namespace=namespace, default_route=bind_gw) # Compute affinity for iPerf server. self._s_affinity = CpuUtils.get_affinity_iperf( node, pf_key, cpu_skip_cnt=cpu_skip_cnt, cpu_cnt=cpu_cnt * instances) # Compute affinity for iPerf client. self._c_affinity = CpuUtils.get_affinity_iperf( node, pf_key, cpu_skip_cnt=cpu_skip_cnt + cpu_cnt * instances, cpu_cnt=cpu_cnt * instances) for i in range(0, instances): Iperf3.start_iperf_server(node, namespace=namespace, port=5201 + i, affinity=self._s_affinity)
def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, ip_step, bd_id_start): """ Configure ARPs and routes for VXLAN interfaces and put each pair of VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain. :param node: VPP node. :param node_vxlan_if: VPP node interface key where VXLAN tunnel interfaces have been created. :param vxlan_count: Number of tunnel interfaces. :param op_node: Opposite VPP node for VXLAN tunnel interfaces. :param op_node_if: Opposite VPP node interface key for VXLAN tunnel interfaces. :param dst_ip_start: VXLAN tunnel destination IP address start. :param ip_step: IP address incremental step. :param bd_id_start: Bridge-domain ID start. :type node: dict :type node_vxlan_if: str :type vxlan_count: int :type op_node: dict :type op_node_if: :type dst_ip_start: str :type ip_step: int :type bd_id_start: int """ dst_ip_addr_start = ip_address(unicode(dst_ip_start)) if vxlan_count > 1: sw_idx_vxlan = Topology.get_interface_sw_index(node, node_vxlan_if) tmp_fn = '/tmp/configure_routes_and_bridge_domains.config' commands = list() for i in xrange(0, vxlan_count): dst_ip = dst_ip_addr_start + i * ip_step commands.append( 'ip_neighbor_add_del sw_if_index {sw_idx} dst {ip} ' 'mac {mac}\n'.format(sw_idx=sw_idx_vxlan, ip=dst_ip, mac=Topology.get_interface_mac( op_node, op_node_if))) commands.append( 'ip_route_add_del {ip}/{ip_len} count 1 via {ip} ' 'sw_if_index {sw_idx}\n'.format( ip=dst_ip, ip_len=128 if dst_ip.version == 6 else 32, sw_idx=sw_idx_vxlan)) commands.append( 'sw_interface_set_l2_bridge sw_if_index {sw_idx} ' 'bd_id {bd_id} shg 0 enable\n'.format( sw_idx=Topology.get_interface_sw_index( node, 'vxlan_tunnel{nr}'.format(nr=i + 1)), bd_id=bd_id_start + i)) commands.append( 'sw_interface_set_l2_bridge sw_if_index {sw_idx} ' 'bd_id {bd_id} shg 0 enable\n'.format( sw_idx=Topology.get_interface_sw_index( node, 'vlan_subif{nr}'.format(nr=i + 1)), bd_id=bd_id_start + i)) VatExecutor().write_and_execute_script(node, tmp_fn, commands) return cmd1 = 'ip_neighbor_add_del' neighbor = dict( sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if), flags=0, mac_address=Topology.get_interface_mac(op_node, op_node_if), ip_address='') args1 = dict(is_add=1, neighbor=neighbor) cmd2 = 'ip_route_add_del' kwargs = dict(interface=node_vxlan_if, gateway=str(dst_ip_addr_start)) route = IPUtil.compose_vpp_route_structure( node, str(dst_ip_addr_start), 128 if dst_ip_addr_start.version == 6 else 32, **kwargs) args2 = dict(is_add=1, is_multipath=0, route=route) cmd3 = 'sw_interface_set_l2_bridge' args3 = dict(rx_sw_if_index=None, bd_id=None, shg=0, port_type=0, enable=1) args4 = dict(rx_sw_if_index=None, bd_id=None, shg=0, port_type=0, enable=1) err_msg = 'Failed to put VXLAN and VLAN interfaces to bridge domain ' \ 'on host {host}'.format(host=node['host']) with PapiExecutor(node) as papi_exec: for i in xrange(0, vxlan_count): dst_ip = dst_ip_addr_start + i * ip_step args1['neighbor']['ip_address'] = str(dst_ip) args2['route']['prefix']['address']['un'] = \ IPUtil.union_addr(dst_ip) args2['route']['paths'][0]['nh']['address'] = \ IPUtil.union_addr(dst_ip) args3['rx_sw_if_index'] = Topology.get_interface_sw_index( node, 'vxlan_tunnel{nr}'.format(nr=i + 1)) args3['bd_id'] = int(bd_id_start + i) args4['rx_sw_if_index'] = Topology.get_interface_sw_index( node, 'vlan_subif{nr}'.format(nr=i + 1)) args4['bd_id'] = int(bd_id_start + i) history = False if 1 < i < vxlan_count else True papi_exec.add(cmd1, history=history, **args1). \ add(cmd2, history=history, **args2). \ add(cmd3, history=history, **args3). \ add(cmd3, history=history, **args4) if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 4) == 0: papi_exec.get_replies(err_msg) papi_exec.get_replies()