summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2024-11-15 05:09:08 +0300
committerJakub Kicinski <kuba@kernel.org>2024-11-15 05:09:08 +0300
commit59b6c043da0bb12631cf4e84e0be58727c0eab17 (patch)
tree524f0b3b6b7d50d38898f3f8fcf5e1fe4ce3286f
parent76e81a5a1749e638a09b424641f0b9d3ece1f2a7 (diff)
parent8aefcfa04beaab070a2009828da40bdd4888eee6 (diff)
downloadlinux-59b6c043da0bb12631cf4e84e0be58727c0eab17.tar.xz
Merge branch 'tools-net-ynl-rework-async-notification-handling'
Donald Hunter says: ==================== tools/net/ynl: rework async notification handling Revert patch 1bf70e6c3a53 which modified check_ntf() and instead add a new poll_ntf() with async notification semantics. See patch 2 for a detailed description. ==================== Link: https://patch.msgid.link/20241113090843.72917-1-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rwxr-xr-xtools/net/ynl/cli.py20
-rw-r--r--tools/net/ynl/lib/ynl.py57
2 files changed, 44 insertions, 33 deletions
diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/cli.py
index 5e2913a7f3e4..41d9fa5c818d 100755
--- a/tools/net/ynl/cli.py
+++ b/tools/net/ynl/cli.py
@@ -6,8 +6,6 @@ import json
import pathlib
import pprint
import sys
-import time
-import signal
sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
from lib import YnlFamily, Netlink, NlError
@@ -21,8 +19,6 @@ class YnlEncoder(json.JSONEncoder):
return list(obj)
return json.JSONEncoder.default(self, obj)
-def handle_timeout(sig, frame):
- exit(0)
def main():
description = """
@@ -49,7 +45,10 @@ def main():
group.add_argument('--list-ops', action='store_true')
group.add_argument('--list-msgs', action='store_true')
- parser.add_argument('--sleep', dest='sleep', type=int)
+ parser.add_argument('--duration', dest='duration', type=int,
+ help='when subscribed, watch for DURATION seconds')
+ parser.add_argument('--sleep', dest='duration', type=int,
+ help='alias for duration')
parser.add_argument('--subscribe', dest='ntf', type=str)
parser.add_argument('--replace', dest='flags', action='append_const',
const=Netlink.NLM_F_REPLACE)
@@ -86,10 +85,6 @@ def main():
if args.ntf:
ynl.ntf_subscribe(args.ntf)
- if args.sleep:
- signal.signal(signal.SIGALRM, handle_timeout)
- signal.alarm(args.sleep)
-
if args.list_ops:
for op_name, op in ynl.ops.items():
print(op_name, " [", ", ".join(op.modes), "]")
@@ -113,8 +108,11 @@ def main():
exit(1)
if args.ntf:
- for msg in ynl.check_ntf():
- output(msg)
+ try:
+ for msg in ynl.poll_ntf(duration=args.duration):
+ output(msg)
+ except KeyboardInterrupt:
+ pass
if __name__ == "__main__":
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index 92f85698c50e..01ec01a90e76 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -13,6 +13,7 @@ import yaml
import ipaddress
import uuid
import queue
+import selectors
import time
from .nlspec import SpecFamily
@@ -907,37 +908,49 @@ class YnlFamily(SpecFamily):
msg['msg'] = attrs
self.async_msg_queue.put(msg)
- def check_ntf(self, interval=0.1):
+ def check_ntf(self):
while True:
try:
reply = self.sock.recv(self._recv_size, socket.MSG_DONTWAIT)
- nms = NlMsgs(reply)
- self._recv_dbg_print(reply, nms)
- for nl_msg in nms:
- if nl_msg.error:
- print("Netlink error in ntf!?", os.strerror(-nl_msg.error))
- print(nl_msg)
- continue
- if nl_msg.done:
- print("Netlink done while checking for ntf!?")
- continue
+ except BlockingIOError:
+ return
- decoded = self.nlproto.decode(self, nl_msg, None)
- if decoded.cmd() not in self.async_msg_ids:
- print("Unexpected msg id while checking for ntf", decoded)
- continue
+ nms = NlMsgs(reply)
+ self._recv_dbg_print(reply, nms)
+ for nl_msg in nms:
+ if nl_msg.error:
+ print("Netlink error in ntf!?", os.strerror(-nl_msg.error))
+ print(nl_msg)
+ continue
+ if nl_msg.done:
+ print("Netlink done while checking for ntf!?")
+ continue
- self.handle_ntf(decoded)
- except BlockingIOError:
- pass
+ decoded = self.nlproto.decode(self, nl_msg, None)
+ if decoded.cmd() not in self.async_msg_ids:
+ print("Unexpected msg id while checking for ntf", decoded)
+ continue
+
+ self.handle_ntf(decoded)
+ def poll_ntf(self, duration=None):
+ start_time = time.time()
+ selector = selectors.DefaultSelector()
+ selector.register(self.sock, selectors.EVENT_READ)
+
+ while True:
try:
yield self.async_msg_queue.get_nowait()
except queue.Empty:
- try:
- time.sleep(interval)
- except KeyboardInterrupt:
- return
+ if duration is not None:
+ timeout = start_time + duration - time.time()
+ if timeout <= 0:
+ return
+ else:
+ timeout = None
+ events = selector.select(timeout)
+ if events:
+ self.check_ntf()
def operation_do_attributes(self, name):
"""