pyroute2 icon indicating copy to clipboard operation
pyroute2 copied to clipboard

exception - queue full in nlsocket - async_recv()

Open laplasz opened this issue 2 years ago • 4 comments

example code:

with IPRoute() as ipr: # With IPRoute objects you have to call bind() manually ipr.bind(async_cache=True) while True: try: for message in ipr.get(): <....> except OSError as e: raise e

callstack: for message in ipr.get(): File "/usr/local/lib/python3.9/site-packages/pr2modules/netlink/nlsocket.py", line 394, in get return tuple(self._genlm_get(*argv, **kwarg)) File "/usr/local/lib/python3.9/site-packages/pr2modules/netlink/nlsocket.py", line 788, in get data = self.recv_ft(bufsize) File "/usr/local/lib/python3.9/site-packages/pr2modules/netlink/nlsocket.py", line 1067, in recv_plugin raise data_in File "/usr/local/lib/python3.9/site-packages/pr2modules/netlink/nlsocket.py", line 580, in async_recv self.buffer_queue.put_nowait(data) File "/usr/lib64/python3.9/queue.py", line 191, in put_nowait return self.put(item, block=False) File "/usr/lib64/python3.9/queue.py", line 137, in put raise Full

laplasz avatar Sep 28 '22 22:09 laplasz

Looks like the parser doesn't manage to handle the packet flow.

Possible solutions:

1. increase the buffer queue

from pyroute2 import config, IPRoute
config.async_qsize = X
ipr = IPRoute()

# or
from pyroute2 import IPRoute
ipr = IPRoute(async_qsize=X)

Where X is the queue max size, by default 4096. The socket uses 64K buffers for each recv_into(), so consider memory usage as well.

2. use a custom parser

IPRoute objects have .marshal to run parsers on incoming messages.

IPRoute.marshal.msg_map = {msg_type: parser}
IPRoute.marshal.seq_map = {sequence_number: parser}

More on parsers and how to run own implementations: https://docs.pyroute2.org/parser.html

svinota avatar Sep 29 '22 09:09 svinota

Looks like the parser doesn't manage to handle the packet flow.

Possible solutions:

1. increase the buffer queue

from pyroute2 import config, IPRoute
config.async_qsize = X
ipr = IPRoute()

# or
from pyroute2 import IPRoute
ipr = IPRoute(async_qsize=X)

Where X is the queue max size, by default 4096. The socket uses 64K buffers for each recv_into(), so consider memory usage as well.

2. use a custom parser

IPRoute objects have .marshal to run parsers on incoming messages.

IPRoute.marshal.msg_map = {msg_type: parser}
IPRoute.marshal.seq_map = {sequence_number: parser}

More on parsers and how to run own implementations: https://docs.pyroute2.org/parser.html

As I understand this could happen due to temporal event storm, in which case the parser will lose pace against the socket reader, and the queue will get full. Is there a way to somehow instruct the API to restrict which events it should deliver via the socket?

LuiGuest avatar Sep 30 '22 12:09 LuiGuest

@LuiGuest there are three ways setting up that:

  1. Using groups -- ipr.bind(groups=...), see pyroute2.netlink.rtnl.RTMGRP_* (becomes deprecated in the Linux kernel, but still used by default in the library)
  2. Using membership -- ipr.add_membership(...) / ipr.drop_membership(...), see pyroute2.netlink.rtnl.RTNLGRP_*
  3. Using custom parsers and assigning to particular message types (ipr.marshal.msg_map) or sequence numbers (ipr.marshal.seq_map)

...

  1. and 2. will instruct the kernel not to send some message types, while 3. makes pyroute2 to drop received messages w/o parsing them (by the default parser)

svinota avatar Sep 30 '22 13:09 svinota

  1. RTMGRP_

Thank You a lot for your help!

LuiGuest avatar Sep 30 '22 15:09 LuiGuest