diff options
Diffstat (limited to 'tools/net/ynl/lib/nlspec.py')
| -rw-r--r-- | tools/net/ynl/lib/nlspec.py | 91 | 
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 | 
