Skip to content

Commit

Permalink
tools: ynl: allow setting recv() size
Browse files Browse the repository at this point in the history
Make the size of the buffer we use for recv() configurable.
The details of the buffer sizing in netlink are somewhat
arcane, we could spend a lot of time polishing this API.
Let's just leave some hopefully helpful comments for now.
This is a for-developers-only feature, anyway.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jakub Kicinski authored and David S. Miller committed Mar 6, 2024
1 parent 7df7231 commit 7c93a88
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions tools/net/ynl/lib/ynl.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ def __str__(self):
return f"Netlink error: {os.strerror(-self.nl_msg.error)}\n{self.nl_msg}"


class ConfigError(Exception):
pass


class NlAttr:
ScalarFormat = namedtuple('ScalarFormat', ['native', 'big', 'little'])
type_formats = {
Expand Down Expand Up @@ -400,7 +404,8 @@ def lookup(self, name):


class YnlFamily(SpecFamily):
def __init__(self, def_path, schema=None, process_unknown=False):
def __init__(self, def_path, schema=None, process_unknown=False,
recv_size=0):
super().__init__(def_path, schema)

self.include_raw = False
Expand All @@ -415,6 +420,16 @@ def __init__(self, def_path, schema=None, process_unknown=False):
except KeyError:
raise Exception(f"Family '{self.yaml['name']}' not supported by the kernel")

# Note that netlink will use conservative (min) message size for
# the first dump recv() on the socket, our setting will only matter
# from the second recv() on.
self._recv_size = recv_size if recv_size else 131072
# Netlink will always allocate at least PAGE_SIZE - sizeof(skb_shinfo)
# for a message, so smaller receive sizes will lead to truncation.
# Note that the min size for other families may be larger than 4k!
if self._recv_size < 4000:
raise ConfigError()

self.sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, self.nlproto.proto_num)
self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1)
self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_EXT_ACK, 1)
Expand Down Expand Up @@ -799,7 +814,7 @@ def handle_ntf(self, decoded):
def check_ntf(self):
while True:
try:
reply = self.sock.recv(128 * 1024, socket.MSG_DONTWAIT)
reply = self.sock.recv(self._recv_size, socket.MSG_DONTWAIT)
except BlockingIOError:
return

Expand Down Expand Up @@ -854,7 +869,7 @@ def _op(self, method, vals, flags=None, dump=False):
done = False
rsp = []
while not done:
reply = self.sock.recv(128 * 1024)
reply = self.sock.recv(self._recv_size)
nms = NlMsgs(reply, attr_space=op.attr_set)
for nl_msg in nms:
if nl_msg.extack:
Expand Down

0 comments on commit 7c93a88

Please sign in to comment.