tools: ynl-gen: sanitize notification tracking
Don't modify the raw dicts (as loaded from YAML) to pretend
that the notify attributes also exist on the ops. This makes
the code easier to follow.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py
index 9f7ad87..623c570 100644
--- a/tools/net/ynl/lib/nlspec.py
+++ b/tools/net/ynl/lib/nlspec.py
@@ -329,8 +329,8 @@
attr_sets dict of attribute sets
msgs dict of all messages (index by name)
- msgs_by_value dict of all messages (indexed by name)
ops dict of all valid requests / responses
+ ntfs dict of all async events
consts dict of all constants/enums
fixed_header string, optional name of family default fixed header struct
"""
@@ -370,6 +370,7 @@
self.req_by_value = collections.OrderedDict()
self.rsp_by_value = collections.OrderedDict()
self.ops = collections.OrderedDict()
+ self.ntfs = collections.OrderedDict()
self.consts = collections.OrderedDict()
last_exception = None
@@ -491,3 +492,5 @@
self.rsp_by_value[op.rsp_value] = op
if not op.is_async and 'attribute-set' in op:
self.ops[op.name] = op
+ elif op.is_async:
+ self.ntfs[op.name] = op
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
index f884179..a230598 100755
--- a/tools/net/ynl/ynl-gen-c.py
+++ b/tools/net/ynl/ynl-gen-c.py
@@ -714,6 +714,8 @@
self.dual_policy = ('do' in yaml and 'request' in yaml['do']) and \
('dump' in yaml and 'request' in yaml['dump'])
+ self.has_ntf = False
+
# Added by resolve:
self.enum_name = None
delattr(self, "enum_name")
@@ -726,12 +728,8 @@
else:
self.enum_name = self.family.async_op_prefix + c_upper(self.name)
- def add_notification(self, op):
- if 'notify' not in self.yaml:
- self.yaml['notify'] = dict()
- self.yaml['notify']['reply'] = self.yaml['do']['reply']
- self.yaml['notify']['cmds'] = []
- self.yaml['notify']['cmds'].append(op)
+ def mark_has_ntf(self):
+ self.has_ntf = True
class Family(SpecFamily):
@@ -793,14 +791,12 @@
self.root_sets = dict()
# dict space-name -> set('request', 'reply')
self.pure_nested_structs = dict()
- self.all_notify = dict()
+ self._mark_notify()
self._mock_up_events()
- self._dictify()
self._load_root_sets()
self._load_nested_sets()
- self._load_all_notify()
self._load_hooks()
self.kernel_policy = self.yaml.get('kernel-policy', 'split')
@@ -816,6 +812,11 @@
def new_operation(self, elem, req_value, rsp_value):
return Operation(self, elem, req_value, rsp_value)
+ def _mark_notify(self):
+ for op in self.msgs.values():
+ if 'notify' in op:
+ self.ops[op['notify']].mark_has_ntf()
+
# Fake a 'do' equivalent of all events, so that we can render their response parsing
def _mock_up_events(self):
for op in self.yaml['operations']['list']:
@@ -826,14 +827,6 @@
}
}
- def _dictify(self):
- ntf = []
- for msg in self.msgs.values():
- if 'notify' in msg:
- ntf.append(msg)
- for n in ntf:
- self.ops[n['notify']].add_notification(n)
-
def _load_root_sets(self):
for op_name, op in self.ops.items():
if 'attribute-set' not in op:
@@ -922,14 +915,6 @@
child.request |= struct.request
child.reply |= struct.reply
- def _load_all_notify(self):
- for op_name, op in self.ops.items():
- if not op:
- continue
-
- if 'notify' in op:
- self.all_notify[op_name] = op['notify']['cmds']
-
def _load_global_policy(self):
global_set = set()
attr_set_name = None
@@ -968,21 +953,15 @@
self.hooks[when][op_mode]['set'].add(name)
self.hooks[when][op_mode]['list'].append(name)
- def has_notifications(self):
- for op in self.ops.values():
- if 'notify' in op or 'event' in op:
- return True
- return False
-
class RenderInfo:
def __init__(self, cw, family, ku_space, op, op_name, op_mode, attr_set=None):
self.family = family
self.nl = cw.nlib
self.ku_space = ku_space
+ self.op_mode = op_mode
self.op = op
self.op_name = op_name
- self.op_mode = op_mode
# 'do' and 'dump' response parsing is identical
self.type_consistent = True
@@ -1004,6 +983,8 @@
self.cw = cw
self.struct = dict()
+ if op_mode == 'notify':
+ op_mode = 'do'
for op_dir in ['request', 'reply']:
if op and op_dir in op[op_mode]:
self.struct[op_dir] = Struct(family, self.attr_set,
@@ -2209,14 +2190,14 @@
cw.p(f'extern {symbol};')
return
- ntf = family.has_notifications()
- if ntf:
+ if family.ntfs:
cw.block_start(line=f"static const struct ynl_ntf_info {family['name']}_ntf_info[] = ")
- for ntf_op in sorted(family.all_notify.keys()):
- op = family.ops[ntf_op]
- ri = RenderInfo(cw, family, "user", op, ntf_op, "notify")
- for ntf in op['notify']['cmds']:
- _render_user_ntf_entry(ri, ntf)
+ for ntf_op_name, ntf_op in family.ntfs.items():
+ if 'notify' not in ntf_op:
+ continue
+ op = family.ops[ntf_op['notify']]
+ ri = RenderInfo(cw, family, "user", op, op.name, "notify")
+ _render_user_ntf_entry(ri, ntf_op)
for op_name, op in family.ops.items():
if 'event' not in op:
continue
@@ -2227,7 +2208,7 @@
cw.block_start(f'{symbol} = ')
cw.p(f'.name\t\t= "{family.name}",')
- if ntf:
+ if family.ntfs:
cw.p(f".ntf_info\t= {family['name']}_ntf_info,")
cw.p(f".ntf_info_size\t= MNL_ARRAY_SIZE({family['name']}_ntf_info),")
cw.block_end(line=';')
@@ -2436,7 +2417,7 @@
print_dump_prototype(ri)
cw.nl()
- if 'notify' in op:
+ if op.has_ntf:
cw.p(f"/* {op.enum_name} - notify */")
ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'notify')
if not ri.type_consistent:
@@ -2497,7 +2478,7 @@
print_dump(ri)
cw.nl()
- if 'notify' in op:
+ if op.has_ntf:
cw.p(f"/* {op.enum_name} - notify */")
ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'notify')
if not ri.type_consistent: