IPDB module

Basically, IPDB is a transactional database, containing records, representing network stack objects. Any change in the database is not reflected immediately in OS (unless you ask for that explicitly), but waits until commit() is called.

quickstart

Simple tutorial:

from pyroute2 import IPDB
# several IPDB instances are supported within on process
ip = IPDB()

# commit is called automatically upon the exit from `with`
# statement
with ip.interfaces.eth0 as i:
    i.address = '00:11:22:33:44:55'
    i.ifname = 'bala'
    i.txqlen = 2000

# basic routing support
ip.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit()

IPDB uses IPRoute as a transport, and monitors all broadcast netlink messages from the kernel, thus keeping the database up-to-date in an asynchronous manner. IPDB inherits dict class, and has two keys:

>>> from pyroute2 import IPDB
>>> ip = IPDB()
>>> ip.by_name.keys()
['bond0', 'lo', 'em1', 'wlan0', 'dummy0', 'virbr0-nic', 'virbr0']
>>> ip.by_index.keys()
[32, 1, 2, 3, 4, 5, 8]
>>> ip.interfaces.keys()
[32,
 1,
 2,
 3,
 4,
 5,
 8,
 'lo',
 'em1',
 'wlan0',
 'bond0',
 'dummy0',
 'virbr0-nic',
 'virbr0']
>>> ip.interfaces['em1']['address']
'f0:de:f1:93:94:0d'
>>> ip.interfaces['em1']['ipaddr']
[('10.34.131.210', 23),
 ('2620:52:0:2282:f2de:f1ff:fe93:940d', 64),
 ('fe80::f2de:f1ff:fe93:940d', 64)]
>>>

One can address objects in IPDB not only with dict notation, but with dot notation also:

>>> ip.interfaces.em1.address
'f0:de:f1:93:94:0d'
>>> ip.interfaces.em1.ipaddr
[('10.34.131.210', 23),
 ('2620:52:0:2282:f2de:f1ff:fe93:940d', 64),
 ('fe80::f2de:f1ff:fe93:940d', 64)]
