pyroute2
pyroute2 copied to clipboard
How to use poll/epoll to receive Netlink broadcast?
I saw these information in the Quickstart :
In the runtime pyroute2 socket objects behave as normal sockets. One can use them in the poll/select, one can call recv() and sendmsg():
from pyroute2 import IPRoute
# create RTNL socket
ipr = IPRoute()
# subscribe to broadcast messages
ipr.bind()
# wait for data (do not parse it)
data = ipr.recv(65535)
# parse received data
messages = ipr.marshal.parse(data)
# shortcut: recv() + parse()
#
# (under the hood is much more, but for
# simplicity it's enough to say so)
#
messages = ipr.get()
So I wrote a demo according to it:
from pyroute2 import IPRoute
if __name__ == '__main__':
# create RTNL socket
ipr = IPRoute()
# subscribe to broadcast messages
ipr.bind()
while True:
# wait for data (do not parse it)
data = ipr.recv(65535)
# parse received data
messages = ipr.marshal.parse(data)
# print message
for msg in messages:
print(msg)
I run this demo and found the script would be blocked at the line data = ipr.recv(65535)
.
So, I want to use poll/epoll method to get the messages asynchronously. But I have no idea how to write the codes?
I checkout some poll/epoll examples in Google. But I found all the examples are based on a socket object. I have no idea how can I get this socket object in Pyroute2. Here are some poll/epoll introduction I have found: https://pythontic.com/modules/select/poll https://blog.csdn.net/jialan75/article/details/122005874
Here we go:
import select
from pyroute2 import IPRoute
print('create poll object')
poll = select.poll()
print('create IPRoute object')
with IPRoute(nlm_generator=True) as ipr:
print('register IPRoute for select.POLLIN')
poll.register(ipr, select.POLLIN)
print('bind IPRoute to get broadcasts')
ipr.bind()
print('wait for input data')
poll.poll()
print('receive and parse; you can use ipr.recv() here or ipr.get()')
for msg in ipr.get():
print(msg)
The result:
$ python test.py
create poll object
create IPRoute object
register IPRoute for select.POLLIN
bind IPRoute to get broadcasts
wait for input data
receive and parse; you can use ipr.recv() here or ipr.get()
{'family': 0, '__align': (), 'ifi_type': 1, 'index': 2, 'flags': 69699, 'change': 0, 'attrs': [('IFLA_IFNAME', 'wlp3s0'), ('IFLA_WIRELESS', {'attrs': [('SIOCGIWSCAN', '00:00:00:00:00:00:00:00:00:00:00:00', 32768)]})], 'header': {'length': 64, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}, 'state': 'up', 'event': 'RTM_NEWLINK'}
Since NetlinkSocket
objects behave (or pretend to behave) like a normal socket, so they have .fileno()
and may be used for poll/select.
Explanation about nlm_generator
see here: https://github.com/svinota/pyroute2/discussions/972
@svinota Thanks! I will try it!