summaryrefslogtreecommitdiff
path: root/tools/net/ynl/lib/nlspec.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/net/ynl/lib/nlspec.py')
-rw-r--r--tools/net/ynl/lib/nlspec.py91
1 files changed, 77 insertions, 14 deletions
diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/lib/nlspec.py
index d04450c2a44a..a0241add3839 100644
--- a/tools/net/ynl/lib/nlspec.py
+++ b/tools/net/ynl/lib/nlspec.py
@@ -90,8 +90,8 @@ class SpecEnumEntry(SpecElement):
def raw_value(self):
return self.value
- def user_value(self):
- if self.enum_set['type'] == 'flags':
+ def user_value(self, as_flags=None):
+ if self.enum_set['type'] == 'flags' or as_flags:
return 1 << self.value
else:
return self.value
@@ -136,10 +136,10 @@ class SpecEnumSet(SpecElement):
return True
return False
- def get_mask(self):
+ def get_mask(self, as_flags=None):
mask = 0
for e in self.entries.values():
- mask += e.user_value()
+ mask += e.user_value(as_flags)
return mask
@@ -149,8 +149,11 @@ class SpecAttr(SpecElement):
Represents a single attribute type within an attr space.
Attributes:
- value numerical ID when serialized
- attr_set Attribute Set containing this attr
+ value numerical ID when serialized
+ attr_set Attribute Set containing this attr
+ is_multi bool, attr may repeat multiple times
+ struct_name string, name of struct definition
+ sub_type string, name of sub type
"""
def __init__(self, family, attr_set, yaml, value):
super().__init__(family, yaml)
@@ -158,6 +161,9 @@ class SpecAttr(SpecElement):
self.value = value
self.attr_set = attr_set
self.is_multi = yaml.get('multi-attr', False)
+ self.struct_name = yaml.get('struct')
+ self.sub_type = yaml.get('sub-type')
+ self.byte_order = yaml.get('byte-order')
class SpecAttrSet(SpecElement):
@@ -214,22 +220,61 @@ class SpecAttrSet(SpecElement):
return self.attrs.items()
+class SpecStructMember(SpecElement):
+ """Struct member attribute
+
+ Represents a single struct member attribute.
+
+ Attributes:
+ type string, type of the member attribute
+ """
+ def __init__(self, family, yaml):
+ super().__init__(family, yaml)
+ self.type = yaml['type']
+
+
+class SpecStruct(SpecElement):
+ """Netlink struct type
+
+ Represents a C struct definition.
+
+ Attributes:
+ members ordered list of struct members
+ """
+ def __init__(self, family, yaml):
+ super().__init__(family, yaml)
+
+ self.members = []
+ for member in yaml.get('members', []):
+ self.members.append(self.new_member(family, member))
+
+ def new_member(self, family, elem):
+ return SpecStructMember(family, elem)
+
+ def __iter__(self):
+ yield from self.members
+
+ def items(self):
+ return self.members.items()
+
+
class SpecOperation(SpecElement):
"""Netlink Operation
Information about a single Netlink operation.
Attributes:
- value numerical ID when serialized, None if req/rsp values differ
+ value numerical ID when serialized, None if req/rsp values differ
- req_value numerical ID when serialized, user -> kernel
- rsp_value numerical ID when serialized, user <- kernel
- is_call bool, whether the operation is a call
- is_async bool, whether the operation is a notification
- is_resv bool, whether the operation does not exist (it's just a reserved ID)
- attr_set attribute set name
+ req_value numerical ID when serialized, user -> kernel
+ rsp_value numerical ID when serialized, user <- kernel
+ is_call bool, whether the operation is a call
+ is_async bool, whether the operation is a notification
+ is_resv bool, whether the operation does not exist (it's just a reserved ID)
+ attr_set attribute set name
+ fixed_header string, optional name of fixed header struct
- yaml raw spec as loaded from the spec file
+ yaml raw spec as loaded from the spec file
"""
def __init__(self, family, yaml, req_value, rsp_value):
super().__init__(family, yaml)
@@ -241,6 +286,7 @@ class SpecOperation(SpecElement):
self.is_call = 'do' in yaml or 'dump' in yaml
self.is_async = 'notify' in yaml or 'event' in yaml
self.is_resv = not self.is_async and not self.is_call
+ self.fixed_header = self.yaml.get('fixed-header', family.fixed_header)
# Added by resolve:
self.attr_set = None
@@ -281,6 +327,7 @@ class SpecFamily(SpecElement):
msgs_by_value dict of all messages (indexed by name)
ops dict of all valid requests / responses
consts dict of all constants/enums
+ fixed_header string, optional name of family default fixed header struct
"""
def __init__(self, spec_path, schema_path=None):
with open(spec_path, "r") as stream:
@@ -344,6 +391,9 @@ class SpecFamily(SpecElement):
def new_attr_set(self, elem):
return SpecAttrSet(self, elem)
+ def new_struct(self, elem):
+ return SpecStruct(self, elem)
+
def new_operation(self, elem, req_val, rsp_val):
return SpecOperation(self, elem, req_val, rsp_val)
@@ -351,6 +401,7 @@ class SpecFamily(SpecElement):
self._resolution_list.append(elem)
def _dictify_ops_unified(self):
+ self.fixed_header = self.yaml['operations'].get('fixed-header')
val = 1
for elem in self.yaml['operations']['list']:
if 'value' in elem:
@@ -362,6 +413,7 @@ class SpecFamily(SpecElement):
self.msgs[op.name] = op
def _dictify_ops_directional(self):
+ self.fixed_header = self.yaml['operations'].get('fixed-header')
req_val = rsp_val = 1
for elem in self.yaml['operations']['list']:
if 'notify' in elem:
@@ -392,6 +444,15 @@ class SpecFamily(SpecElement):
self.msgs[op.name] = op
+ def find_operation(self, name):
+ """
+ For a given operation name, find and return operation spec.
+ """
+ for op in self.yaml['operations']['list']:
+ if name == op['name']:
+ return op
+ return None
+
def resolve(self):
self.resolve_up(super())
@@ -399,6 +460,8 @@ class SpecFamily(SpecElement):
for elem in definitions:
if elem['type'] == 'enum' or elem['type'] == 'flags':
self.consts[elem['name']] = self.new_enum(elem)
+ elif elem['type'] == 'struct':
+ self.consts[elem['name']] = self.new_struct(elem)
else:
self.consts[elem['name']] = elem