```

It is up to you, which way to choose. The former, being more flexible, is better for developers, the latter, the shorter form – for system administrators.

The library has also IPDB module. It is a database synchronized with the kernel, containing some of the information. It can be used also to set up IP settings in a transactional manner:

>>> from pyroute2 import IPDB
>>> from pprint import pprint
>>> ip = IPDB()
>>> pprint(ip.by_name.keys())
['bond0',
 'lo',
 'vnet0',
 'em1',
 'wlan0',
 'macvtap0',
 'dummy0',
 'virbr0-nic',
 'virbr0']
>>> ip.interfaces.lo
{'promiscuity': 0,
 'operstate': 'UNKNOWN',
 'qdisc': 'noqueue',
 'group': 0,
 'family': 0,
 'index': 1,
 'linkmode': 0,
 'ipaddr': [('127.0.0.1', 8), ('::1', 128)],
 'mtu': 65536,
 'broadcast': '00:00:00:00:00:00',
 'num_rx_queues': 1,
 'txqlen': 0,
 'ifi_type': 772,
 'address': '00:00:00:00:00:00',
 'flags': 65609,
 'ifname': 'lo',
 'num_tx_queues': 1,
 'ports': [],
 'change': 0}
>>>

transaction modes

IPDB has several operating modes:

  • ‘direct’ – any change goes immediately to the OS level
  • ‘implicit’ (default) – the first change starts an implicit transaction, that have to be committed
  • ‘explicit’ – you have to begin() a transaction prior to make any change
  • ‘snapshot’ – no changes will go to the OS in any case

The default is to use implicit transaction. This behaviour can be changed in the future, so use ‘mode’ argument when creating IPDB instances.

The sample session with explicit transactions:

In [1]: from pyroute2 import IPDB
In [2]: ip = IPDB(mode='explicit')
In [3]: ifdb = ip.interfaces
In [4]: ifdb.tap0.begin()
    Out[3]: UUID('7a637a44-8935-4395-b5e7-0ce40d31d937')
In [5]: ifdb.tap0.up()
In [6]: ifdb.tap0.address = '00:11:22:33:44:55'
In [7]: ifdb.tap0.add_ip('10.0.0.1', 24)
In [8]: ifdb.tap0.add_ip('10.0.0.2', 24)
In [9]: ifdb.tap0.review()
    Out[8]:
    {'+ipaddr': set([('10.0.0.2', 24), ('10.0.0.1', 24)]),
     '-ipaddr': set([]),
     'address': '00:11:22:33:44:55',
     'flags': 4099}
In [10]: ifdb.tap0.commit()

Note, that you can review() the last() transaction, and commit() or drop() it. Also, multiple self._transactions are supported, use uuid returned by begin() to identify them.

Actually, the form like ‘ip.tap0.address’ is an eye-candy. The IPDB objects are dictionaries, so you can write the code above as that:

ip.interfaces['tap0'].down()
ip.interfaces['tap0']['address'] = '00:11:22:33:44:55'
...

context managers

Also, interface objects in transactional mode can operate as context managers:

with ip.interfaces.tap0 as i:
    i.address = '00:11:22:33:44:55'
    i.ifname = 'vpn'
    i.add_ip('10.0.0.1', 24)
    i.add_ip('10.0.0.1', 24)

On exit, the context manager will authomatically commit() the transaction.

interface creation

IPDB can also create interfaces:

with ip.create(kind='bridge', ifname='control') as i:
    i.add_port(ip.interfaces.eth1)
    i.add_port(ip.interfaces.eth2)
    i.add_ip('10.0.0.1/24')  # the same as i.add_ip('10.0.0.1', 24)

Right now IPDB supports creation of dummy, bond, bridge and vlan interfaces. VLAN creation requires also link and vlan_id parameters, see example scripts.

class pyroute2.ipdb.CBRequest(*argv, **kwarg)

FIXME

class pyroute2.ipdb.IPDB(nl=None, host=None, mode='implicit', key=None, cert=None, ca=None, iclass=<class 'pyroute2.ipdb.Interface'>, fork=False)

The class that maintains information about network setup of the host. Monitoring netlink events allows it to react immediately. It uses no polling.

create(kind, ifname, reuse=False, **kwarg)

Create an interface. Arguments ‘kind’ and ‘ifname’ are required.

  • kind – interface type, can be of: * bridge * bond * vlan * tun * dummy
  • ifname – interface name
  • reuse – if such interface exists, return it anyway

Different interface kinds can require different arguments for creation.

FIXME: this should be documented.

register_callback(callback, mode='post')

IPDB callbacks are routines executed on a RT netlink message arrival. There are two types of callbacks: “post” and “pre” callbacks.

...

“Post” callbacks are executed after the message is processed by IPDB and all corresponding objects are created or deleted. Using ipdb reference in “post” callbacks you will access the most up-to-date state of the IP database.

“Post” callbacks are executed asynchronously in separate threads. These threads can work as long as you want them to. Callback threads are joined occasionally, so for a short time there can exist stopped threads.

...

“Pre” callbacks are synchronous routines, executed before the message gets processed by IPDB. It gives you the way to patch arriving messages, but also places a restriction: until the callback exits, the main event IPDB loop is blocked.

Normally, only “post” callbacks are required. But in some specific cases “pre” also can be useful.

...

The routine, register_callback(), takes two arguments: 1. callback function 2. mode (optional, default=”post”)

The callback should be a routine, that accepts three arguments:

cb(ipdb, msg, action)
  1. ipdb is a reference to IPDB instance, that invokes the callback.
  2. msg is a message arrived
  3. action is just a msg[‘event’] field

E.g., to work on a new interface, you should catch action == ‘RTM_NEWLINK’ and with the interface index (arrived in msg[‘index’]) get it from IPDB:

index = msg['index']
interface = ipdb.interfaces[index]
release()

Shutdown monitoring thread and release iproute.

serve_forever()

Main monitoring cycle. It gets messages from the default iproute queue and updates objects in the database.

Note

Should not be called manually.

class pyroute2.ipdb.IPLinkRequest(obj=None)

Utility class, that converts human-readable dictionary into RTNL link request.

class pyroute2.ipdb.IPRouteRequest(obj=None)

Utility class, that converts human-readable dictionary into RTNL route request.

class pyroute2.ipdb.IPaddrSet(*argv, **kwarg)

LinkedSet child class with different target filter. The filter ignores link local IPv6 addresses when sets and checks the target.

class pyroute2.ipdb.Interface(ipdb, mode=None)

Objects of this class represent network interface and all related objects: * addresses * (todo) neighbors * (todo) routes

Interfaces provide transactional model and can act as context managers. Any attribute change implicitly starts a transaction. The transaction can be managed with three methods: * review() – review changes * rollback() – drop all the changes * commit() – try to apply changes

If anything will go wrong during transaction commit, it will be rolled back authomatically and an exception will be raised. Failed transaction review will be attached to the exception.

add_ip(*argv, **kwarg)

Add IP address to an interface

add_port(*argv, **kwarg)

Add a slave port to a bridge or bonding

commit(tid=None, transaction=None, rollback=False)

Commit transaction. In the case of exception all changes applied during commit will be reverted.

del_ip(*argv, **kwarg)

Delete IP address from an interface

del_port(*argv, **kwarg)

Remove a slave port from a bridge or bonding

down()

Shortcut: change the interface state to ‘down’.

if_master

[property] Link to the parent interface – if it exists

load_bond()
load_bridge()

Update the interface info from RTM_NEWLINK message.

This call always bypasses open transactions, loading changes directly into the interface data.

reload()

Reload interface information

remove()

Mark the interface for removal

shadow()

Remove the interface from the OS, but leave it in the database. When one will try to re-create interface with the same name, all the old saved attributes will apply to the new interface, incl. MAC-address and even the interface index. Please be aware, that the interface index can be reused by OS while the interface is “in the shadow state”, in this case re-creation will fail.

up()

Shortcut: change the interface state to ‘up’.

class pyroute2.ipdb.LinkedSet(*argv, **kwarg)

Utility class, used by Interface to track ip addresses and ports. Called “linked” as it automatically updates all instances, linked with it.

Target filter is a function, that returns True if a set member should be counted in target checks (target methods see below), or False if it should be ignored.

add(key, raw=None, cascade=False)

Add an item to the set and all connected instances, check the target state.

Args:
  • key: any hashable object
  • raw (optional): raw representation of the object

Raw representation is not required. It can be used, e.g., to store RTM_NEWADDR RTNL messages along with human-readable ip addr representation.

check_target()

Check the target state and set the target event in the case the state is reached. Called from mutators, add() and remove()

connect(link)

Connect a LinkedSet instance to this one. Connected sets will be updated together with this instance.

Do not ignore key on cascade updates.

remove(key, raw=None, cascade=False)

Remove an item from the set and all connected instances, check the target state.

set_target(value)

Set target state for the object and clear the target event. Once the target is reached, the event will be set, see also: check_target()

Args:
  • value (set): the target state to compare with

Exclude key from cascade updates.

class pyroute2.ipdb.Transactional(ipdb, mode=None)

Utility class that implements common transactional logic.

begin()

Start new transaction

drop(tid=None)

Drop a transaction.

last()

Return last open transaction

pick(detached=True)

Get a snapshot of the object. Can be of two types: * detached=True – (default) “true” snapshot * detached=False – keep ip addr set updated from OS

Please note, that “updated” doesn’t mean “in sync”. The reason behind this logic is that snapshots can be used as transactions.

review()

Review last open transaction

snapshot()

Create new snapshot

pyroute2.ipdb.get_addr_nla(msg)

Utility function to get NLA, containing the interface address.

Incosistency in Linux IP addressing scheme is that IPv4 uses IFA_LOCAL to store interface’s ip address, and IPv6 uses for the same IFA_ADDRESS.

IPv4 sets IFA_ADDRESS to == IFA_LOCAL or to a tunneling endpoint.

Args:
  • msg (nlmsg): RTM_.*ADDR message
Returns:
  • nla (nla): IFA_LOCAL for IPv4 and IFA_ADDRESS for IPv6
pyroute2.ipdb.get_interface_type(name)

Utility function to get interface type.

Unfortunately, we can not rely on RTNL or even ioctl(). RHEL doesn’t support interface type in RTNL and doesn’t provide extended (private) interface flags via ioctl().

Args:
  • name (str): interface name
Returns:
  • False – sysfs info unavailable

  • None – type not known

  • str – interface type:
    • ‘bond’
    • ‘bridge’

Table Of Contents

Previous topic

IPRoute module

Next topic

Remote netlink

This Page