Example #1
0
 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")
Example #2
0
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
Example #4
0
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()
Example #5
0
    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)
Example #6
0
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)
Example #7
0
 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()
Example #8
0
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()
Example #9
0
    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': {}}
Example #10
0
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
Example #11
0
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
Example #13
0
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()
Example #14
0
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)
Example #15
0
    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()
Example #16
0
        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)
Example #17
0
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()
Example #18
0
    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')
Example #19
0
    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')
Example #20
0
 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
Example #21
0
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
Example #22
0
    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
Example #23
0
 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
Example #24
0
 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")
Example #25
0
    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)
Example #26
0
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()
Example #27
0
    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()
Example #29
0
 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")
Example #30
0
 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")
Example #31
0
    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
Example #32
0
    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
Example #33
0
    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
Example #34
0
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)
Example #35
0
    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 = []
Example #36
0
    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
Example #37
0
    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
Example #38
0
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))
Example #39
0
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
Example #40
0
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
Example #42
0
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')
Example #43
0
    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
Example #44
0
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()
Example #46
0
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])
Example #47
0
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))
Example #48
0
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)
Example #49
0
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))
Example #50
0
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))