def setUp(self): b = BPF(arg1, arg2, debug=0) fn = b.load_func("on_packet", BPF.SCHED_CLS) ip = IPRoute() ifindex = ip.link_lookup(ifname="eth0")[0] # set up a network to change the flow: # outside | inside # 172.16.1.1 - 172.16.1.2 | 192.168.1.1 - 192.16.1.2 ip.addr("del", index=ifindex, address="172.16.1.2", mask=24) ip.addr("add", index=ifindex, address="192.168.1.2", mask=24) # add an ingress and egress qdisc ip.tc("add", "ingress", ifindex, "ffff:") ip.tc("add", "sfq", ifindex, "1:") # add same program to both ingress/egress, so pkt is translated in both directions ip.tc("add-filter", "bpf", ifindex, ":1", fd=fn.fd, name=fn.name, parent="ffff:", action="ok", classid=1) ip.tc("add-filter", "bpf", ifindex, ":2", fd=fn.fd, name=fn.name, parent="1:", action="ok", classid=1) self.xlate = b.get_table("xlate")
def set_net(lease): ipr = IPRoute() try: index = ipr.link_lookup(ifname=lease.interface)[0] except IndexError as e: logger.error('Interface %s not found, can not set IP.', lease.interface) try: ipr.addr('add', index, address=lease.address, mask=int(lease.subnet_mask_cidr)) except NetlinkError as e: if ipr.get_addr(index=index)[0].\ get_attrs('IFA_ADDRESS')[0] == lease.address: logger.debug('Interface %s is already set to IP %s' % (lease.interface, lease.address)) else: logger.error(e) else: logger.debug('Interface %s set to IP %s' % (lease.interface, lease.address)) try: ipr.route('add', dst='0.0.0.0', gateway=lease.router, oif=index) except NetlinkError as e: if ipr.get_routes(table=254)[0].\ get_attrs('RTA_GATEWAY')[0] == lease.router: logger.debug('Default gateway is already set to %s' % (lease.router)) else: logger.error(e) else: logger.debug('Default gateway set to %s', lease.router) ipr.close() set_dns(lease)
def del_addr(self, ip): iproute= IPRoute() br = iproute.link_lookup(ifname=BRIDGE_INTERFACE_NAME)[0] if not self.check_exists(ip, iproute, br): iproute.addr('delete', br, address=ip, mask=30) iproute.close() iproute = None
def set_loopback(): ip = IPRoute() idx = ip.link_lookup(ifname="lo")[0] ip.addr( "add", index=idx, address="127.0.0.1", broadcast="127.0.0.255", prefixlen=24 ) ip.close()
def create_tuntap(self, name, address, mtu, channel): self.tap = tuntap.Tun(name=name) self.tap.open() #channel.on("message")(self.tap.fd.write) @channel.on("message") def on_message(message): self.tap.fd.write(message) def tun_reader(): data = self.tap.fd.read(self.tap.mtu) channel_state = self.channel.transport.transport.state if data and channel_state == "connected": channel.send(data) loop = asyncio.get_event_loop() loop.add_reader(self.tap.fd, tun_reader) self.tap.up() ip = IPRoute() index = ip.link_lookup(ifname=name)[0] ip.addr('add', index=index, address=address, mask=24) ip.link("set", index=index, mtu=mtu)
def set_net(self): from pyroute2 import IPRoute from pyroute2.netlink import NetlinkError ipr = IPRoute() # FIXME: bring iface up if down? index = ipr.link_lookup(ifname=self.iface)[0] try: ipr.addr('add', index, address=self.client_ip, mask=self.subnet_mask_cidr) except NetlinkError as e: # FIXME: add other errors if ipr.get_addr(index=index)[0].\ get_attrs('IFA_ADDRESS')[0] == self.client_ip: logger.debug('Interface %s is already set to IP %s' % (self.iface, self.client_ip)) else: logger.error(e) else: logger.debug('Interface %s set to IP %s' % (self.iface, self.client_ip)) try: ipr.route('add', dst='0.0.0.0', gateway=self.router, oif=index) except NetlinkError as e: # FIXME: add other errors if ipr.get_routes(table=254)[0].\ get_attrs('RTA_GATEWAY')[0] == self.router: logger.debug('Default gateway is already set to %s' % (self.router)) else: logger.error(e) else: logger.debug('Default gateway set to %s', self.router) ipr.close()
def set_addr(dev: str, addr: str) -> None: """Associate address with TUN device.""" ip = IPRoute() idx = ip.link_lookup(ifname=dev)[0] ip.addr('add', index=idx, address=addr, prefixlen=24) ip.link('set', index=idx, state='up') ip.close()
def _create_endpoint(self, request, response): logger.debug('endpoint.create') network_id = request['NetworkID'] # if no CreateNetwork request received namespace = 'sdns' + network_id[:6] if namespace not in netns.listnetns(): self._create_namespace(namespace) endpoint_id = request['EndpointID'] address = request['Interface']['Address'] ip = IPRoute() veth0_name = 'veth%s0' % endpoint_id[:6] veth1_name = 'veth%s1' % endpoint_id[:6] ip.link('add', ifname=veth0_name, kind='veth', peer=veth1_name) veth0 = ip.link_lookup(ifname=veth0_name)[0] veth1 = ip.link_lookup(ifname=veth1_name)[0] ip.link('set', index=veth0, mtu=1450) ip.link('set', index=veth1, mtu=1450) ip_addr, mask = address.split('/') ip.addr('add', index=veth1, address=ip_addr, mask=int(mask)) ip.link('set', index=veth0, net_ns_fd=namespace) ns = NetNS(namespace) ns.link('set', index=veth0, state='up') bridge = ns.link_lookup(ifname='shoutbr0')[0] ns.link('set', index=veth0, master=bridge) ip.close() ns.close() return {'Interface': {}}
def clean_prepare(ifname): ''' clean `monitor_prepare` configurations ''' ip = IPRoute() idx = ip.link_lookup(ifname=ifname)[0] try: ip.rule('del', table=TUN_TABLE, priority=100, action='FR_ACT_TO_TBL') except: pass try: ip.rule('del', table=MAIN_TABLE, priority=10, iifname=TUN_IFNAME, action='FR_ACT_TO_TBL') except: pass try: ip.route('del', dst="0.0.0.0", mask=0, gateway=TUN_ADDRESS, table=TUN_TABLE) except: pass try: ip.addr('del', index=idx, address=TUN_ADDRESS, mask=TUN_ADDRESS_MASK) except: pass
def monitor_prepare(ifname): ''' 1. setup tun device <ifname> 2. assign IPv4 address to tun device <ifname> 3. add route rules 3. configure linux kernel to receive IP packet from local device <ifname> like command: $sudo ip link set tun0 up $sudo ip addr add 172.32.0.1/24 dev tun0 $sudo ip route add default via 172.32.0.1 dev tun0 table 100 $sudo ip rule add from all pref 100 lookup 100 $sudo ip rule add from all iif tun0 pref 10 lookup main $sudo sysctl -w net.ipv4.conf.tun0.accept_local=1 ''' ip = IPRoute() idx = ip.link_lookup(ifname=ifname)[0] ip.link('set', index=idx, state='up') ip.addr('add', index=idx, address=TUN_ADDRESS, mask=TUN_ADDRESS_MASK) ip.route('add', dst="0.0.0.0", mask=0, gateway=TUN_ADDRESS, table=TUN_TABLE) ip.rule('add', table=MAIN_TABLE, priority=10, iifname=TUN_IFNAME, action='FR_ACT_TO_TBL') ip.rule('add', table=TUN_TABLE, priority=100, action='FR_ACT_TO_TBL') os.system("sysctl -w net.ipv4.conf.{}.accept_local=1".format(TUN_IFNAME))
def connect_to_br(self): index = 0 with docker_netns(self.name) as pid: for quagga_config in self.quagga_config: ip = IPRoute() br = ip.link_lookup(ifname=quagga_config['bridge']) if len(br) == 0: ip.link_create(ifname=quagga_config['bridge'], kind='bridge') br = ip.link_lookup(ifname=quagga_config['bridge']) br = br[0] ip.link('set', index=br, state='up') ifname = '{0}-{1}'.format(self.name, index) ifs = ip.link_lookup(ifname=ifname) if len(ifs) > 0: ip.link_remove(ifs[0]) peer_ifname = '{0}-{1}'.format(pid, index) ip.link_create(ifname=ifname, kind='veth', peer=peer_ifname) host = ip.link_lookup(ifname=ifname)[0] ip.link('set', index=host, master=br) ip.link('set', index=host, state='up') guest = ip.link_lookup(ifname=peer_ifname)[0] ip.link('set', index=guest, net_ns_fd=pid) with Namespace(pid, 'net'): ip = IPRoute() ip.link('set', index=guest, ifname='eth{}'.format(index+1)) ip.addr('add', index=guest, address=quagga_config['ip'], mask=quagga_config['mask']) ip.link('set', index=guest, state='up') index += 1
def set_container_veth(): ip = IPRoute() idx = ip.link_lookup(ifname="v0p1")[0] ip.link("set", index=idx, state="up") ip.addr("add", index=idx, address="10.0.0.2", broadcast="10.0.0.255", prefixlen=24) ip.route( "add", dst="default", gateway="10.0.0.1", metrics={"mtu": 1400, "hoplimit": 16} ) ip.close()
def add_addr(client_ip): ip = IPRoute() idx = ip.link_lookup(ifname=config.IFNAME)[0] address, prefixlen = client_ip.split('/') prefixlen = int(prefixlen) ip.flush_addr(index=idx) ip.addr('add', index=idx, address=address, prefixlen=prefixlen)
def apply_configuration(self, oneshot=False): if self.managed == False: raise ValueError( "Can't apply configuration on unmanaged interface") netlink = IPRoute() index = netlink.link_lookup(ifname=self.current_name)[0] if self.current_name != self.name: self.logger.info("Renaming %s to %s", self.current_name, self.name) # Interface must be brought down to rename it netlink.link('set', index=index, state='down') netlink.link('set', index=index, ifname=self.name) netlink.link('set', index=index, state='up') # Bring up the interface if we're not a monitor port if self.method == InterfaceConfigurationMethods.DHCP: dhcpcd_cmdline = ['dhcpcd', '-w', '-D', '--inactive'] # If we're a oneshot, invoke dhcpcd as a oneshot if oneshot is True: dhcpcd_cmdline += ['-1'] # Add the interface name dhcpcd_cmdline += [self.name] self.logger.info("Configuring DHCP on %s", self.name) dhcpcd_process = subprocess.run(args=dhcpcd_cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) # This should rarely if ever happen. If we don't have a DHCP server handy, we'll # end up with a link local access and the client should return. This will only # happen if IPv4LL fails if dhcpcd_process.returncode != 0: self.logger.error("failed to recieve an IP address!") return False return True if self.method == InterfaceConfigurationMethods.STATIC: if len(self.static_addrs) == 0: raise ValueError("Static configuration, but no addresses set!") for address in self.static_addrs: netlink.addr('add', index=index, address=address.ip_addr.compressed, prefixlen=int(address.prefixlen)) netlink.close() # Refresh ourselves self.refresh()
class LoopBackAddress(object): def __init__(self, logger, config): self.config = config self._label = self.config.get("balancer.agent.plugins.loopback", "label") self._prefix = self.config.getint("balancer.agent.plugins.loopback", "prefix") self._ip = IPRoute() self._idx = self._ip.link_lookup(ifname="lo")[0] self.logger = logger @property def configured_ips(self): ips = set() for link in self._ip.get_addr(index=self._idx): if not "attrs" in link: continue interface = None ip = None for key, value in link["attrs"]: if key == "IFA_ADDRESS": ip = value elif key == "IFA_LABEL": interface = value elif interface == self._label and ip not in ["127.0.0.1", None]: ips.add(ip) return ips def close(self): if self._ip: self._ip.close() def __disable__(self, ip): self.logger("Disabling {}/{} on {}".format(ip, self._prefix, self._label)) self._ip.addr("del", index=self._idx, address=ip, prefixlen=self._prefix, label=self._label) def __enable__(self, ip): self.logger("Enabling {}/{} on {}".format(ip, self._prefix, self._label)) self._ip.addr("add", index=self._idx, address=ip, prefixlen=self._prefix, label=self._label) def apply(self, frontends): configured_ips = self.configured_ips ips = set() for frontend, ips_and_ports in frontends.items(): for ip, port in ips_and_ports: ips.add(ip) to_disabled = configured_ips.difference(ips) to_enabled = ips.difference(configured_ips) for ip in to_disabled: self.__disable__(ip) for ip in to_enabled: self.__enable__(ip)
def set_host_veth(container_id): # create VETH pair and move v0p1 to netns 'test' ip = IPRoute() idx = ip.link_lookup(ifname="v0p0") if idx: ip.link("del", ifname="v0p0") ip.link("add", ifname="v0p0", peer="v0p1", kind="veth") idx = ip.link_lookup(ifname="v0p0")[0] ip.link("set", index=idx, state="up") ip.addr("add", index=idx, address="10.0.0.1", broadcast="10.0.0.255", prefixlen=24) idx = ip.link_lookup(ifname="v0p1")[0] ip.link("set", index=idx, net_ns_fd=container_id) ip.close()
def connect(self): """ Connect ASA to neighbors, using pyroute """ ipr = IPRoute() self.logger.info("Connecting ASA vm to external veth interfaces") # Create inside bridge ipr.link('add', ifname=self.bridge_inside, kind='bridge') # Lookup the index dev_br_inside = ipr.link_lookup(ifname=self.bridge_inside)[0] # Bring it down ipr.link('set', index=dev_br_inside, state='down') # Create outside bridge ipr.link('add', ifname=self.bridge_outside, kind='bridge') # Lookup the index dev_br_outside = ipr.link_lookup(ifname=self.bridge_outside)[0] # Bring it down ipr.link('set', index=dev_br_outside, state='down') # Add inside tap and inside veth to bridge dev_tap_inside = ipr.link_lookup(ifname=self.tap_inside)[0] ipr.link('set', index=dev_tap_inside, master=dev_br_inside) dev_veth_inside = ipr.link_lookup(ifname=self.veth_inside)[0] ipr.flush_addr(index=dev_veth_inside) ipr.link('set', index=dev_veth_inside, master=dev_br_inside) # Add outside tap and outside veth to outside bridge dev_tap_outside = ipr.link_lookup(ifname=self.tap_outside)[0] ipr.link('set', index=dev_tap_outside, master=dev_br_outside) dev_veth_outside = ipr.link_lookup(ifname=self.veth_outside)[0] ipr.flush_addr(index=dev_veth_outside) ipr.link('set', index=dev_veth_outside, master=dev_br_outside) # Bring interfaces up ipr.link('set', index=dev_br_inside, state='up') ipr.link('set', index=dev_br_outside, state='up') ipr.link('set', index=dev_tap_inside, state='up') ipr.link('set', index=dev_tap_outside, state='up') ipr.link('set', index=dev_veth_inside, state='up') ipr.link('set', index=dev_veth_outside, state='up') dev_tap_mgmt = ipr.link_lookup(ifname=self.tap_mgmt)[0] ipr.link('set', index=dev_tap_mgmt, state='up') ipr.addr('add', index=dev_tap_mgmt, address='10.69.0.2', mask=24, broadcast='10.69.0.255')
def setup_veth_container_end(self, ifname): """Setup the VETH in a container. Parameters ---------- ifname : str The interface name within the container. """ ipr = IPRoute() logger.debug('Bind veth %s to %s at %s', self.veth_name, ifname, self.address) index = ipr.link_lookup(ifname=ifname)[0] ipr.addr('add', index=index, address=str(self.address.ip), mask=self.address.network.prefixlen) ipr.link('set', index=index, state='up')
def initContainerNetwork(self): ip = IPRoute() try: addr = self['internal_ip'].split('/')[0] mask = int(self['internal_ip'].split('/')[1]) except KeyError as e: print("OpenvSwitch: CYGNET_INTERNAL_IP environment variable not found") raise e ip.addr('add', index=(ip.link_lookup(ifname='br2')), address=addr, mask=mask) run("ifconfig br2 up") self.interfaces.append(('br2', (self.addr, str(mask)))) return addr
def address_exists(netns=None, **kwarg): ret = 0 ipr = None if netns is None: ipr = IPRoute() else: ipr = NetNS(netns) if 'match' in kwarg: nkw = kwarg['match'] else: nkw = dict(kwarg) for key in ('address', 'local'): if key in nkw: nkw[key] = nkw[key].split('/')[0] if 'ifname' in kwarg: links = list(ipr.link_lookup(ifname=kwarg['ifname'])) if links: nkw['index'] = links[0] nkw.pop('ifname') else: ipr.close() return 0 ret = list(ipr.addr('dump', match=nkw)) ipr.close() return len(ret) == 1
def configure_link(self, ip4_address, plen, gateway): ''' Configure following attributes for interface inside the container - Link-up - IP Address - Default gateway ''' @staticmethod def _intf_error(e, ifname, message): raise Error( CNI_ERROR_CONFIG_NS_INTF, message + ifname + ' code ' + str(e.code) + ' message ' + e.message) return with CniNamespace(self.cni.container_netns): iproute = IPRoute() intf = iproute.link_lookup(ifname=self.cni.container_ifname) if len(intf) == 0: raise Error( CNI_ERROR_CONFIG_NS_INTF, 'Error finding interface ' + self.cni.container_ifname + ' inside container') idx_ns = intf[0] try: iproute.link('set', index=idx_ns, state='up') except NetlinkError as e: _intf_error( e, self.cni.container_ifname, 'Error setting link state for interface ' + 'inside container') try: iproute.addr('add', index=idx_ns, address=ip4_address, prefixlen=plen) except NetlinkError as e: if e.code != errno.EEXIST: _intf_error( e, self.cni.container_ifname, 'Error setting ip-address for interface ' + 'inside container') try: iproute.route('add', dst='0.0.0.0/0', gateway=gateway) except NetlinkError as e: if e.code != errno.EEXIST: _intf_error(e, self.cni.container_ifname, 'Error adding default route inside container') return
def initContainerNetwork(self): ip = IPRoute() try: addr = self['internal_ip'].split('/')[0] mask = int(self['internal_ip'].split('/')[1]) except KeyError as e: print( "OpenvSwitch: CYGNET_INTERNAL_IP environment variable not found" ) raise e ip.addr('add', index=(ip.link_lookup(ifname='br2')), address=addr, mask=mask) run("ifconfig br2 up") self.interfaces.append(('br2', (self.addr, str(mask)))) return addr
def _prepare_linux_enviroment(self): ip = IPRoute() exist = ip.link_lookup(ifname='vpp1') if exist: return ip.link('add', ifname='vpp1', peer='virtual1', kind='veth') ip.link('add', ifname='vpp2', peer='virtual2', kind='veth') vpp1 = ip.link_lookup(ifname='virtual1')[0] vpp2 = ip.link_lookup(ifname='virtual2')[0] ip.link('set', index=vpp1, state='up') ip.link('set', index=vpp2, state='up') ip.addr('add', index=vpp1, address='192.168.0.2', prefixlen=24) ip.addr('add', index=vpp2, address='192.168.1.2', prefixlen=24)
def set_local_ip_address(wlan, ip_address): """The high-level method to set static local ip address. Args: wlan (str): wi-fi interface that will be used to connect to external network ip_address (str): Static ip address of this machine the network """ from pyroute2 import IPRoute, NetlinkError ip = IPRoute() index = ip.link_lookup(ifname=wlan)[0] try: ip.addr('add', index, address=ip_address, mask=24) except NetlinkError as e: print(e) ip.close()
def configure_link(self, ip4_address, plen, gateway): ''' Configure following attributes for interface inside the container - Link-up - IP Address - Default gateway ''' @staticmethod def _intf_error(e, ifname, message): raise Error(CNI_ERROR_CONFIG_NS_INTF, message + ifname + ' code ' + str(e.code) + ' message ' + e.message) return with CniNamespace(self.cni.container_netns): iproute = IPRoute() intf = iproute.link_lookup(ifname=self.cni.container_ifname) if len(intf) == 0: raise Error(CNI_ERROR_CONFIG_NS_INTF, 'Error finding interface ' + self.cni.container_ifname + ' inside container') idx_ns = intf[0] try: iproute.link('set', index=idx_ns, state='up') except NetlinkError as e: _intf_error(e, self.cni.container_ifname, 'Error setting link state for interface ' + 'inside container') try: iproute.addr('add', index=idx_ns, address=ip4_address, prefixlen=plen) except NetlinkError as e: if e.code != errno.EEXIST: _intf_error(e, self.cni.container_ifname, 'Error setting ip-address for interface ' + 'inside container') try: iproute.route('add', dst='0.0.0.0/0', gateway=gateway) except NetlinkError as e: if e.code != errno.EEXIST: _intf_error(e, self.cni.container_ifname, 'Error adding default route inside container') return
def handle_dhcp(packet): global dhcpserverip global offeredip global sub_mask global router_id for check in packet[DHCP].options: if check[0] == "message-type": if check[1] == 2: print("[+] DHCP Offer received") dhcpserverip = packet[IP].src offeredip = packet[BOOTP].yiaddr for options_attrib in packet[DHCP].options: if options_attrib[0] == "subnet_mask": sub_mask = options_attrib[1] if options_attrib[0] == "router": router_id = options_attrib[1] print("[+] DHCP Server IP:", dhcpserverip) print("[+] Offered IP:", offeredip) print("[+] Subnet mask:", sub_mask) print("[+] Gateway:", router_id) if check[1] == 5: print("[+] DHCP ACK received, IP allocation done") ip = IPRoute() index = ip.link_lookup(ifname='eth0')[0] # Need to figure out how to assign broadcast address- not part of DHCP reponse # Interface is assigned proper IP address mask_short = IPv4Network((0, sub_mask)) mask_short = mask_short.prefixlen max_short = 24 print("Mask=", mask_short) ip.addr('add', index, address=offeredip, mask=mask_short) ip.close()
def setUp(self): b = BPF(arg1, arg2, debug=0) fn = b.load_func("on_packet", BPF.SCHED_ACT) ip = IPRoute() ifindex = ip.link_lookup(ifname="eth0")[0] # set up a network to change the flow: # outside | inside # 172.16.1.1 - 172.16.1.2 | 192.168.1.1 - 192.16.1.2 ip.addr("del", index=ifindex, address="172.16.1.2", mask=24) ip.addr("add", index=ifindex, address="192.168.1.2", mask=24) # add an ingress and egress qdisc ip.tc("add", "ingress", ifindex, "ffff:") ip.tc("add", "sfq", ifindex, "1:") # add same program to both ingress/egress, so pkt is translated in both directions action = {"kind": "bpf", "fd": fn.fd, "name": fn.name, "action": "ok"} ip.tc("add-filter", "u32", ifindex, ":1", parent="ffff:", action=[action], protocol=protocols.ETH_P_ALL, classid=1, target=0x10002, keys=['0x0/0x0+0']) ip.tc("add-filter", "u32", ifindex, ":2", parent="1:", action=[action], protocol=protocols.ETH_P_ALL, classid=1, target=0x10002, keys=['0x0/0x0+0']) self.xlate = b.get_table("xlate")
def addif(self, ctn, ifname='', mac=''): with docker_netns(ctn.name) as pid: host_ifname = '{0}_{1}'.format(self.name, ctn.name) guest_ifname = random_str(5) ip = IPRoute() ip.link('add', ifname=host_ifname, kind='veth', peer=guest_ifname) host = ip.link_lookup(ifname=host_ifname)[0] ip.link('set', index=host, master=self.br) ip.link('set', index=host, state='up') self.ctns.append(ctn) guest = ip.link_lookup(ifname=guest_ifname)[0] ip.link('set', index=guest, net_ns_fd=pid) with Namespace(pid, 'net'): ip = IPRoute() if ifname == '': links = [x.get_attr('IFLA_IFNAME') for x in ip.get_links()] n = [ int(l[len('eth'):]) for l in links if l.startswith('eth') ] idx = 0 if len(n) > 0: idx = max(n) + 1 ifname = 'eth{0}'.format(idx) ip.link('set', index=guest, ifname=ifname) ip.link('set', index=guest, state='up') if mac != '': ip.link('set', index=guest, address=mac) if self.with_ip: address, mask = self.next_ip_address().split('/') ip.addr('add', index=guest, address=address, mask=int(mask)) ctn.ip_addrs.append((ifname, address, self.name)) return ifname
def configure_veth(self, mac, ip4, plen, gw): ''' Configure the interface inside container with, - Mac-address - IP Address - Default gateway - Link-up ''' ip = IPRoute() idx = ip.link_lookup(ifname=self.host_ifname)[0] ip.link('set', index=idx, state='up') with CniNamespace(self.container_netns, logger): ip_ns = IPRoute() idx_ns = ip_ns.link_lookup(ifname=self.container_ifname)[0] try: ip_ns.link('set', index=idx_ns, state='up') except NetlinkError as e: self.veth_error(e, self.container_ifname, 'Error setting link state for veth device') try: ip_ns.link('set', index=idx_ns, address=mac) except NetlinkError as e: self.veth_error(e, self.container_ifname, 'Error setting mac-address for veth device') try: ip_ns.addr('add', index=idx_ns, address=ip4, prefixlen=plen) except NetlinkError as e: if e.code != errno.EEXIST: self.veth_error(e, self.container_ifname, 'Error setting ip-address for veth device') try: ip_ns.route('add', dst='0.0.0.0/0', gateway=gw) except NetlinkError as e: if e.code != errno.EEXIST: self.veth_error(e, self.container_ifname, 'Error adding default route in container') return
def configure_veth(self, mac, ip4, plen, gw): ''' Configure the interface inside container with, - Mac-address - IP Address - Default gateway - Link-up ''' ip = IPRoute() idx = ip.link_lookup(ifname=self.host_ifname)[0] ip.link('set', index=idx, state='up') with Namespace(self.container_pid, 'net'): ip_ns = IPRoute() idx_ns = ip_ns.link_lookup(ifname=self.container_ifname)[0] try: ip_ns.link('set', index=idx_ns, state='up') except NetlinkError as e: self.veth_error(e, self.container_ifname, 'Error setting link state for veth device') try: ip_ns.link('set', index=idx_ns, address=mac) except NetlinkError as e: self.veth_error(e, self.container_ifname, 'Error setting mac-address for veth device') try: ip_ns.addr('add', index=idx_ns, address=ip4, prefixlen=plen) except NetlinkError as e: if e.code != errno.EEXIST: self.veth_error(e, self.container_ifname, 'Error setting ip-address for veth device') try: ip_ns.route('add', dst='0.0.0.0/0', gateway=gw) except NetlinkError as e: if e.code != errno.EEXIST: self.veth_error(e, self.container_ifname, 'Error adding default route in container') return
def config_ipaddr(ifname, config): logger.debug("[%s] ifconfig: %s" % (ifname, config)) ipr = IPRoute() index = _find_device_index(ifname, ipr) ipaddr = config["ipaddr"] mask = config["mask"] route = config.get("route") ns = config.get("ns") logger.debug("[%s] Add ip %s/%s" % (ifname, ipaddr, mask)) ipr.addr('add', index=index, address=ipaddr, mask=mask) _clean_route() if route: logger.debug("Add gateway %s" % (route)) ipr.route('add', gateway=route) if ns: config_nameserver(ns)
def __init__(self, name, subnet='', with_ip=True): ip = IPRoute() br = ip.link_lookup(ifname=name) if len(br) != 0: ip.link('del', index=br[0]) ip.link('add', ifname=name, kind='bridge') br = ip.link_lookup(ifname=name) br = br[0] ip.link( 'set', index=br, IFLA_AF_SPEC={ 'attrs': [['AF_INET6', { 'attrs': [['IFLA_INET6_ADDR_GEN_MODE', 1]] }]] }) ip.link('set', index=br, state='up') if with_ip: self.subnet = netaddr.IPNetwork(subnet) def f(): for host in self.subnet: yield host self._ip_generator = f() # throw away first network address self.next_ip_address() self.ip_addr = self.next_ip_address() address, prefixlen = self.ip_addr.split('/') ip.addr('add', index=br, address=address, prefixlen=int(prefixlen)) self.name = name self.with_ip = with_ip self.br = br self.ctns = []
def set_parameter_higher_layer(self, **kwargs): """ Set the parameter on higher layers of protocol stack (higher MAC and above) Args: param_key_value: key and value of this parameter iface : interface name (required) e.g. "wlan0" (str) ip_addres : interface ip adress e.g. "10.0.0.1" (str) netmask : interface network mask e.g. 24 (int) """ if "iface" in kwargs: iface = kwargs["iface"] else: return False ipr = IPRoute() idx = ip.link_lookup(ifname=iface)[0] netmask=None if "netmask" in kwargs: netmask=kwargs["netmask"] if "ip_address" in kwargs: ip_address=kwargs["ip_address"] ipr.addr('add', index=idx, address=ip_address, netmask=netmask) return True
def get_links_ip_addrs(self, ipr: IPRoute) -> Mapping[int, Sequence[str]]: ret = {} addresses = ipr.addr('dump') for addrinfo in addresses: index = addrinfo['index'] if index not in ret: ret[index] = [] addr = addrinfo.get_attr('IFA_ADDRESS') prefixlen = addrinfo['prefixlen'] scope = addrinfo['scope'] family = "inet4" if addrinfo['family'] == 2 else "inet6" addr_out = "{}/{}".format(addr, prefixlen) if scope in SCOPE_MAP and (family == "inet6" or SCOPE_MAP[scope] != "global"): addr_out = "{} ({})".format(addr_out, SCOPE_MAP[scope]) ret[index].append(addr_out) return ret
class TestIPRoute(object): def setup(self): self.ip = IPRoute() try: self.ifaces = [] self.dev, idx = self.create() except IndexError: pass def create(self, kind='dummy'): name = uifname() create_link(name, kind=kind) idx = self.ip.link_lookup(ifname=name)[0] self.ifaces.append(idx) return (name, idx) def teardown(self): if hasattr(self, 'ifaces'): for dev in self.ifaces: try: self.ip.link('delete', index=dev) except: pass self.ip.close() def _test_nla_operators(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == self.ifaces[0]] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == self.dev assert intersection['prefixlen'] == 24 assert intersection['index'] == self.ifaces[0] def test_addr_add(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def test_vlan_filter_dump(self): require_user('root') (an, ax) = self.create('bridge') (bn, bx) = self.create('bridge') self.ip.link('set', index=ax, state='up') self.ip.link('set', index=bx, state='up') assert len(self.ip.get_vlans()) >= 2 for name in (an, bn): assert len(self.ip.get_vlans(ifname=name)) == 1 assert (self.ip.get_vlans( ifname=name)[0].get_attr('IFLA_IFNAME')) == name assert (self.ip.get_vlans(ifname=name)[0].get_nested( 'IFLA_AF_SPEC', 'IFLA_BRIDGE_VLAN_INFO'))['vid'] == 1 def test_vlan_filter_add(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern='567') self.ip.vlan_filter('add', index=sx, vlan_info={'vid': 567}) assert grep('bridge vlan show', pattern='567') self.ip.vlan_filter('del', index=sx, vlan_info={'vid': 567}) assert not grep('bridge vlan show', pattern='567') def test_vlan_filter_add_raw(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern='567') self.ip.vlan_filter( 'add', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', { 'vid': 567 }]]}) assert grep('bridge vlan show', pattern='567') self.ip.vlan_filter( 'del', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', { 'vid': 567 }]]}) assert not grep('bridge vlan show', pattern='567') def test_brport_basic(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) self.ip.link('set', index=sx, state='up') self.ip.link('set', index=bx, state='up') self.ip.brport('set', index=sx, unicast_flood=0, cost=200, proxyarp=1) port = self.ip.brport('show', index=sx)[0] protinfo = port.get_attr('IFLA_PROTINFO') assert protinfo.get_attr('IFLA_BRPORT_COST') == 200 assert protinfo.get_attr('IFLA_BRPORT_PROXYARP') == 1 assert protinfo.get_attr('IFLA_BRPORT_UNICAST_FLOOD') == 0 def test_local_add(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', local='172.16.0.1', mask=24) link = self.ip.get_addr(index=self.ifaces[0])[0] address = link.get_attr('IFA_ADDRESS') local = link.get_attr('IFA_LOCAL') assert address == '172.16.0.2' assert local == '172.16.0.1' def test_addr_broadcast(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24, broadcast='172.16.0.250') assert '172.16.0.250' in get_ip_brd() def test_addr_broadcast_default(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24, broadcast=True) assert '172.16.0.255' in get_ip_brd() def test_flush_addr(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.2', mask=24) assert len( self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 4 self.ip.flush_addr(index=self.ifaces[0]) assert len( self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 0 def test_flush_rules(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', table=10, priority=110) self.ip.rule('add', table=15, priority=150, action='FR_ACT_PROHIBIT') self.ip.rule('add', table=20, priority=200, src='172.16.200.1') self.ip.rule('add', table=25, priority=250, dst='172.16.250.1') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 4 assert len(self.ip.get_rules(src='172.16.200.1')) == 1 assert len(self.ip.get_rules(dst='172.16.250.1')) == 1 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(src='172.16.200.1')) == 0 assert len(self.ip.get_rules(dst='172.16.250.1')) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_rules_deprecated(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', 10, 110) self.ip.rule('add', 15, 150, 'FR_ACT_PROHIBIT') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 2 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_match_callable(self): assert len(self.ip.get_links(match=partial(lambda x: x))) > 0 def test_addr_filter(self): require_user('root') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.1', prefixlen=24, broadcast='172.16.0.255') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.2', prefixlen=24, broadcast='172.16.0.255') assert len(self.ip.get_addr(index=self.ifaces[0])) == 2 assert len(self.ip.get_addr(address='172.16.0.1')) == 1 assert len(self.ip.get_addr(broadcast='172.16.0.255')) == 2 assert len( self.ip.get_addr( match=lambda x: x['index'] == self.ifaces[0])) == 2 @skip_if_not_supported def _create_ipvlan(self, smode): master = uifname() ipvlan = uifname() # create the master link self.ip.link('add', ifname=master, kind='dummy') midx = self.ip.link_lookup(ifname=master)[0] # check modes # maybe move modes dict somewhere else? cmode = ifinfmsg.ifinfo.data_map['ipvlan'].modes[smode] assert ifinfmsg.ifinfo.data_map['ipvlan'].modes[cmode] == smode # create ipvlan self.ip.link('add', ifname=ipvlan, kind='ipvlan', link=midx, mode=cmode) devs = self.ip.link_lookup(ifname=ipvlan) assert devs self.ifaces.extend(devs) def test_create_ipvlan_l2(self): return self._create_ipvlan('IPVLAN_MODE_L2') def test_create_ipvlan_l3(self): return self._create_ipvlan('IPVLAN_MODE_L3') @skip_if_not_supported def _create(self, kind, **kwarg): name = uifname() self.ip.link('add', ifname=name, kind=kind, **kwarg) devs = self.ip.link_lookup(ifname=name) assert devs self.ifaces.extend(devs) return (name, devs[0]) def test_create_dummy(self): require_user('root') self._create('dummy') def test_create_bond(self): require_user('root') self._create('bond') def test_create_bridge(self): require_user('root') self._create('bridge') def test_create_team(self): require_user('root') self._create('team') def test_create_vti(self): require_user('root') self._create('vti', vti_link=1, vti_local='127.0.0.1', vti_remote='127.0.0.10', vti_ikey=64, vti_okey=72) def test_create_vti6(self): require_user('root') self._create('vti6', vti_link=2, vti_local='fd00:1:2:3:4:1::1', vti_remote='fd00:1:2:3:4:2::1', vti_ikey=80, vti_okey=88) def test_ntables(self): setA = set( filter(lambda x: x is not None, [ x.get_attr('NDTA_PARMS').get_attr('NDTPA_IFINDEX') for x in self.ip.get_ntables() ])) setB = set([x['index'] for x in self.ip.get_links()]) assert setA == setB def test_fdb_vxlan(self): require_kernel(4, 4) require_user('root') # create dummy (dn, dx) = self._create('dummy') # create vxlan on it (vn, vx) = self._create('vxlan', vxlan_link=dx, vxlan_id=500) # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=vx, vni=600, port=5678, dst='172.16.40.40') # dump r = self.ip.fdb('dump', ifindex=vx, lladdr=l2) assert len(r) == 1 assert r[0]['ifindex'] == vx assert r[0].get_attr('NDA_LLADDR') == l2 assert r[0].get_attr('NDA_DST') == '172.16.40.40' assert r[0].get_attr('NDA_PORT') == 5678 assert r[0].get_attr('NDA_VNI') == 600 def test_fdb_bridge_simple(self): require_kernel(4, 4) require_user('root') require_kernel(4, 4) # create bridge (bn, bx) = self._create('bridge') # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=bx) # dump FDB r = self.ip.fdb('dump', ifindex=bx, lladdr=l2) # one vlan == 1, one w/o vlan assert len(r) == 2 assert len(list(filter(lambda x: x['ifindex'] == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_VLAN'), r))) == 1 assert len(list(filter(lambda x: x.get_attr('NDA_MASTER') == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_LLADDR') == l2, r))) == 2 r = self.ip.fdb('dump', ifindex=bx, lladdr=l2, vlan=1) assert len(r) == 1 assert r[0].get_attr('NDA_VLAN') == 1 assert r[0].get_attr('NDA_MASTER') == bx assert r[0].get_attr('NDA_LLADDR') == l2 def test_neigh_real_links(self): links = set([x['index'] for x in self.ip.get_links()]) neigh = set([x['ifindex'] for x in self.ip.get_neighbours()]) assert neigh < links def test_neigh_filter(self): require_user('root') # inject arp records self.ip.neigh('add', dst='172.16.45.1', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) self.ip.neigh('add', dst='172.16.45.2', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) # assert two arp records on the interface assert len(self.ip.get_neighbours(ifindex=self.ifaces[0])) == 2 # filter by dst assert len(self.ip.get_neighbours(dst='172.16.45.1')) == 1 # filter with lambda assert len( self.ip.get_neighbours( match=lambda x: x['ifindex'] == self.ifaces[0])) == 2 def test_mass_ipv6(self): # # Achtung! This test is time consuming. # It is really time consuming, I'm not not # kidding you. Beware. # require_user('root') base = 'fdb3:84e5:4ff4:55e4::{0}' limit = int(os.environ.get('PYROUTE2_SLIMIT', '0x800'), 16) # add addresses for idx in range(limit): self.ip.addr('add', self.ifaces[0], base.format(hex(idx)[2:]), 48) # assert addresses in two steps, to ease debug addrs = self.ip.get_addr(10) assert len(addrs) >= limit # clean up addresses # # it is not required, but if you don't do that, # you'll get this on the interface removal: # # >> kernel:BUG: soft lockup - CPU#0 stuck for ... # # so, not to scare people, remove addresses gracefully # one by one # # it also verifies all the addresses are in place for idx in reversed(range(limit)): self.ip.addr('delete', self.ifaces[0], base.format(hex(idx)[2:]), 48) def test_fail_not_permitted(self): try: self.ip.addr('add', 1, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.EPERM: # Operation not permitted raise finally: try: self.ip.addr('delete', 1, address='172.16.0.1', mask=24) except: pass def test_fail_no_such_device(self): require_user('root') dev = sorted([i['index'] for i in self.ip.get_links()])[-1] + 10 try: self.ip.addr('add', dev, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.ENODEV: # No such device raise def test_remove_link(self): require_user('root') try: self.ip.link('del', index=self.ifaces[0]) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 0 def _test_route_proto(self, proto, fake, spec=''): require_user('root') os.system('ip route add 172.16.3.0/24 via 127.0.0.1 %s' % spec) time.sleep(1) assert grep('ip ro', pattern='172.16.3.0/24.*127.0.0.1') try: self.ip.route('del', dst='172.16.3.0/24', gateway='127.0.0.1', proto=fake) except NetlinkError: pass self.ip.route('del', dst='172.16.3.0/24', gateway='127.0.0.1', proto=proto) assert not grep('ip ro', pattern='172.16.3.0/24.*127.0.0.1') def test_route_proto_static(self): return self._test_route_proto('static', 'boot', 'proto static') def test_route_proto_static_num(self): return self._test_route_proto(4, 3, 'proto static') def test_route_proto_boot(self): return self._test_route_proto('boot', 4) def test_route_proto_boot_num(self): return self._test_route_proto(3, 'static') def test_route_oif_as_iterable(self): require_user('root') spec = {'dst': '172.16.0.0', 'dst_len': 24, 'oif': (1, )} self.ip.route('add', **spec) rts = self.ip.get_routes(family=socket.AF_INET, dst='172.16.0.0') self.ip.route('del', **spec) assert len(rts) == 1 assert rts[0].get_attr('RTA_OIF') == 1 def test_route_get_target(self): if not self.ip.get_default_routes(table=254): raise SkipTest('no default IPv4 routes') rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_route_get_target_default_ipv4(self): rts = self.ip.get_routes(dst='127.0.0.1') assert len(rts) > 0 def test_route_get_target_default_ipv6(self): rts = self.ip.get_routes(dst='::1') assert len(rts) > 0 def test_route_get_by_spec(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', index=self.ifaces[0], address='172.16.60.1', mask=24) self.ip.addr('add', index=self.ifaces[0], address='172.16.61.1', mask=24) rts = self.ip.get_routes(family=socket.AF_INET, dst=lambda x: x in ('172.16.60.0', '172.16.61.0')) assert len(rts) == 4 @skip_if_not_supported def _test_route_mpls_via_ipv(self, family, address, label): require_kernel(4, 4) require_user('root') self.ip.route( 'add', **{ 'family': AF_MPLS, 'oif': self.ifaces[0], 'via': { 'family': family, 'addr': address }, 'newdst': { 'label': label, 'bos': 1 } }) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_VIA')['addr'] == address assert rt.get_attr('RTA_VIA')['family'] == family assert rt.get_attr('RTA_NEWDST')[0]['label'] == label assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route( 'del', **{ 'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': { 'label': 0x10, 'bos': 1 }, 'via': { 'family': family, 'addr': address }, 'newdst': { 'label': label, 'bos': 1 } }) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_mpls_via_ipv4(self): self._test_route_mpls_via_ipv(socket.AF_INET, '172.16.0.1', 0x20) def test_route_mpls_via_ipv6(self): self._test_route_mpls_via_ipv(socket.AF_INET6, 'fe80::5054:ff:fe4b:7c32', 0x20) @skip_if_not_supported def test_route_mpls_swap_newdst_simple(self): require_kernel(4, 4) require_user('root') req = { 'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': { 'label': 0x20, 'bos': 1 }, 'newdst': { 'label': 0x21, 'bos': 1 } } self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 @skip_if_not_supported def test_route_mpls_swap_newdst_list(self): require_kernel(4, 4) require_user('root') req = { 'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': { 'label': 0x20, 'bos': 1 }, 'newdst': [{ 'label': 0x21, 'bos': 1 }] } self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_multipath_raw(self): require_user('root') self.ip.route('add', dst='172.16.241.0', mask=24, multipath=[{ 'hops': 20, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.2']] }, { 'hops': 30, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.3']] }]) assert grep('ip route show', pattern='172.16.241.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.241.0', mask=24) def test_route_multipath_helper(self): require_user('root') req = IPRouteRequest({ 'dst': '172.16.242.0/24', 'multipath': [{ 'hops': 20, 'oif': 1, 'gateway': '127.0.0.2' }, { 'hops': 30, 'oif': 1, 'gateway': '127.0.0.3' }] }) self.ip.route('add', **req) assert grep('ip route show', pattern='172.16.242.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.242.0', mask=24) def test_route_multipath(self): require_user('root') self.ip.route('add', dst='172.16.243.0/24', multipath=[{ 'gateway': '127.0.0.2' }, { 'gateway': '127.0.0.3' }]) assert grep('ip route show', pattern='172.16.243.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2') assert grep('ip route show', pattern='nexthop.*127.0.0.3') self.ip.route('del', dst='172.16.243.0', mask=24) def test_route_onlink(self): require_user('root') self.ip.route('add', dst='172.16.244.0/24', gateway='10.100.1.1', oif=1, flags=RTNH_F_ONLINK) assert grep('ip route show', pattern='10.100.1.1.*onlink') self.ip.route('del', dst='172.16.244.0/24') def test_route_onlink_multipath(self): require_user('root') self.ip.route('add', dst='172.16.245.0/24', multipath=[{ 'gateway': '10.100.1.1', 'oif': 1, 'flags': RTNH_F_ONLINK }, { 'gateway': '10.100.1.2', 'oif': 1, 'flags': RTNH_F_ONLINK }]) assert grep('ip route show', pattern='172.16.245.0/24') assert grep('ip route show', pattern='nexthop.*10.100.1.1.*onlink') assert grep('ip route show', pattern='nexthop.*10.100.1.2.*onlink') self.ip.route('del', dst='172.16.245.0', mask=24) def test_route_onlink_strflags(self): require_user('root') self.ip.route('add', dst='172.16.244.0/24', gateway='10.100.1.1', oif=1, flags=['onlink']) assert grep('ip route show', pattern='10.100.1.1.*onlink') self.ip.route('del', dst='172.16.244.0/24') def test_route_onlink_multipath_strflags(self): require_user('root') self.ip.route('add', dst='172.16.245.0/24', multipath=[{ 'gateway': '10.100.1.1', 'oif': 1, 'flags': ['onlink'] }, { 'gateway': '10.100.1.2', 'oif': 1, 'flags': RTNH_F_ONLINK }]) assert grep('ip route show', pattern='172.16.245.0/24') assert grep('ip route show', pattern='nexthop.*10.100.1.1.*onlink') assert grep('ip route show', pattern='nexthop.*10.100.1.2.*onlink') self.ip.route('del', dst='172.16.245.0', mask=24) @skip_if_not_supported def test_lwtunnel_multipath_mpls(self): require_kernel(4, 4) require_user('root') require_kernel(4, 5) self.ip.route('add', dst='172.16.216.0/24', multipath=[{ 'encap': { 'type': 'mpls', 'labels': 500 }, 'oif': 1 }, { 'encap': { 'type': 'mpls', 'labels': '600/700' }, 'gateway': '127.0.0.4' }]) routes = self.ip.route('dump', dst='172.16.216.0/24') assert len(routes) == 1 mp = routes[0].get_attr('RTA_MULTIPATH') assert len(mp) == 2 assert mp[0]['oif'] == 1 assert mp[0].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[0].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 500 assert mp[1].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[1].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 600 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 700 self.ip.route('del', dst='172.16.216.0/24') @skip_if_not_supported def test_lwtunnel_mpls_dict_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) self.ip.route('add', dst='172.16.226.0/24', encap={ 'type': 'mpls', 'labels': [{ 'bos': 0, 'label': 226 }, { 'bos': 1, 'label': 227 }] }, gateway='127.0.0.2') routes = self.ip.route('dump', dst='172.16.226.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_GATEWAY') == '127.0.0.2' labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 226 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 227 self.ip.route('del', dst='172.16.226.0/24') @skip_if_not_supported def test_lwtunnel_mpls_2_int_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) self.ip.route('add', dst='172.16.206.0/24', encap={ 'type': 'mpls', 'labels': [206, 207] }, oif=1) routes = self.ip.route('dump', dst='172.16.206.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 206 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 207 self.ip.route('del', dst='172.16.206.0/24') @skip_if_not_supported def test_lwtunnel_mpls_2_str_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) self.ip.route('add', dst='172.16.246.0/24', encap={ 'type': 'mpls', 'labels': "246/247" }, oif=1) routes = self.ip.route('dump', dst='172.16.246.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 246 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 247 self.ip.route('del', dst='172.16.246.0/24') @skip_if_not_supported def test_lwtunnel_mpls_1_str_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) self.ip.route('add', dst='172.16.244.0/24', encap={ 'type': 'mpls', 'labels': "244" }, oif=1) routes = self.ip.route('dump', dst='172.16.244.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 244 self.ip.route('del', dst='172.16.244.0/24') @skip_if_not_supported def test_lwtunnel_mpls_1_int_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) self.ip.route('add', dst='172.16.245.0/24', encap={ 'type': 'mpls', 'labels': 245 }, oif=1) routes = self.ip.route('dump', dst='172.16.245.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 245 self.ip.route('del', dst='172.16.245.0/24') def test_route_change_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_change_not_existing_fail(self): # route('change', ...) should fail, if no route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') try: self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) except NetlinkError as e: if e.code != errno.ENOENT: raise def test_route_replace_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_replace_not_existing(self): # route('replace', ...) should succeed, if route doesn't exist require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') def test_flush_routes(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) self.ip.route('add', dst='172.16.2.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') self.ip.flush_routes(table=100, family=socket.AF_INET6) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') self.ip.flush_routes(table=100, family=socket.AF_INET) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert not grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') def test_route_table_2048(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=2048) assert grep('ip route show table 2048', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_symbolic_flags_ifaddrmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], '172.16.1.1', 24) addr = [ x for x in self.ip.get_addr() if x.get_attr('IFA_LOCAL') == '172.16.1.1' ][0] assert 'IFA_F_PERMANENT' in addr.flags2names(addr['flags']) def test_symbolic_flags_ifinfmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], flags=['IFF_UP']) iface = self.ip.get_links(self.ifaces[0])[0] assert iface['flags'] & 1 assert 'IFF_UP' in iface.flags2names(iface['flags']) self.ip.link('set', index=self.ifaces[0], flags=['!IFF_UP']) assert not (self.ip.get_links(self.ifaces[0])[0]['flags'] & 1) def test_updown_link(self): require_user('root') try: self.ip.link_up(*self.ifaces) except NetlinkError: pass assert self.ip.get_links(*self.ifaces)[0]['flags'] & 1 try: self.ip.link_down(*self.ifaces) except NetlinkError: pass assert not (self.ip.get_links(*self.ifaces)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.ifaces[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == -1, (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_link_filter(self): links = self.ip.link('dump', ifname='lo') assert len(links) == 1 assert links[0].get_attr('IFLA_IFNAME') == 'lo' def test_link_legacy_nla(self): require_user('root') dev = self.ifaces[0] try: self.ip.link('set', index=dev, state='down') self.ip.link('set', index=dev, IFLA_IFNAME='bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link('set', index=dev, ifname=self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_link_rename(self): require_user('root') dev = self.ifaces[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))
class EnableDeployerIfc(object): BRIDGE = 'bridge' LOCAL = 'lo' def __init__(self, log, inv_file): inv = Inventory(log, inv_file) self.log = log self.ext_label_dev = inv.get_mgmt_switch_external_dev_label() if inv.is_passive_mgmt_switches(): if self.ext_label_dev: self.log.info('Passive Management Switch(es) Detected') print(self.ext_label_dev) sys.exit(0) else: self.log.error('Management switch not found') sys.exit(1) for self.ipv4 in inv.yield_mgmt_switch_ip(): pass mgmt_network = inv.get_ipaddr_mgmt_network() self.broadcast = str(netaddr.IPNetwork(mgmt_network).broadcast) self.mask = str(netaddr.IPNetwork(mgmt_network).netmask) if self.ext_label_dev: self.log.debug('External dev label %s was specified' % self.ext_label_dev) else: self.log.debug('External dev label was not specified') self.ext_ip_dev = inv.get_mgmt_switch_external_dev_ip() self.ext_prefix = inv.get_mgmt_switch_external_prefix() for self.ext_ip_switch in inv.yield_mgmt_switch_external_switch_ip(): pass self.ext_broadcast = str( netaddr.IPNetwork(self.ext_ip_dev + '/' + self.ext_prefix).broadcast) self.ext_mask = str( netaddr.IPNetwork(self.ext_ip_dev + '/' + self.ext_prefix).netmask) self.ipr = IPRoute() for link in self.ipr.get_links(): kind = None try: self.label = (link.get_attr('IFLA_IFNAME')) kind = ( link.get_attr('IFLA_LINKINFO').get_attr('IFLA_INFO_KIND')) except: pass if kind == self.BRIDGE: if self.ipr.get_addr(label=self.label, broadcast=self.broadcast): self.log.info('Bridge %s on management subnet %s found' % (self.label, mgmt_network)) if self._ping(self.ipv4, self.label): self.log.info('Management switch found on %s' % self.label) sys.exit(0) else: self.log.debug('Management switch not found on %s' % self.label) if self.ext_label_dev: self.dev = self.ipr.link_lookup(ifname=self.ext_label_dev)[0] self._add_ip() # Print to stdout for Ansible playbook to register print(self.ext_label_dev) else: switch_found = False for link in self.ipr.get_links(): kind = None try: self.label = (link.get_attr('IFLA_IFNAME')) kind = (link.get_attr('IFLA_LINKINFO').get_attr( 'IFLA_INFO_KIND')) except: pass if self.label != self.LOCAL and not kind: self.dev = self.ipr.link_lookup(ifname=self.label)[0] self._add_ip() if self._ping(self.ext_ip_switch, self.label): switch_found = True self.log.info('Management switch found on %s' % self.label) self._configure_switch() else: self.log.debug('Management switch not found on %s' % self.label) self._del_ip() if switch_found: break if not switch_found: self.log.error('Management switch not found') sys.exit(1) # Print to stdout for Ansible playbook to register print(self.label) def _add_ip(self): if self.ext_label_dev: label = self.ext_label_dev else: label = self.label if self.ipr.get_addr(label=label, address=self.ext_ip_dev): self._is_add_ext_ip = False self.log.debug('%s was already configured on %s' % (self.ext_ip_dev, label)) else: self._is_add_ext_ip = True self.log.debug('Add %s to interface %s' % (self.ext_ip_dev, label)) self.ipr.addr('add', index=self.dev, address=self.ext_ip_dev, mask=int(self.ext_prefix), broadcast=self.ext_broadcast) def _ping(self, ipaddr, dev): if os.system('ping -c 1 -I %s %s > /dev/null' % (dev, ipaddr)): self.log.info('Ping via %s to management switch at %s failed' % (dev, ipaddr)) return False self.log.info('Ping via %s to management switch at %s passed' % (dev, ipaddr)) return True
class TestIPRoute(object): def setup(self): self.ip = IPRoute() self.ap = AddrPool() self.iftmp = 'pr2x{0}' try: self.dev, idx = self.create() self.ifaces = [idx] except IndexError: pass def get_ifname(self): return self.iftmp.format(self.ap.alloc()) def create(self, kind='dummy'): name = self.get_ifname() create_link(name, kind=kind) idx = self.ip.link_lookup(ifname=name)[0] return (name, idx) def teardown(self): if hasattr(self, 'ifaces'): for dev in self.ifaces: try: self.ip.link('delete', index=dev) except: pass self.ip.close() def _test_nla_operators(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == self.ifaces[0]] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == self.dev assert intersection['prefixlen'] == 24 assert intersection['index'] == self.ifaces[0] def test_add_addr(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def _create(self, kind): name = self.get_ifname() self.ip.link_create(ifname=name, kind=kind) devs = self.ip.link_lookup(ifname=name) assert devs self.ifaces.extend(devs) def test_create_dummy(self): require_user('root') self._create('dummy') def test_create_bond(self): require_user('root') self._create('bond') def test_create_bridge(self): require_user('root') self._create('bridge') def test_neigh_real_links(self): links = set([x['index'] for x in self.ip.get_links()]) neigh = set([x['ifindex'] for x in self.ip.get_neighbors()]) assert neigh < links def test_mass_ipv6(self): # # Achtung! This test is time consuming. # It is really time consuming, I'm not not # kidding you. Beware. # require_user('root') base = 'fdb3:84e5:4ff4:55e4::{0}' limit = int(os.environ.get('PYROUTE2_SLIMIT', '0x800'), 16) # add addresses for idx in range(limit): self.ip.addr('add', self.ifaces[0], base.format(hex(idx)[2:]), 48) # assert addresses in two steps, to ease debug addrs = self.ip.get_addr(10) assert len(addrs) >= limit # clean up addresses # # it is not required, but if you don't do that, # you'll get this on the interface removal: # # >> kernel:BUG: soft lockup - CPU#0 stuck for ... # # so, not to scare people, remove addresses gracefully # one by one # # it also verifies all the addresses are in place for idx in reversed(range(limit)): self.ip.addr('delete', self.ifaces[0], base.format(hex(idx)[2:]), 48) def test_fail_not_permitted(self): try: self.ip.addr('add', 1, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != 1: # Operation not permitted raise finally: try: self.ip.addr('delete', 1, address='172.16.0.1', mask=24) except: pass def test_fail_no_such_device(self): require_user('root') dev = sorted([i['index'] for i in self.ip.get_links()])[-1] + 10 try: self.ip.addr('add', dev, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != 19: # No such device raise def test_remove_link(self): require_user('root') try: self.ip.link_remove(self.ifaces[0]) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 0 def test_get_route(self): if not self.ip.get_default_routes(table=254): return rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_flush_routes(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', prefix='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) self.ip.route('add', prefix='172.16.2.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert not grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') def test_route_table_2048(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', prefix='172.16.1.0', mask=24, gateway='172.16.0.1', table=2048) assert grep('ip route show table 2048', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_symbolic_flags_ifaddrmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], '172.16.1.1', 24) addr = [x for x in self.ip.get_addr() if x.get_attr('IFA_LOCAL') == '172.16.1.1'][0] assert 'IFA_F_PERMANENT' in addr.flags2names(addr['flags']) def test_symbolic_flags_ifinfmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], flags=['IFF_UP']) iface = self.ip.get_links(self.ifaces[0])[0] assert iface['flags'] & 1 assert 'IFF_UP' in iface.flags2names(iface['flags']) self.ip.link('set', index=self.ifaces[0], flags=['!IFF_UP']) assert not (self.ip.get_links(self.ifaces[0])[0]['flags'] & 1) def test_updown_link(self): require_user('root') try: self.ip.link_up(*self.ifaces) except NetlinkError: pass assert self.ip.get_links(*self.ifaces)[0]['flags'] & 1 try: self.ip.link_down(*self.ifaces) except NetlinkError: pass assert not (self.ip.get_links(*self.ifaces)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.ifaces[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == -1, (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_rename_link(self): require_user('root') dev = self.ifaces[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))
def process(self, pkt): if not hasattr(pkt, 'ip'): return ip = pkt.ip # Ignore non-tcp, non-udp packets if type(ip.data) not in (TCP, UDP): return pload = ip.data src, dst, dport, flags = int(struct.unpack('I', ip.src)[0]), int( struct.unpack('I', ip.dst)[0]), int(pload.dport), 0 proto = type(pload) if proto == TCP: flags = pload.flags key = self.host_hash(src, dst) curr = time.time() # Keep dropping old entries self.recent_scans.collect() if key in self.scans: scan = self.scans[key] if scan.src != src: # Skip packets in reverse direction or invalid protocol return # Update only if not too old, else skip and remove entry if curr - scan.timestamp > self.timeout: del self.scans[key] return if scan.logged: return # Update TCP flags if existing port if dport in scan.ports: # Same port, update flags scan.tcpflags_or |= flags return scan.timestamp = curr scan.tcpflags_or |= flags scan.ports.append(dport) #print dport #destination port printed # Add weight for port if dport < 1024: scan.weight += 3 else: scan.weight += 1 if scan.weight >= self.threshold: scan.logged = True if proto == TCP: scan.type = self.scan_types.get(scan.tcpflags_or, 'unknown') elif proto == UDP: scan.type = 'UDP' # Reset flags for UDP scan scan.tcpflags_or = 0 # See if this was logged recently scanentry = (key, scan.type, scan.tcpflags_or) if scanentry not in self.recent_scans: #ip change code here ipdb = pyroute2.IPDB() with ipdb.interfaces.ens33 as ens33: #print ens33 ip = IPRoute() oldip = ip.get_addr()[1]['attrs'][0][1] oldoctet = int(oldip[11:]) oldip = oldip + '/24' newoctet = np.random.randint(100, 110) #print (oldoctet,newoctet,type(oldoctet),type(newoctet)) while oldoctet == newoctet: #print 'entered while' newoctet = np.random.randint(100, 110) oldoctet = newoctet newip = '192.168.50.' + str(newoctet) #+'/24' print "**********************************" x = datetime.datetime.now() print(x) print "old ip :" + oldip print "Printing new octet : " + str(newoctet) print "new ip :" + newip print "**********************************" ens33.del_ip(oldip) #ens33.add_ip(newip) index = ip.link_lookup(ifname='ens33')[0] ip.addr('add', index, address=newip, mask=24, broadcast='192.168.50.255', metric=100) ip.close() #ens33.set('broadcast', '192.168.50.255').commit() #ens33['broadcast']='192.168.50.255' self.log_scan(scan) self.recent_scans.append(scanentry) else: self.log_scan(scan, True) else: # Add new entry scan = ScanEntry(key) scan.src = src scan.dst = dst scan.timestamp = curr scan.tcpflags_or |= flags scan.ports.append(dport) self.scans[key] = scan
def main(argv): if (len(argv) != 2): print('Usage: python pvdtest_veth.py PVD_ID') print('PVD_ID := name of the interface that contains PvD-related network configuration') sys.exit() # Get user-entered PVD ID pvdId = sys.argv[1] # Create IPRoute object for manipulation with a default network namespace ipMain = IPRoute() # Create a PvD-related network namespace pvdNetnsName = getPvdNetnsName(pvdId); if (pvdNetnsName in netns.listnetns()): netns.remove(pvdNetnsName) netns.create(pvdNetnsName) # Create IPRoute object for manipulation with a PvD-related network namespace netns.setns(pvdNetnsName) ipPvd = IPRoute() # Activate loopback interface in a PvD-related network namespace loIndex = ipPvd.link_lookup(ifname='lo')[0] ipPvd.link_up(loIndex) # Get addresses from a PvD-related network interface pvdIfIndex = ipMain.link_lookup(ifname=getPvdIfName(pvdId))[0] pvdAddresses = ipMain.get_addr(index=pvdIfIndex) # Get current routes pvdRoutes = ipMain.get_routes() # Create bridge bridge = getPvdBridgeName(pvdId) ipMain.link_create(ifname=bridge, kind='bridge') # Create veth interface (veth0, veth1) = getPvdVethNames(pvdId) ipMain.link_create(ifname=veth0, kind='veth', peer=veth1) # Move one end of the veth interafce to a PvD-related network namespace veth1Index = ipMain.link_lookup(ifname=veth1)[0] ipMain.link('set', index=veth1Index, net_ns_fd=pvdNetnsName) # Shut down and remove addresses from the PvD interface before adding it to the bridge ipMain.link_down(pvdIfIndex) ipMain.flush_addr(pvdIfIndex) # Make a bridge between PvD interface and one end of veth interface veth0Index = ipMain.link_lookup(ifname=veth0)[0] bridgeIndex = ipMain.link_lookup(ifname=bridge)[0] ipMain.link('set', index=veth0Index, master=bridgeIndex) ipMain.link('set', index=pvdIfIndex, master=bridgeIndex) # Activate bridge and connected interfaces ipMain.link_up(pvdIfIndex) ipMain.link_up(veth0Index) ipMain.link_up(bridgeIndex) ipPvd.link_up(veth1Index) # Configure bridge and another end of the veth interface with PvD-related network parameters + add routes ipMain.flush_routes() ipPvd.flush_routes() for address in pvdAddresses: ipAddress = broadcastAddress = netmask = addrFamily = None for attr in address['attrs']: if attr[0] == 'IFA_ADDRESS': ipAddress = attr[1] if attr[0] == 'IFA_BROADCAST': broadcastAddress = attr[1] netmask = address['prefixlen'] addrFamily = address['family'] # Configure bridge try: ipMain.addr('add', index=bridgeIndex, family=addrFamily, address=ipAddress, broadcast=broadcastAddress, mask=netmask) except: pass # Configure veth try: ipPvd.addr('add', index=veth1Index, family=addrFamily, address=ipAddress, broadcast=broadcastAddress, mask=netmask) except: pass # Configure routes # Some routes are added during interface IP address/netmask configuration, skip them if already there ipNetwork = IPNetwork(ipAddress + '/' + str(netmask)) try: ipMain.route('add', dst=str(ipNetwork.network), mask=netmask, oif=bridgeIndex, src=ipAddress, rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_LINK') except: pass try: ipPvd.route('add', dst=str(ipNetwork.network), mask=netmask, oif=veth1Index, src=ipAddress, rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_LINK') except: pass # Fing gateway(s) and add default routes defGateways = [] for route in pvdRoutes: for attr in route['attrs']: if (attr[0] == 'RTA_GATEWAY' and attr[1] not in defGateways): defGateways.append(attr[1]) if (len(defGateways) > 0): ipMain.route('add', dst='0.0.0.0', oif=bridgeIndex, gateway=defGateways[0], rtproto='RTPROT_STATIC') ipPvd.route('add', dst='0.0.0.0', oif=veth1Index, gateway=defGateways[0], rtproto='RTPROT_STATIC')
def test_freeze(self): require_user('root') interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.1.1/24') i.up() # check assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 # assert routine def probe(): # The freeze results are dynamic: it is not a real freeze, # it is a restore routine. So it takes time for results # to stabilize err = None for _ in range(3): err = None interface.ipaddr.set_target((('172.16.0.1', 24), ('172.16.1.1', 24))) interface.ipaddr.target.wait() try: assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 break except AssertionError as e: err = e continue except Exception as e: err = e break if err is not None: interface.unfreeze() i2.close() raise err # freeze interface.freeze() # change the interface somehow i2 = IPRoute() i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) probe() # unfreeze self.ip.interfaces[self.ifd].unfreeze() try: i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) except: pass finally: i2.close() # should be up, but w/o addresses interface.ipaddr.set_target(set()) interface.ipaddr.target.wait(3) assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1
class TestIPRoute(object): def setup(self): self.ip = IPRoute() try: self.ifaces = [] self.dev, idx = self.create() except IndexError: pass def create(self, kind='dummy'): name = uifname() create_link(name, kind=kind) idx = self.ip.link_lookup(ifname=name)[0] self.ifaces.append(idx) return (name, idx) def teardown(self): if hasattr(self, 'ifaces'): for dev in self.ifaces: try: self.ip.link('delete', index=dev) except: pass self.ip.close() def _test_nla_operators(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == self.ifaces[0]] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == self.dev assert intersection['prefixlen'] == 24 assert intersection['index'] == self.ifaces[0] def test_addr_add(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def test_vlan_filter_dump(self): require_user('root') (an, ax) = self.create('bridge') (bn, bx) = self.create('bridge') self.ip.link('set', index=ax, state='up') self.ip.link('set', index=bx, state='up') assert len(self.ip.get_vlans()) >= 2 for name in (an, bn): assert len(self.ip.get_vlans(ifname=name)) == 1 assert (self .ip .get_vlans(ifname=name)[0] .get_attr('IFLA_IFNAME')) == name assert (self .ip .get_vlans(ifname=name)[0] .get_nested('IFLA_AF_SPEC', 'IFLA_BRIDGE_VLAN_INFO'))['vid'] == 1 def test_vlan_filter_add(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern='567') self.ip.vlan_filter('add', index=sx, vlan_info={'vid': 567}) assert grep('bridge vlan show', pattern='567') self.ip.vlan_filter('del', index=sx, vlan_info={'vid': 567}) assert not grep('bridge vlan show', pattern='567') def test_vlan_filter_add_raw(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern='567') self.ip.vlan_filter('add', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', {'vid': 567}]]}) assert grep('bridge vlan show', pattern='567') self.ip.vlan_filter('del', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', {'vid': 567}]]}) assert not grep('bridge vlan show', pattern='567') def test_local_add(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', local='172.16.0.1', mask=24) link = self.ip.get_addr(index=self.ifaces[0])[0] address = link.get_attr('IFA_ADDRESS') local = link.get_attr('IFA_LOCAL') assert address == '172.16.0.2' assert local == '172.16.0.1' def test_addr_broadcast(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24, broadcast='172.16.0.250') assert '172.16.0.250' in get_ip_brd() def test_addr_broadcast_default(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24, broadcast=True) assert '172.16.0.255' in get_ip_brd() def test_flush_addr(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.2', mask=24) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 4 self.ip.flush_addr(index=self.ifaces[0]) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 0 def test_flush_rules(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', table=10, priority=110) self.ip.rule('add', table=15, priority=150, action='FR_ACT_PROHIBIT') self.ip.rule('add', table=20, priority=200, src='172.16.200.1') self.ip.rule('add', table=25, priority=250, dst='172.16.250.1') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 4 assert len(self.ip.get_rules(src='172.16.200.1')) == 1 assert len(self.ip.get_rules(dst='172.16.250.1')) == 1 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(src='172.16.200.1')) == 0 assert len(self.ip.get_rules(dst='172.16.250.1')) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_rules_deprecated(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', 10, 110) self.ip.rule('add', 15, 150, 'FR_ACT_PROHIBIT') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 2 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_addr_filter(self): require_user('root') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.1', prefixlen=24, broadcast='172.16.0.255') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.2', prefixlen=24, broadcast='172.16.0.255') assert len(self.ip.get_addr(index=self.ifaces[0])) == 2 assert len(self.ip.get_addr(address='172.16.0.1')) == 1 assert len(self.ip.get_addr(broadcast='172.16.0.255')) == 2 assert len(self.ip.get_addr(match=lambda x: x['index'] == self.ifaces[0])) == 2 @skip_if_not_supported def _create_ipvlan(self, smode): master = uifname() ipvlan = uifname() # create the master link self.ip.link('add', ifname=master, kind='dummy') midx = self.ip.link_lookup(ifname=master)[0] # check modes # maybe move modes dict somewhere else? cmode = ifinfmsg.ifinfo.ipvlan_data.modes[smode] assert ifinfmsg.ifinfo.ipvlan_data.modes[cmode] == smode # create ipvlan self.ip.link('add', ifname=ipvlan, kind='ipvlan', link=midx, mode=cmode) devs = self.ip.link_lookup(ifname=ipvlan) assert devs self.ifaces.extend(devs) def test_create_ipvlan_l2(self): return self._create_ipvlan('IPVLAN_MODE_L2') def test_create_ipvlan_l3(self): return self._create_ipvlan('IPVLAN_MODE_L3') @skip_if_not_supported def _create(self, kind, **kwarg): name = uifname() self.ip.link('add', ifname=name, kind=kind, **kwarg) devs = self.ip.link_lookup(ifname=name) assert devs self.ifaces.extend(devs) return (name, devs[0]) def test_create_dummy(self): require_user('root') self._create('dummy') def test_create_bond(self): require_user('root') self._create('bond') def test_create_bridge(self): require_user('root') self._create('bridge') def test_create_team(self): require_user('root') self._create('team') def test_ntables(self): setA = set(filter(lambda x: x is not None, [x.get_attr('NDTA_PARMS').get_attr('NDTPA_IFINDEX') for x in self.ip.get_ntables()])) setB = set([x['index'] for x in self.ip.get_links()]) assert setA == setB def test_fdb_vxlan(self): require_kernel(4, 4) require_user('root') # create dummy (dn, dx) = self._create('dummy') # create vxlan on it (vn, vx) = self._create('vxlan', vxlan_link=dx, vxlan_id=500) # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=vx, vni=600, port=5678, dst='172.16.40.40') # dump r = self.ip.fdb('dump', ifindex=vx, lladdr=l2) assert len(r) == 1 assert r[0]['ifindex'] == vx assert r[0].get_attr('NDA_LLADDR') == l2 assert r[0].get_attr('NDA_DST') == '172.16.40.40' assert r[0].get_attr('NDA_PORT') == 5678 assert r[0].get_attr('NDA_VNI') == 600 def test_fdb_bridge_simple(self): require_kernel(4, 4) require_user('root') # create bridge (bn, bx) = self._create('bridge') # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=bx) # dump FDB r = self.ip.fdb('dump', ifindex=bx, lladdr=l2) # one vlan == 1, one w/o vlan assert len(r) == 2 assert len(list(filter(lambda x: x['ifindex'] == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_VLAN'), r))) == 1 assert len(list(filter(lambda x: x.get_attr('NDA_MASTER') == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_LLADDR') == l2, r))) == 2 r = self.ip.fdb('dump', ifindex=bx, lladdr=l2, vlan=1) assert len(r) == 1 assert r[0].get_attr('NDA_VLAN') == 1 assert r[0].get_attr('NDA_MASTER') == bx assert r[0].get_attr('NDA_LLADDR') == l2 def test_neigh_real_links(self): links = set([x['index'] for x in self.ip.get_links()]) neigh = set([x['ifindex'] for x in self.ip.get_neighbours()]) assert neigh < links def test_neigh_filter(self): require_user('root') # inject arp records self.ip.neigh('add', dst='172.16.45.1', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) self.ip.neigh('add', dst='172.16.45.2', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) # assert two arp records on the interface assert len(self.ip.get_neighbours(ifindex=self.ifaces[0])) == 2 # filter by dst assert len(self.ip.get_neighbours(dst='172.16.45.1')) == 1 # filter with lambda assert len(self.ip.get_neighbours(match=lambda x: x['ifindex'] == self.ifaces[0])) == 2 def test_mass_ipv6(self): # # Achtung! This test is time consuming. # It is really time consuming, I'm not not # kidding you. Beware. # require_user('root') base = 'fdb3:84e5:4ff4:55e4::{0}' limit = int(os.environ.get('PYROUTE2_SLIMIT', '0x800'), 16) # add addresses for idx in range(limit): self.ip.addr('add', self.ifaces[0], base.format(hex(idx)[2:]), 48) # assert addresses in two steps, to ease debug addrs = self.ip.get_addr(10) assert len(addrs) >= limit # clean up addresses # # it is not required, but if you don't do that, # you'll get this on the interface removal: # # >> kernel:BUG: soft lockup - CPU#0 stuck for ... # # so, not to scare people, remove addresses gracefully # one by one # # it also verifies all the addresses are in place for idx in reversed(range(limit)): self.ip.addr('delete', self.ifaces[0], base.format(hex(idx)[2:]), 48) def test_fail_not_permitted(self): try: self.ip.addr('add', 1, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.EPERM: # Operation not permitted raise finally: try: self.ip.addr('delete', 1, address='172.16.0.1', mask=24) except: pass def test_fail_no_such_device(self): require_user('root') dev = sorted([i['index'] for i in self.ip.get_links()])[-1] + 10 try: self.ip.addr('add', dev, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.ENODEV: # No such device raise def test_remove_link(self): require_user('root') try: self.ip.link('del', index=self.ifaces[0]) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 0 def _test_route_proto(self, proto, fake, spec=''): require_user('root') os.system('ip route add 172.16.3.0/24 via 127.0.0.1 %s' % spec) time.sleep(1) assert grep('ip ro', pattern='172.16.3.0/24.*127.0.0.1') try: self.ip.route('del', dst='172.16.3.0/24', gateway='127.0.0.1', proto=fake) except NetlinkError: pass self.ip.route('del', dst='172.16.3.0/24', gateway='127.0.0.1', proto=proto) assert not grep('ip ro', pattern='172.16.3.0/24.*127.0.0.1') def test_route_proto_static(self): return self._test_route_proto('static', 'boot', 'proto static') def test_route_proto_static_num(self): return self._test_route_proto(4, 3, 'proto static') def test_route_proto_boot(self): return self._test_route_proto('boot', 4) def test_route_proto_boot_num(self): return self._test_route_proto(3, 'static') def test_route_oif_as_iterable(self): require_user('root') spec = {'dst': '172.16.0.0', 'dst_len': 24, 'oif': (1, )} self.ip.route('add', **spec) rts = self.ip.get_routes(family=socket.AF_INET, dst='172.16.0.0') self.ip.route('del', **spec) assert len(rts) == 1 assert rts[0].get_attr('RTA_OIF') == 1 def test_route_get_target(self): if not self.ip.get_default_routes(table=254): raise SkipTest('no default IPv4 routes') rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_route_get_target_default_ipv4(self): rts = self.ip.get_routes(dst='127.0.0.1') assert len(rts) > 0 def test_route_get_target_default_ipv6(self): rts = self.ip.get_routes(dst='::1') assert len(rts) > 0 def test_route_get_by_spec(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', index=self.ifaces[0], address='172.16.60.1', mask=24) self.ip.addr('add', index=self.ifaces[0], address='172.16.61.1', mask=24) rts = self.ip.get_routes(family=socket.AF_INET, dst=lambda x: x in ('172.16.60.0', '172.16.61.0')) assert len(rts) == 4 @skip_if_not_supported def _test_route_mpls_via_ipv(self, family, address, label): require_kernel(4, 4) require_user('root') self.ip.route('add', **{'family': AF_MPLS, 'oif': self.ifaces[0], 'via': {'family': family, 'addr': address}, 'newdst': {'label': label, 'bos': 1}}) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_VIA')['addr'] == address assert rt.get_attr('RTA_VIA')['family'] == family assert rt.get_attr('RTA_NEWDST')[0]['label'] == label assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **{'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x10, 'bos': 1}, 'via': {'family': family, 'addr': address}, 'newdst': {'label': label, 'bos': 1}}) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_mpls_via_ipv4(self): self._test_route_mpls_via_ipv(socket.AF_INET, '172.16.0.1', 0x20) def test_route_mpls_via_ipv6(self): self._test_route_mpls_via_ipv(socket.AF_INET6, 'fe80::5054:ff:fe4b:7c32', 0x20) @skip_if_not_supported def test_route_mpls_swap_newdst_simple(self): require_kernel(4, 4) require_user('root') req = {'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x20, 'bos': 1}, 'newdst': {'label': 0x21, 'bos': 1}} self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 @skip_if_not_supported def test_route_mpls_swap_newdst_list(self): require_kernel(4, 4) require_user('root') req = {'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x20, 'bos': 1}, 'newdst': [{'label': 0x21, 'bos': 1}]} self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_multipath_raw(self): require_user('root') self.ip.route('add', dst='172.16.241.0', mask=24, multipath=[{'hops': 20, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.2']]}, {'hops': 30, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.3']]}]) assert grep('ip route show', pattern='172.16.241.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.241.0', mask=24) def test_route_multipath_helper(self): require_user('root') req = IPRouteRequest({'dst': '172.16.242.0/24', 'multipath': [{'hops': 20, 'oif': 1, 'gateway': '127.0.0.2'}, {'hops': 30, 'oif': 1, 'gateway': '127.0.0.3'}]}) self.ip.route('add', **req) assert grep('ip route show', pattern='172.16.242.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.242.0', mask=24) def test_route_multipath(self): require_user('root') self.ip.route('add', dst='172.16.243.0/24', multipath=[{'gateway': '127.0.0.2'}, {'gateway': '127.0.0.3'}]) assert grep('ip route show', pattern='172.16.243.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2') assert grep('ip route show', pattern='nexthop.*127.0.0.3') self.ip.route('del', dst='172.16.243.0', mask=24) @skip_if_not_supported def test_lwtunnel_multipath_mpls(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.216.0/24', multipath=[{'encap': {'type': 'mpls', 'labels': 500}, 'oif': 1}, {'encap': {'type': 'mpls', 'labels': '600/700'}, 'gateway': '127.0.0.4'}]) routes = self.ip.route('dump', dst='172.16.216.0/24') assert len(routes) == 1 mp = routes[0].get_attr('RTA_MULTIPATH') assert len(mp) == 2 assert mp[0]['oif'] == 1 assert mp[0].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[0].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 500 assert mp[1].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[1].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 600 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 700 self.ip.route('del', dst='172.16.216.0/24') @skip_if_not_supported def test_lwtunnel_mpls_dict_label(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.226.0/24', encap={'type': 'mpls', 'labels': [{'bos': 0, 'label': 226}, {'bos': 1, 'label': 227}]}, gateway='127.0.0.2') routes = self.ip.route('dump', dst='172.16.226.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_GATEWAY') == '127.0.0.2' labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 226 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 227 self.ip.route('del', dst='172.16.226.0/24') @skip_if_not_supported def test_lwtunnel_mpls_2_int_label(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.206.0/24', encap={'type': 'mpls', 'labels': [206, 207]}, oif=1) routes = self.ip.route('dump', dst='172.16.206.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 206 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 207 self.ip.route('del', dst='172.16.206.0/24') @skip_if_not_supported def test_lwtunnel_mpls_2_str_label(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.246.0/24', encap={'type': 'mpls', 'labels': "246/247"}, oif=1) routes = self.ip.route('dump', dst='172.16.246.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 246 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 247 self.ip.route('del', dst='172.16.246.0/24') @skip_if_not_supported def test_lwtunnel_mpls_1_str_label(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.244.0/24', encap={'type': 'mpls', 'labels': "244"}, oif=1) routes = self.ip.route('dump', dst='172.16.244.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 244 self.ip.route('del', dst='172.16.244.0/24') @skip_if_not_supported def test_lwtunnel_mpls_1_int_label(self): require_kernel(4, 4) require_user('root') self.ip.route('add', dst='172.16.245.0/24', encap={'type': 'mpls', 'labels': 245}, oif=1) routes = self.ip.route('dump', dst='172.16.245.0/24') assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 245 self.ip.route('del', dst='172.16.245.0/24') def test_route_change_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_change_not_existing_fail(self): # route('change', ...) should fail, if no route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') try: self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) except NetlinkError as e: if e.code != errno.ENOENT: raise def test_route_replace_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_replace_not_existing(self): # route('replace', ...) should succeed, if route doesn't exist require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') def test_flush_routes(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) self.ip.route('add', dst='172.16.2.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert not grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') def test_route_table_2048(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=2048) assert grep('ip route show table 2048', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_symbolic_flags_ifaddrmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], '172.16.1.1', 24) addr = [x for x in self.ip.get_addr() if x.get_attr('IFA_LOCAL') == '172.16.1.1'][0] assert 'IFA_F_PERMANENT' in addr.flags2names(addr['flags']) def test_symbolic_flags_ifinfmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], flags=['IFF_UP']) iface = self.ip.get_links(self.ifaces[0])[0] assert iface['flags'] & 1 assert 'IFF_UP' in iface.flags2names(iface['flags']) self.ip.link('set', index=self.ifaces[0], flags=['!IFF_UP']) assert not (self.ip.get_links(self.ifaces[0])[0]['flags'] & 1) def test_updown_link(self): require_user('root') try: self.ip.link_up(*self.ifaces) except NetlinkError: pass assert self.ip.get_links(*self.ifaces)[0]['flags'] & 1 try: self.ip.link_down(*self.ifaces) except NetlinkError: pass assert not (self.ip.get_links(*self.ifaces)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.ifaces[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == -1, (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_link_filter(self): l = self.ip.link('dump', ifname='lo') assert len(l) == 1 assert l[0].get_attr('IFLA_IFNAME') == 'lo' def test_link_rename(self): require_user('root') dev = self.ifaces[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))
netns.create('test') # create VETH pair and move v0p1 to netns 'test' ip.link_create(ifname='v0p0', peer='v0p1', kind='veth') idx = ip.link_lookup(ifname='v0p1')[0] ip.link('set', index=idx, net_ns_fd='test') # bring v0p0 up and add an address idx = ip.link_lookup(ifname='v0p0')[0] ip.link('set', index=idx, state='up') ip.addr('add', index=idx, address='10.0.0.1', broadcast='10.0.0.255', prefixlen=24) # create a route with metrics ip.route('add', dst='172.16.0.0/24', gateway='10.0.0.10', metrics={'mtu': 1400, 'hoplimit': 16}) # release Netlink socket ip.close()
class TestIPRoute(object): ipnets = [] ipranges = [] ifnames = [] def setup(self): self.ip = IPRoute() self.ipnets = [allocate_network() for _ in range(3)] self.ipranges = [[str(x) for x in net] for net in self.ipnets] self.ifaces = [] self.ifnames = [] try: self.dev, idx = self.create() except IndexError: pass def create(self, kind='dummy'): require_user('root') name = uifname() self.ip.link('add', ifname=name, kind=kind) idx = None while not idx: idx = self.ip.link_lookup(ifname=name) idx = idx[0] self.ifaces.append(idx) return (name, idx) def uifname(self): ifname = uifname() self.ifnames.append(ifname) return ifname def teardown(self): for net in self.ipnets: free_network(net) if hasattr(self, 'ifaces'): for dev in reversed(self.ifaces): try: self.ip.link('delete', index=dev) except: pass for name in reversed(self.ifnames): try: (self .ip .link('del', index=(self .ip .link_lookup(ifname=name)[0]))) except: pass self.ip.close() def ifaddr(self, r=0): return str(self.ipranges[r].pop()) def _test_nla_operators(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == self.ifaces[0]] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == self.dev assert intersection['prefixlen'] == 24 assert intersection['index'] == self.ifaces[0] def test_addr_add(self): require_user('root') ifaddr = self.ifaddr() self.ip.addr('add', self.ifaces[0], address=ifaddr, mask=24) assert '{0}/24'.format(ifaddr) in get_ip_addr() def test_vlan_filter_dump(self): require_user('root') (an, ax) = self.create('bridge') (bn, bx) = self.create('bridge') self.ip.link('set', index=ax, state='up') self.ip.link('set', index=bx, state='up') assert len(self.ip.get_vlans()) >= 2 for name in (an, bn): assert len(self.ip.get_vlans(ifname=name)) == 1 assert (self .ip .get_vlans(ifname=name)[0] .get_attr('IFLA_IFNAME')) == name assert (self .ip .get_vlans(ifname=name)[0] .get_nested('IFLA_AF_SPEC', 'IFLA_BRIDGE_VLAN_INFO'))['vid'] == 1 def test_vlan_filter_add(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern=' 568') self.ip.vlan_filter('add', index=sx, vlan_info={'vid': 568}) assert grep('bridge vlan show', pattern=' 568') self.ip.vlan_filter('del', index=sx, vlan_info={'vid': 568}) assert not grep('bridge vlan show', pattern=' 568') def test_vlan_filter_add_raw(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) assert not grep('bridge vlan show', pattern=' 567') self.ip.vlan_filter('add', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', {'vid': 567}]]}) assert grep('bridge vlan show', pattern=' 567') self.ip.vlan_filter('del', index=sx, af_spec={'attrs': [['IFLA_BRIDGE_VLAN_INFO', {'vid': 567}]]}) assert not grep('bridge vlan show', pattern=' 567') def test_brport_basic(self): require_user('root') (bn, bx) = self.create('bridge') (sn, sx) = self.create('dummy') self.ip.link('set', index=sx, master=bx) self.ip.link('set', index=sx, state='up') self.ip.link('set', index=bx, state='up') self.ip.brport('set', index=sx, unicast_flood=0, cost=200, proxyarp=1) port = self.ip.brport('show', index=sx)[0] protinfo = port.get_attr('IFLA_PROTINFO') assert protinfo.get_attr('IFLA_BRPORT_COST') == 200 assert protinfo.get_attr('IFLA_BRPORT_PROXYARP') == 1 assert protinfo.get_attr('IFLA_BRPORT_UNICAST_FLOOD') == 0 def test_local_add(self): require_user('root') ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.addr('add', self.ifaces[0], address=ifaddr1, local=ifaddr2, mask=24) link = self.ip.get_addr(index=self.ifaces[0])[0] address = link.get_attr('IFA_ADDRESS') local = link.get_attr('IFA_LOCAL') assert address == ifaddr1 assert local == ifaddr2 def test_addr_broadcast(self): require_user('root') ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24, broadcast=ifaddr2) assert ifaddr2 in get_ip_brd() def test_addr_broadcast_default(self): require_user('root') ifaddr1 = self.ifaddr() # -> 255 ifaddr2 = self.ifaddr() # -> 254 self.ip.addr('add', self.ifaces[0], address=ifaddr2, mask=24, broadcast=True) assert ifaddr1 in get_ip_brd() def test_flush_addr(self): require_user('root') ifaddr1 = self.ifaddr(0) ifaddr2 = self.ifaddr(0) ifaddr3 = self.ifaddr(1) ifaddr4 = self.ifaddr(1) self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.addr('add', self.ifaces[0], address=ifaddr2, mask=24) self.ip.addr('add', self.ifaces[0], address=ifaddr3, mask=24) self.ip.addr('add', self.ifaces[0], address=ifaddr4, mask=24) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 4 self.ip.flush_addr(index=self.ifaces[0]) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 0 def test_flush_rules(self): require_user('root') ifaddr1 = self.ifaddr(0) ifaddr2 = self.ifaddr(1) init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', table=10, priority=110) self.ip.rule('add', table=15, priority=150, action='FR_ACT_PROHIBIT') self.ip.rule('add', table=20, priority=200, src=ifaddr1) self.ip.rule('add', table=25, priority=250, dst=ifaddr2) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 4 assert len(self.ip.get_rules(src=ifaddr1)) == 1 assert len(self.ip.get_rules(dst=ifaddr2)) == 1 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(src=ifaddr1)) == 0 assert len(self.ip.get_rules(dst=ifaddr2)) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_rules_deprecated(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', 10, 110) self.ip.rule('add', 15, 150, 'FR_ACT_PROHIBIT') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 2 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_match_callable(self): assert len(self.ip.get_links(match=partial(lambda x: x))) > 0 def test_addr_filter(self): require_user('root') ifaddr_brd = self.ifaddr() ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.addr('add', index=self.ifaces[0], address=ifaddr1, prefixlen=24, broadcast=ifaddr_brd) self.ip.addr('add', index=self.ifaces[0], address=ifaddr2, prefixlen=24, broadcast=ifaddr_brd) assert len(self.ip.get_addr(index=self.ifaces[0])) == 2 assert len(self.ip.get_addr(address=ifaddr1)) == 1 assert len(self.ip.get_addr(broadcast=ifaddr_brd)) == 2 assert len(self.ip.get_addr(match=lambda x: x['index'] == self.ifaces[0])) == 2 @skip_if_not_supported def _create_ipvlan(self, smode): require_user('root') master = self.uifname() ipvlan = self.uifname() # create the master link self.ip.link('add', ifname=master, kind='dummy') midx = self.ip.link_lookup(ifname=master)[0] # check modes # maybe move modes dict somewhere else? cmode = ifinfmsg.ifinfo.data_map['ipvlan'].modes[smode] assert ifinfmsg.ifinfo.data_map['ipvlan'].modes[cmode] == smode # create ipvlan self.ip.link('add', ifname=ipvlan, kind='ipvlan', link=midx, mode=cmode) devs = self.ip.link_lookup(ifname=ipvlan) assert devs def test_create_ipvlan_l2(self): return self._create_ipvlan('IPVLAN_MODE_L2') def test_create_ipvlan_l3(self): return self._create_ipvlan('IPVLAN_MODE_L3') def _create_veth(self, peer): ifname = self.uifname() self.ip.link('add', kind='veth', ifname=ifname, peer=peer) assert len(self.ip.link_lookup(ifname=ifname)) > 0 return ifname def test_create_veth_simple(self): require_user('root') peer = self.uifname() self._create_veth(peer) assert len(self.ip.link_lookup(ifname=peer)) > 0 def test_create_veth_attrs(self): require_user('root') nsname = str(uuid.uuid4()) netns = NetNS(nsname) try: peer = {'ifname': self.uifname(), 'net_ns_fd': nsname} self._create_veth(peer) assert len(self.ip.link_lookup(ifname=peer['ifname'])) == 0 assert len(netns.link_lookup(ifname=peer['ifname'])) > 0 finally: netns.close() netns.remove() def test_get_netns_info(self): require_user('root') nsname = str(uuid.uuid4()) netns = NetNS(nsname) try: peer = {'ifname': self.uifname(), 'net_ns_fd': nsname} ifname = self._create_veth(peer) # get veth veth = self.ip.link('get', ifname=ifname)[0] target = veth.get_attr('IFLA_LINK_NETNSID') for info in self.ip.get_netns_info(): path = info.get_attr('NSINFO_PATH') assert path.endswith(nsname) netnsid = info['netnsid'] if target == netnsid: break else: raise KeyError('peer netns not found') finally: netns.close() netns.remove() @skip_if_not_supported def _create(self, kind, **kwarg): name = self.uifname() self.ip.link('add', ifname=name, kind=kind, **kwarg) devs = self.ip.link_lookup(ifname=name) assert devs return (name, devs[0]) def test_create_dummy(self): require_user('root') self._create('dummy') def test_create_bond(self): require_user('root') self._create('bond') def test_create_bridge(self): require_user('root') self._create('bridge') def test_create_team(self): require_user('root') self._create('team') def test_create_vti(self): require_user('root') ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() (ifname, idx) = self.create() self.ip.link('set', index=idx, state='up') self.ip.addr('add', index=idx, address=ifaddr1, mask=24) self._create('vti', vti_link=idx, vti_local=ifaddr1, vti_remote=ifaddr2, vti_ikey=64, vti_okey=72) def test_create_vti6(self): require_user('root') self._create('vti6', vti_link=2, vti_local='fd00:1:2:3:4:1::1', vti_remote='fd00:1:2:3:4:2::1', vti_ikey=80, vti_okey=88) def test_create_xfrm(self): require_user('root') # XXX: Currently does not work on top of a dummy device idx = self.ip.link_lookup(ifname='lo')[0] # # Create Dummy for Parent # (_, idx) = self.create() self.ip.link('set', index=idx, state='up') # Create XFRM Interface on It self._create('xfrm', xfrm_link=idx, xfrm_if_id=555) def _test_ntables(self): setA = set(filter(lambda x: x is not None, [x.get_attr('NDTA_PARMS').get_attr('NDTPA_IFINDEX') for x in self.ip.get_ntables()])) setB = set([x['index'] for x in self.ip.get_links()]) assert setA == setB def test_fdb_vxlan(self): require_kernel(4, 4) require_user('root') ifaddr = self.ifaddr() # create dummy (dn, dx) = self._create('dummy') # create vxlan on it (vn, vx) = self._create('vxlan', vxlan_link=dx, vxlan_id=500) # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=vx, vni=600, port=5678, dst=ifaddr) # dump r = self.ip.fdb('dump', ifindex=vx, lladdr=l2) assert len(r) == 1 assert r[0]['ifindex'] == vx assert r[0].get_attr('NDA_LLADDR') == l2 assert r[0].get_attr('NDA_DST') == ifaddr assert r[0].get_attr('NDA_PORT') == 5678 assert r[0].get_attr('NDA_VNI') == 600 def test_fdb_bridge_simple(self): require_kernel(4, 4) require_user('root') require_kernel(4, 4) # create bridge (bn, bx) = self._create('bridge') # create FDB record l2 = '00:11:22:33:44:55' self.ip.fdb('add', lladdr=l2, ifindex=bx) # dump FDB r = self.ip.fdb('dump', ifindex=bx, lladdr=l2) # one vlan == 1, one w/o vlan assert len(r) == 2 assert len(list(filter(lambda x: x['ifindex'] == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_VLAN'), r))) == 1 assert len(list(filter(lambda x: x.get_attr('NDA_MASTER') == bx, r))) == 2 assert len(list(filter(lambda x: x.get_attr('NDA_LLADDR') == l2, r))) == 2 r = self.ip.fdb('dump', ifindex=bx, lladdr=l2, vlan=1) assert len(r) == 1 assert r[0].get_attr('NDA_VLAN') == 1 assert r[0].get_attr('NDA_MASTER') == bx assert r[0].get_attr('NDA_LLADDR') == l2 def test_neigh_real_links(self): links = set([x['index'] for x in self.ip.get_links()]) neigh = set([x['ifindex'] for x in self.ip.get_neighbours()]) assert neigh < links def test_neigh_filter(self): require_user('root') ifaddr1 = self.ifaddr(1) ifaddr2 = self.ifaddr(1) # inject arp records self.ip.neigh('add', dst=ifaddr1, lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) self.ip.neigh('add', dst=ifaddr2, lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) # assert two arp records on the interface assert len(self.ip.get_neighbours(ifindex=self.ifaces[0])) == 2 # filter by dst assert len(self.ip.get_neighbours(dst=ifaddr1)) == 1 # filter with lambda assert len(self.ip.get_neighbours(match=lambda x: x['ifindex'] == self.ifaces[0])) == 2 def test_mass_ipv6(self): # # Achtung! This test is time consuming. # It is really time consuming, I'm not not # kidding you. Beware. # require_user('root') ipv6net = allocate_network('ipv6') base = str(ipv6net.network) + '{0}' limit = int(os.environ.get('PYROUTE2_SLIMIT', '0x800'), 16) # add addresses for idx in range(limit): self.ip.addr('add', self.ifaces[0], base.format(hex(idx)[2:]), 48) # assert addresses in two steps, to ease debug addrs = self.ip.get_addr(10) assert len(addrs) >= limit # clean up addresses # # it is not required, but if you don't do that, # you'll get this on the interface removal: # # >> kernel:BUG: soft lockup - CPU#0 stuck for ... # # so, not to scare people, remove addresses gracefully # one by one # # it also verifies all the addresses are in place for idx in reversed(range(limit)): self.ip.addr('delete', self.ifaces[0], base.format(hex(idx)[2:]), 48) free_network(ipv6net, 'ipv6') def test_fail_not_permitted(self): ifaddr = self.ifaddr() try: self.ip.addr('add', 1, address=ifaddr, mask=24) except NetlinkError as e: if e.code != errno.EPERM: # Operation not permitted raise finally: try: self.ip.addr('delete', 1, address=ifaddr, mask=24) except: pass def test_fail_no_such_device(self): require_user('root') ifaddr = self.ifaddr() dev = sorted([i['index'] for i in self.ip.get_links()])[-1] + 10 try: self.ip.addr('add', dev, address=ifaddr, mask=24) except NetlinkError as e: if e.code != errno.ENODEV: # No such device raise def test_remove_link(self): require_user('root') try: self.ip.link('del', index=self.ifaces[0]) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 0 def _test_route_proto(self, proto, fake, spec=''): require_user('root') naddr = str(self.ipnets[1].network) os.system('ip route add %s/24 via 127.0.0.1 %s' % (naddr, spec)) time.sleep(1) assert grep('ip ro', pattern='%s/24.*127.0.0.1' % naddr) try: self.ip.route('del', dst='%s/24' % naddr, gateway='127.0.0.1', proto=fake) except NetlinkError: pass self.ip.route('del', dst='%s/24' % naddr, gateway='127.0.0.1', proto=proto) assert not grep('ip ro', pattern='%s/24.*127.0.0.1' % naddr) def test_route_proto_static(self): return self._test_route_proto('static', 'boot', 'proto static') def test_route_proto_static_num(self): return self._test_route_proto(4, 3, 'proto static') def test_route_proto_boot(self): return self._test_route_proto('boot', 4) def test_route_proto_boot_num(self): return self._test_route_proto(3, 'static') def test_route_oif_as_iterable(self): require_user('root') naddr = str(self.ipnets[1].network) spec = {'dst': naddr, 'dst_len': 24, 'oif': (1, )} self.ip.route('add', **spec) rts = self.ip.get_routes(family=socket.AF_INET, dst=naddr) self.ip.route('del', **spec) assert len(rts) == 1 assert rts[0].get_attr('RTA_OIF') == 1 def test_route_get_target(self): if not self.ip.get_default_routes(table=254): raise SkipTest('no default IPv4 routes') rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_route_get_target_default_ipv4(self): rts = self.ip.get_routes(dst='127.0.0.1') assert len(rts) > 0 def test_route_get_target_default_ipv6(self): rts = self.ip.get_routes(dst='::1') assert len(rts) > 0 def test_route_get_by_spec(self): require_user('root') ifaddr1 = self.ifaddr(0) ifaddr2 = self.ifaddr(1) self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', index=self.ifaces[0], address=ifaddr1, mask=24) self.ip.addr('add', index=self.ifaces[0], address=ifaddr2, mask=24) rts = self.ip.get_routes(family=socket.AF_INET, dst=lambda x: x in (ifaddr1, ifaddr2)) assert len(rts) == 4 @skip_if_not_supported def _test_route_mpls_via_ipv(self, family, address, label): require_kernel(4, 4) require_user('root') self.ip.route('add', **{'family': AF_MPLS, 'oif': self.ifaces[0], 'via': {'family': family, 'addr': address}, 'newdst': {'label': label, 'bos': 1}}) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_VIA')['addr'] == address assert rt.get_attr('RTA_VIA')['family'] == family assert rt.get_attr('RTA_NEWDST')[0]['label'] == label assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **{'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x10, 'bos': 1}, 'via': {'family': family, 'addr': address}, 'newdst': {'label': label, 'bos': 1}}) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_mpls_via_ipv4(self): ifaddr = self.ifaddr() self._test_route_mpls_via_ipv(socket.AF_INET, ifaddr, 0x20) def test_route_mpls_via_ipv6(self): ipv6net = allocate_network('ipv6') address = str(ipv6net.network) + '7c32' self._test_route_mpls_via_ipv(socket.AF_INET6, address, 0x20) free_network(ipv6net, 'ipv6') @skip_if_not_supported def test_route_mpls_swap_newdst_simple(self): require_kernel(4, 4) require_user('root') req = {'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x20, 'bos': 1}, 'newdst': {'label': 0x21, 'bos': 1}} self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 @skip_if_not_supported def test_route_mpls_swap_newdst_list(self): require_kernel(4, 4) require_user('root') req = {'family': AF_MPLS, 'oif': self.ifaces[0], 'dst': {'label': 0x20, 'bos': 1}, 'newdst': [{'label': 0x21, 'bos': 1}]} self.ip.route('add', **req) rt = self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)[0] assert rt.get_attr('RTA_DST')[0]['label'] == 0x20 assert len(rt.get_attr('RTA_DST')) == 1 assert rt.get_attr('RTA_NEWDST')[0]['label'] == 0x21 assert len(rt.get_attr('RTA_NEWDST')) == 1 self.ip.route('del', **req) assert len(self.ip.get_routes(oif=self.ifaces[0], family=AF_MPLS)) == 0 def test_route_multipath_raw(self): require_user('root') naddr = str(self.ipnets[1].network) self.ip.route('add', dst=naddr, mask=24, multipath=[{'hops': 20, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.2']]}, {'hops': 30, 'oif': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.3']]}]) assert grep('ip route show', pattern='%s/24' % naddr) assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst=naddr, mask=24) def test_route_multipath_helper(self): require_user('root') naddr = str(self.ipnets[1].network) req = IPRouteRequest({'dst': '%s/24' % naddr, 'multipath': [{'hops': 20, 'oif': 1, 'gateway': '127.0.0.2'}, {'hops': 30, 'oif': 1, 'gateway': '127.0.0.3'}]}) self.ip.route('add', **req) assert grep('ip route show', pattern='%s/24' % naddr) assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst=naddr, mask=24) def test_route_multipath(self): require_user('root') naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, multipath=[{'gateway': '127.0.0.2'}, {'gateway': '127.0.0.3'}]) assert grep('ip route show', pattern='%s/24' % naddr) assert grep('ip route show', pattern='nexthop.*127.0.0.2') assert grep('ip route show', pattern='nexthop.*127.0.0.3') self.ip.route('del', dst=naddr, mask=24) def test_route_onlink(self): naddr = str(self.ipnets[1].network) ifaddr = self.ifaddr(0) require_user('root') self.ip.route('add', dst='%s/24' % naddr, gateway=ifaddr, oif=1, flags=RTNH_F_ONLINK) assert grep('ip route show', pattern='%s.*onlink' % ifaddr) self.ip.route('del', dst='%s/24' % naddr) def test_route_onlink_multipath(self): require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.route('add', dst='%s/24' % naddr, multipath=[{'gateway': ifaddr1, 'oif': 1, 'flags': RTNH_F_ONLINK}, {'gateway': ifaddr2, 'oif': 1, 'flags': RTNH_F_ONLINK}]) assert grep('ip route show', pattern='%s/24' % naddr) assert grep('ip route show', pattern='nexthop.*%s.*onlink' % ifaddr1) assert grep('ip route show', pattern='nexthop.*%s.*onlink' % ifaddr2) self.ip.route('del', dst=naddr, mask=24) def test_route_onlink_strflags(self): require_user('root') naddr = str(self.ipnets[1].network) ifaddr = self.ifaddr() self.ip.route('add', dst='%s/24' % naddr, gateway=ifaddr, oif=1, flags=['onlink']) assert grep('ip route show', pattern='%s.*onlink' % ifaddr) self.ip.route('del', dst='%s/24' % naddr) def test_route_onlink_multipath_strflags(self): require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.route('add', dst='%s/24' % naddr, multipath=[{'gateway': ifaddr1, 'oif': 1, 'flags': ['onlink']}, {'gateway': ifaddr2, 'oif': 1, 'flags': RTNH_F_ONLINK}]) assert grep('ip route show', pattern='%s/24' % naddr) assert grep('ip route show', pattern='nexthop.*%s.*onlink' % ifaddr1) assert grep('ip route show', pattern='nexthop.*%s.*onlink' % ifaddr2) self.ip.route('del', dst=naddr, mask=24) @skip_if_not_supported def test_lwtunnel_multipath_mpls(self): require_kernel(4, 4) require_user('root') require_kernel(4, 5) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, multipath=[{'encap': {'type': 'mpls', 'labels': 500}, 'oif': 1}, {'encap': {'type': 'mpls', 'labels': '600/700'}, 'gateway': '127.0.0.4'}]) routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 mp = routes[0].get_attr('RTA_MULTIPATH') assert len(mp) == 2 assert mp[0]['oif'] == 1 assert mp[0].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[0].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 500 assert mp[1].get_attr('RTA_ENCAP_TYPE') == 1 labels = mp[1].get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 600 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 700 self.ip.route('del', dst='%s/24' % naddr) @skip_if_not_supported def test_lwtunnel_mpls_dict_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, encap={'type': 'mpls', 'labels': [{'bos': 0, 'label': 226}, {'bos': 1, 'label': 227}]}, gateway='127.0.0.2') routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_GATEWAY') == '127.0.0.2' labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 226 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 227 self.ip.route('del', dst='%s/24' % naddr) @skip_if_not_supported def test_lwtunnel_mpls_2_int_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, encap={'type': 'mpls', 'labels': [206, 207]}, oif=1) routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 206 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 207 self.ip.route('del', dst='%s/24' % naddr) @skip_if_not_supported def test_lwtunnel_mpls_2_str_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, encap={'type': 'mpls', 'labels': "246/247"}, oif=1) routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 2 assert labels[0]['bos'] == 0 assert labels[0]['label'] == 246 assert labels[1]['bos'] == 1 assert labels[1]['label'] == 247 self.ip.route('del', dst='%s/24' % naddr) @skip_if_not_supported def test_lwtunnel_mpls_1_str_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, encap={'type': 'mpls', 'labels': "244"}, oif=1) routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 244 self.ip.route('del', dst='%s/24' % naddr) @skip_if_not_supported def test_lwtunnel_mpls_1_int_label(self): require_kernel(4, 4) require_user('root') require_kernel(4, 3) naddr = str(self.ipnets[1].network) self.ip.route('add', dst='%s/24' % naddr, encap={'type': 'mpls', 'labels': 245}, oif=1) routes = self.ip.route('dump', dst='%s/24' % naddr) assert len(routes) == 1 route = routes[0] assert route.get_attr('RTA_ENCAP_TYPE') == 1 assert route.get_attr('RTA_OIF') == 1 labels = route.get_attr('RTA_ENCAP').get_attr('MPLS_IPTUNNEL_DST') assert len(labels) == 1 assert labels[0]['bos'] == 1 assert labels[0]['label'] == 245 self.ip.route('del', dst='%s/24' % naddr) def test_route_change_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() ifaddr3 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.route('add', dst=naddr, mask=24, gateway=ifaddr2, table=100) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) self.ip.route('change', dst=naddr, mask=24, gateway=ifaddr3, table=100) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr3)) self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr3)) def test_route_change_not_existing_fail(self): # route('change', ...) should fail, if no route exists require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) assert not grep('ip route show table 100', pattern='%s.*%s' % (naddr, ifaddr2)) try: self.ip.route('change', dst=naddr, mask=24, gateway=ifaddr2, table=100) except NetlinkError as e: if e.code != errno.ENOENT: raise def test_route_replace_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() ifaddr3 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.route('replace', dst=naddr, mask=24, gateway=ifaddr2, table=100) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) self.ip.route('replace', dst=naddr, mask=24, gateway=ifaddr3, table=100) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr3)) self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr3)) def test_route_replace_not_existing(self): # route('replace', ...) should succeed, if route doesn't exist require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.route('replace', dst=naddr, mask=24, gateway=ifaddr2, table=100) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr, ifaddr2)) def test_flush_routes(self): require_user('root') naddr1 = str(self.ipnets[1].network) naddr2 = str(self.ipnets[2].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.route('add', dst=naddr1, mask=24, gateway=ifaddr2, table=100) self.ip.route('add', dst=naddr2, mask=24, gateway=ifaddr2, table=100) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr1, ifaddr2)) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr2, ifaddr2)) self.ip.flush_routes(table=100, family=socket.AF_INET6) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr1, ifaddr2)) assert grep('ip route show table 100', pattern='%s/24.*%s' % (naddr2, ifaddr2)) self.ip.flush_routes(table=100, family=socket.AF_INET) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr1, ifaddr2)) assert not grep('ip route show table 100', pattern='%s/24.*%s' % (naddr2, ifaddr2)) def test_route_table_2048(self): require_user('root') naddr = str(self.ipnets[1].network) ifaddr1 = self.ifaddr() ifaddr2 = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address=ifaddr1, mask=24) self.ip.route('add', dst=naddr, mask=24, gateway=ifaddr2, table=2048) assert grep('ip route show table 2048', pattern='%s/24.*%s' % (naddr, ifaddr2)) remove_link('bala') def test_symbolic_flags_ifaddrmsg(self): require_user('root') ifaddr = self.ifaddr() self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], ifaddr, 24) addr = [x for x in self.ip.get_addr() if x.get_attr('IFA_LOCAL') == ifaddr][0] assert 'IFA_F_PERMANENT' in addr.flags2names(addr['flags']) def test_symbolic_flags_ifinfmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], flags=['IFF_UP']) iface = self.ip.get_links(self.ifaces[0])[0] assert iface['flags'] & 1 assert 'IFF_UP' in iface.flags2names(iface['flags']) self.ip.link('set', index=self.ifaces[0], flags=['!IFF_UP']) assert not (self.ip.get_links(self.ifaces[0])[0]['flags'] & 1) def test_updown_link(self): require_user('root') try: for i in self.ifaces: self.ip.link('set', index=i, state='up') except NetlinkError: pass assert self.ip.get_links(*self.ifaces)[0]['flags'] & 1 try: for i in self.ifaces: self.ip.link('set', index=i, state='down') except NetlinkError: pass assert not (self.ip.get_links(*self.ifaces)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.ifaces[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == -1, (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_link_filter(self): links = self.ip.link('dump', ifname='lo') assert len(links) == 1 assert links[0].get_attr('IFLA_IFNAME') == 'lo' def test_link_legacy_nla(self): require_user('root') dev = self.ifaces[0] try: self.ip.link('set', index=dev, state='down') self.ip.link('set', index=dev, IFLA_IFNAME='bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link('set', index=dev, ifname=self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_link_rename(self): require_user('root') dev = self.ifaces[0] try: self.ip.link('set', index=dev, ifname='bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link('set', index=dev, ifname=self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_link_arp_flag(self): require_user('root') dev = self.ifaces[0] # by default dummy interface have NOARP set assert self.ip.get_links(dev)[0]['flags'] & IFF_NOARP self.ip.link('set', index=dev, arp=True) assert not self.ip.get_links(dev)[0]['flags'] & IFF_NOARP self.ip.link('set', index=dev, arp=False) assert self.ip.get_links(dev)[0]['flags'] & IFF_NOARP def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): routes = list(self.ip.get_routes(family=socket.AF_INET, table=255)) assert len(routes) assert all([isinstance(x, dict) for x in routes]) assert all([x['event'] == 'RTM_NEWROUTE' for x in routes])
class TestData(object): def setup(self): create_link('dummyX', 'dummy') self.ip = IPRoute() self.dev = self.ip.link_lookup(ifname='dummyX') def teardown(self): self.ip.release() remove_link('dummyX') remove_link('bala') def test_nla_operators(self): require_user('root') dev = self.dev[0] self.ip.addr('add', dev, address='172.16.0.1', mask=24) self.ip.addr('add', dev, address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == dev] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == 'dummyX' assert intersection['prefixlen'] == 24 assert intersection['index'] == dev def test_add_addr(self): require_user('root') dev = self.dev[0] self.ip.addr('add', dev, address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def test_remove_link(self): require_user('root') create_link('bala', 'dummy') dev = self.ip.link_lookup(ifname='bala')[0] try: self.ip.link_remove(dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 0 def test_get_route(self): if not self.ip.get_default_routes(table=254): return rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_route_table_2048(self): require_user('root') create_link('bala', 'dummy') dev = self.ip.link_lookup(ifname='bala')[0] self.ip.link('set', index=dev, state='up') self.ip.addr('add', dev, address='172.16.0.2', mask=24) self.ip.route('add', prefix='172.16.1.0', mask=24, gateway='172.16.0.1', table=2048) assert grep('ip route show table 2048', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_updown_link(self): require_user('root') dev = self.dev[0] assert not (self.ip.get_links(dev)[0]['flags'] & 1) try: self.ip.link_up(dev) except NetlinkError: pass assert self.ip.get_links(dev)[0]['flags'] & 1 try: self.ip.link_down(dev) except NetlinkError: pass assert not (self.ip.get_links(dev)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.dev[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda e, x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda e, x: x.get('index', None) == 'bala', (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_rename_link(self): require_user('root') dev = self.dev[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, 'dummyX') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='dummyX')) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))
class network_module(PtyshModule): IP = "IP" IP_MASK = "IP/MASK" STRING = "STRING" def __init__(self): super(network_module, self).__init__() super(network_module, self).init_node("network", "network node") super(network_module, self).add_command("link up", "set link state up", self.cmd_link_up, "link up [link name]") super(network_module, self).add_command("link down", "set link state down", self.cmd_link_down, "link down [link name]") super(network_module, self).add_command("ip add", "add ip address", self.cmd_ip_add, "ip add [link name] [ip] [mask] ( [broadcast] [primary] )") super(network_module, self).add_command("route add", "add route address", self.cmd_route_add, "route add [default|ip|ip/mask] [ip|none] [interface]") super(network_module, self).add_command("show link", "show link state", self.cmd_show_link, "show link [link name|none]") super(network_module, self).add_command("show link all", "show all link statue", self.cmd_show_link, "show link all") super(network_module, self).add_command("show route", "show route state", self.cmd_show_route, "show route") self.iproute = IPRoute() self.boarder_len = 60 def get_link_index(self, link_name): index = self.iproute.link_lookup(ifname=link_name) if len(index) != 0: return index[0] else: raise ValueError("There is no interface.") def check_ip_address(self, ip): try: ret = ip_address(ip) except Exception: try: ret = ip_network(ip) except Exception: return self.STRING return self.IP_MASK return self.IP def change_link_state(self, state): index = self.get_link_index(args[0]) ret = self.iproute.link("set", index=index, state=state) if ret[0]["header"]["error"] is not None: raise Exception(ret[0]["header"]["error"]) def print_output_boarder(self, inner): print ("=" * self.boarder_len) if inner else print ("-" * self.boarder_len) def print_output_subject(self, subject): subject_len = len(subject) harf_boarder_len = int((self.boarder_len - (subject_len + 2)) / 2) harf_boarder = "-" * harf_boarder_len print ("%s %s %s" % (harf_boarder, subject, harf_boarder)) def print_key_value(self, key, value): print ("%s : %s" % (key.ljust(25), value)) def print_ip_brief(self, idx, interface, state, ip): print ("%s%s%s%s" % (idx.ljust(8), interface.ljust(15), state.ljust(10), ip.ljust(27))) def print_route_table(self, index, dest, gateway, mask, interface): print ("%s%s%s%s%s" % (index.ljust(8), dest.ljust(17), gateway.ljust(17), mask.ljust(8), interface)) ##### cmd function. ##### def cmd_link_up(self, args): self.change_link_state("up") def cmd_link_down(self, args): self.change_link_state("down") def cmd_ip_add(self, args): if len(args) < 3: raise TypeError() index = self.get_link_index(args[0]) ip = str(args[1]) mask = int(args[2]) broadcast = str(args[3]) if len(args) >= 4 else "" primary = args[4] if len(args) == 5 else True if primary: self.iproute.flush_addr(index=index) if broadcast: ret = self.iproute.addr("add", index=index, address=ip, mask=mask, broadcast=broadcast) else: ret = self.iproute.addr("add", index=index, address=ip, mask=mask) if len(ret): raise Exception(ret) def cmd_route_add(self, args): if len(args) < 3: raise TypeError() dest = args[0] src = args[1] index = self.get_link_index(args[2]) dest_type = self.check_ip_address(dest) src_type = self.check_ip_address(src) if dest == "default" and src_type == self.IP: # default ip self.iproute.route("add", oif=index, gateway=src, proto=rtprotos["RTPROT_BOOT"]) elif dest == "default" and src == "none": # default none self.iproute.route("add", oif=index, gateway=src, proto=rtprotos["RTPROT_BOOT"], dst_len=0, scope=rtscopes["RT_SCOPE_LINK"]) elif dest_type == self.IP_MASK and src_type == self.IP: # ip/mask ip self.iproute.route("add", oif=index, gateway=src, dst=dest, proto=rtprotos["RTPROT_BOOT"]) elif dest_type == self.IP_MASK and src == "none": # ip/mask none self.iproute.route("add", oif=index, dst=dest, proto=rtprotos["RTPROT_BOOT"], scope=rtscopes["RT_SCOPE_LINK"]) elif dest_type == self.IP and src_type == self.IP: # ip ip self.iproute.route("add", oif=index, gateway=src, dst=dest, proto=rtprotos["RTPROT_BOOT"], dst_len=32) elif dest_type == self.IP and src == "none": # ip none self.iproute.route("add", oif=index, dst=dest, proto=rtprotos["RTPROT_BOOT"], dst_len=32, scope=rtscopes["RT_SCOPE_LINK"]) else: raise TypeError() def cmd_show_link(self, args=[]): if len(args) == 0: self.cmd_show_brief_info() elif args[0] == "all": for link in self.iproute.get_links(): self.cmd_show_link_info(link.get_attr("IFLA_IFNAME")) else: self.cmd_show_link_info(args[0]) def cmd_show_brief_info(self): self.print_output_boarder(True) self.print_ip_brief("Index", "Interface", "State", "IP") self.print_output_boarder(False) for link in self.iproute.get_links(): index = link["index"] ip = self.iproute.get_addr(index=index) if len(ip) == 0: self.print_ip_brief(str(index), link.get_attr("IFLA_IFNAME"), link.get_attr("IFLA_OPERSTATE"), "None") continue for idx, address in enumerate(ip): index_format = "%s.%s" % (index, idx) interface = link.get_attr("IFLA_IFNAME") if idx == 0 else "" state = link.get_attr("IFLA_OPERSTATE") if idx == 0 else "" self.print_ip_brief(index_format, interface, state, address.get_attr("IFA_ADDRESS")) self.print_output_boarder(True) def cmd_show_link_info(self, link_name): index = self.get_link_index(link_name) link = self.iproute.get_links(index)[0] self.print_output_boarder(True) self.print_key_value("Index", link["index"]) self.print_key_value("Name", link.get_attr("IFLA_IFNAME")) self.print_key_value("Mac address", link.get_attr("IFLA_ADDRESS")) self.print_key_value("Broadcast", link.get_attr("IFLA_BROADCAST")) self.print_key_value("MTU", link.get_attr("IFLA_MTU")) self.print_key_value("Status", link.get_attr("IFLA_OPERSTATE")) self.print_key_value("Promiscuity", link.get_attr("IFLA_PROMISCUITY")) stats = link.get_attr("IFLA_STATS64") self.print_key_value("multicast", stats["multicast"]) self.print_key_value("collisions", stats["collisions"]) for ip in self.iproute.get_addr(index=index): self.print_output_subject("IP") self.print_key_value("- IP", ip.get_attr("IFA_ADDRESS")) self.print_key_value("- Broadcast IP", ip.get_attr("IFA_BROADCAST")) self.print_key_value("- Subnet", ip["prefixlen"]) self.print_output_boarder(False) self.print_output_subject("RX") self.print_key_value("- rx_packets", stats["rx_packets"]) self.print_key_value("- rx_bytes", stats["rx_bytes"]) self.print_key_value("- rx_dropped", stats["rx_dropped"]) self.print_key_value("- rx_errors", stats["rx_errors"]) self.print_key_value("- rx_compressed", stats["rx_compressed"]) self.print_key_value("- rx_over_errors", stats["rx_over_errors"]) self.print_key_value("- rx_crc_errors", stats["rx_crc_errors"]) self.print_key_value("- rx_length_errors", stats["rx_length_errors"]) self.print_key_value("- rx_fifo_errors", stats["rx_fifo_errors"]) self.print_key_value("- rx_missed_errors", stats["rx_missed_errors"]) self.print_key_value("- rx_frame_errors", stats["rx_frame_errors"]) self.print_output_boarder(False) self.print_output_subject("TX") self.print_key_value("- tx_packets", stats["tx_packets"]) self.print_key_value("- tx_bytes", stats["tx_bytes"]) self.print_key_value("- tx_dropped", stats["tx_dropped"]) self.print_key_value("- tx_errors", stats["tx_errors"]) self.print_key_value("- tx_compressed", stats["tx_compressed"]) self.print_key_value("- tx_heartbeat_errors", stats["tx_heartbeat_errors"]) self.print_key_value("- tx_aborted_errors", stats["tx_aborted_errors"]) self.print_key_value("- tx_window_errors", stats["tx_window_errors"]) self.print_key_value("- tx_fifo_errors", stats["tx_fifo_errors"]) self.print_key_value("- tx_carrier_errors", stats["tx_carrier_errors"]) self.print_output_boarder(False) self.print_output_boarder(True) def cmd_show_route(self): self.print_output_boarder(True) self.print_route_table("Index", "Destination", "Gateway", "Mask", "Interface") self.print_output_boarder(False) for index, route in enumerate(self.iproute.get_routes(table=254)): if route.get_attr("RTA_DST", None) is None and route["dst_len"] == 0: destination = "default" gateway = route.get_attrs("RTA_GATEWAY")[0] else: destination = route.get_attrs("RTA_DST")[0] gateway = "0.0.0.0" interface_index = route.get_attrs("RTA_OIF")[0] interface = self.iproute.get_links(interface_index)[0].get_attrs("IFLA_IFNAME")[0] self.print_route_table(str(index), destination, gateway, str(route["dst_len"]), interface) self.print_output_boarder(True)
class TestData(object): def setup(self): create_link('dummyX', 'dummy') self.release = Event() self.ip = IPRoute() self.dev = self.ip.link_lookup(ifname='dummyX') def teardown(self): self.ip.release() self.release.set() remove_link('dummyX') remove_link('bala') def test_add_addr(self): require_user('root') dev = self.dev[0] self.ip.addr('add', dev, address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def test_remove_link(self): require_user('root') create_link('bala', 'dummy') dev = self.ip.link_lookup(ifname='bala')[0] try: self.ip.link_remove(dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 0 def test_route(self): require_user('root') create_link('bala', 'dummy') dev = self.ip.link_lookup(ifname='bala')[0] self.ip.link('set', index=dev, state='up') self.ip.addr('add', dev, address='172.16.0.2', mask=24) self.ip.route('add', prefix='172.16.1.0', mask=24, gateway='172.16.0.1') assert grep('ip route show', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_updown_link(self): require_user('root') dev = self.dev[0] assert not (self.ip.get_links(dev)[0]['flags'] & 1) try: self.ip.link_up(dev) except NetlinkError: pass assert self.ip.get_links(dev)[0]['flags'] & 1 try: self.ip.link_down(dev) except NetlinkError: pass assert not (self.ip.get_links(dev)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.dev[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda e, x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda e, x: x.get('index', None) == 'bala', (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_rename_link(self): require_user('root') dev = self.dev[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, 'dummyX') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='dummyX')) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))
class TestIPRoute(object): def setup(self): self.ip = IPRoute() try: self.dev, idx = self.create() self.ifaces = [idx] except IndexError: pass def create(self, kind='dummy'): name = uifname() create_link(name, kind=kind) idx = self.ip.link_lookup(ifname=name)[0] return (name, idx) def teardown(self): if hasattr(self, 'ifaces'): for dev in self.ifaces: try: self.ip.link('delete', index=dev) except: pass self.ip.close() def _test_nla_operators(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) r = [x for x in self.ip.get_addr() if x['index'] == self.ifaces[0]] complement = r[0] - r[1] intersection = r[0] & r[1] assert complement.get_attr('IFA_ADDRESS') == '172.16.0.1' assert complement.get_attr('IFA_LABEL') is None assert complement['prefixlen'] == 0 assert complement['index'] == 0 assert intersection.get_attr('IFA_ADDRESS') is None assert intersection.get_attr('IFA_LABEL') == self.dev assert intersection['prefixlen'] == 24 assert intersection['index'] == self.ifaces[0] def test_addr_add(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) assert '172.16.0.1/24' in get_ip_addr() def test_flush_addr(self): require_user('root') self.ip.addr('add', self.ifaces[0], address='172.16.0.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.1', mask=24) self.ip.addr('add', self.ifaces[0], address='172.16.1.2', mask=24) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 4 self.ip.flush_addr(index=self.ifaces[0]) assert len(self.ip.get_addr(index=self.ifaces[0], family=socket.AF_INET)) == 0 def test_flush_rules(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', table=10, priority=110) self.ip.rule('add', table=15, priority=150, action='FR_ACT_PROHIBIT') self.ip.rule('add', table=20, priority=200, src='172.16.200.1') self.ip.rule('add', table=25, priority=250, dst='172.16.250.1') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 4 assert len(self.ip.get_rules(src='172.16.200.1')) == 1 assert len(self.ip.get_rules(dst='172.16.250.1')) == 1 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(src='172.16.200.1')) == 0 assert len(self.ip.get_rules(dst='172.16.250.1')) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_rules_deprecated(self): require_user('root') init = len(self.ip.get_rules(family=socket.AF_INET)) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 self.ip.rule('add', 10, 110) self.ip.rule('add', 15, 150, 'FR_ACT_PROHIBIT') assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 2 self.ip.flush_rules(family=socket.AF_INET, priority=lambda x: 100 < x < 500) assert len(self.ip.get_rules(priority=lambda x: 100 < x < 500)) == 0 assert len(self.ip.get_rules(family=socket.AF_INET)) == init def test_addr_filter(self): require_user('root') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.1', prefixlen=24, broadcast='172.16.0.255') self.ip.addr('add', index=self.ifaces[0], address='172.16.0.2', prefixlen=24, broadcast='172.16.0.255') assert len(self.ip.get_addr(index=self.ifaces[0])) == 2 assert len(self.ip.get_addr(address='172.16.0.1')) == 1 assert len(self.ip.get_addr(broadcast='172.16.0.255')) == 2 assert len(self.ip.get_addr(match=lambda x: x['index'] == self.ifaces[0])) == 2 @skip_if_not_supported def _create(self, kind): name = uifname() self.ip.link_create(ifname=name, kind=kind) devs = self.ip.link_lookup(ifname=name) assert devs self.ifaces.extend(devs) def test_create_dummy(self): require_user('root') self._create('dummy') def test_create_bond(self): require_user('root') self._create('bond') def test_create_bridge(self): require_user('root') self._create('bridge') def test_create_ovs_bridge(self): require_user('root') self._create('ovs-bridge') def test_create_team(self): require_user('root') self._create('team') def test_ntables(self): setA = set(filter(lambda x: x is not None, [x.get_attr('NDTA_PARMS').get_attr('NDTPA_IFINDEX') for x in self.ip.get_ntables()])) setB = set([x['index'] for x in self.ip.get_links()]) assert setA == setB def test_neigh_real_links(self): links = set([x['index'] for x in self.ip.get_links()]) neigh = set([x['ifindex'] for x in self.ip.get_neighbours()]) assert neigh < links def test_neigh_filter(self): require_user('root') # inject arp records self.ip.neigh('add', dst='172.16.45.1', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) self.ip.neigh('add', dst='172.16.45.2', lladdr='00:11:22:33:44:55', ifindex=self.ifaces[0]) # assert two arp records on the interface assert len(self.ip.get_neighbours(ifindex=self.ifaces[0])) == 2 # filter by dst assert len(self.ip.get_neighbours(dst='172.16.45.1')) == 1 # filter with lambda assert len(self.ip.get_neighbours(match=lambda x: x['ifindex'] == self.ifaces[0])) == 2 def test_mass_ipv6(self): # # Achtung! This test is time consuming. # It is really time consuming, I'm not not # kidding you. Beware. # require_user('root') base = 'fdb3:84e5:4ff4:55e4::{0}' limit = int(os.environ.get('PYROUTE2_SLIMIT', '0x800'), 16) # add addresses for idx in range(limit): self.ip.addr('add', self.ifaces[0], base.format(hex(idx)[2:]), 48) # assert addresses in two steps, to ease debug addrs = self.ip.get_addr(10) assert len(addrs) >= limit # clean up addresses # # it is not required, but if you don't do that, # you'll get this on the interface removal: # # >> kernel:BUG: soft lockup - CPU#0 stuck for ... # # so, not to scare people, remove addresses gracefully # one by one # # it also verifies all the addresses are in place for idx in reversed(range(limit)): self.ip.addr('delete', self.ifaces[0], base.format(hex(idx)[2:]), 48) def test_fail_not_permitted(self): try: self.ip.addr('add', 1, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.EPERM: # Operation not permitted raise finally: try: self.ip.addr('delete', 1, address='172.16.0.1', mask=24) except: pass def test_fail_no_such_device(self): require_user('root') dev = sorted([i['index'] for i in self.ip.get_links()])[-1] + 10 try: self.ip.addr('add', dev, address='172.16.0.1', mask=24) except NetlinkError as e: if e.code != errno.ENODEV: # No such device raise def test_remove_link(self): require_user('root') try: self.ip.link_remove(self.ifaces[0]) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 0 def test_route_get_target(self): if not self.ip.get_default_routes(table=254): return rts = self.ip.get_routes(family=socket.AF_INET, dst='8.8.8.8', table=254) assert len(rts) > 0 def test_route_get_by_spec(self): self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', index=self.ifaces[0], address='172.16.60.1', mask=24) self.ip.addr('add', index=self.ifaces[0], address='172.16.61.1', mask=24) rts = self.ip.get_routes(family=socket.AF_INET, dst=lambda x: x in ('172.16.60.0', '172.16.61.0')) assert len(rts) == 4 def test_route_multipath(self): require_user('root') self.ip.route('add', dst='172.16.241.0', mask=24, multipath=[{'hops': 20, 'ifindex': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.2']]}, {'hops': 30, 'ifindex': 1, 'attrs': [['RTA_GATEWAY', '127.0.0.3']]}]) assert grep('ip route show', pattern='172.16.241.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.241.0', mask=24) def test_route_multipath_helper(self): require_user('root') req = IPRouteRequest({'dst': '172.16.242.0/24', 'multipath': [{'hops': 20, 'ifindex': 1, 'gateway': '127.0.0.2'}, {'hops': 30, 'ifindex': 1, 'gateway': '127.0.0.3'}]}) self.ip.route('add', **req) assert grep('ip route show', pattern='172.16.242.0/24') assert grep('ip route show', pattern='nexthop.*127.0.0.2.*weight 21') assert grep('ip route show', pattern='nexthop.*127.0.0.3.*weight 31') self.ip.route('del', dst='172.16.242.0', mask=24) def test_route_change_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_change_not_existing_fail(self): # route('change', ...) should fail, if no route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') try: self.ip.route('change', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) except NetlinkError as e: if e.code != errno.ENOENT: raise def test_route_replace_existing(self): # route('replace', ...) should succeed, if route exists require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.50', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.2', table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.2') def test_route_replace_not_existing(self): # route('replace', ...) should succeed, if route doesn't exist require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('replace', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') def test_flush_routes(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=100) self.ip.route('add', dst='172.16.2.0', mask=24, gateway='172.16.0.1', table=100) assert grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') self.ip.flush_routes(table=100) assert not grep('ip route show table 100', pattern='172.16.1.0/24.*172.16.0.1') assert not grep('ip route show table 100', pattern='172.16.2.0/24.*172.16.0.1') def test_route_table_2048(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], address='172.16.0.2', mask=24) self.ip.route('add', dst='172.16.1.0', mask=24, gateway='172.16.0.1', table=2048) assert grep('ip route show table 2048', pattern='172.16.1.0/24.*172.16.0.1') remove_link('bala') def test_symbolic_flags_ifaddrmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], state='up') self.ip.addr('add', self.ifaces[0], '172.16.1.1', 24) addr = [x for x in self.ip.get_addr() if x.get_attr('IFA_LOCAL') == '172.16.1.1'][0] assert 'IFA_F_PERMANENT' in addr.flags2names(addr['flags']) def test_symbolic_flags_ifinfmsg(self): require_user('root') self.ip.link('set', index=self.ifaces[0], flags=['IFF_UP']) iface = self.ip.get_links(self.ifaces[0])[0] assert iface['flags'] & 1 assert 'IFF_UP' in iface.flags2names(iface['flags']) self.ip.link('set', index=self.ifaces[0], flags=['!IFF_UP']) assert not (self.ip.get_links(self.ifaces[0])[0]['flags'] & 1) def test_updown_link(self): require_user('root') try: self.ip.link_up(*self.ifaces) except NetlinkError: pass assert self.ip.get_links(*self.ifaces)[0]['flags'] & 1 try: self.ip.link_down(*self.ifaces) except NetlinkError: pass assert not (self.ip.get_links(*self.ifaces)[0]['flags'] & 1) def test_callbacks_positive(self): require_user('root') dev = self.ifaces[0] self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == dev, (self, )) self.test_updown_link() assert self.cb_counter > 0 self.ip.unregister_callback(_callback) def test_callbacks_negative(self): require_user('root') self.cb_counter = 0 self.ip.register_callback(_callback, lambda x: x.get('index', None) == -1, (self, )) self.test_updown_link() assert self.cb_counter == 0 self.ip.unregister_callback(_callback) def test_rename_link(self): require_user('root') dev = self.ifaces[0] try: self.ip.link_rename(dev, 'bala') except NetlinkError: pass assert len(self.ip.link_lookup(ifname='bala')) == 1 try: self.ip.link_rename(dev, self.dev) except NetlinkError: pass assert len(self.ip.link_lookup(ifname=self.dev)) == 1 def test_rules(self): assert len(get_ip_rules('-4')) == \ len(self.ip.get_rules(socket.AF_INET)) assert len(get_ip_rules('-6')) == \ len(self.ip.get_rules(socket.AF_INET6)) def test_addr(self): assert len(get_ip_addr()) == len(self.ip.get_addr()) def test_links(self): assert len(get_ip_link()) == len(self.ip.get_links()) def test_one_link(self): lo = self.ip.get_links(1)[0] assert lo.get_attr('IFLA_IFNAME') == 'lo' def test_default_routes(self): assert len(get_ip_default_routes()) == \ len(self.ip.get_default_routes(family=socket.AF_INET, table=254)) def test_routes(self): assert len(get_ip_route()) == \ len(self.ip.get_routes(family=socket.AF_INET, table=255))