Merge branch 'tools-ynl-decode-link-types-present-in-tests'

Jakub Kicinski says:

====================
tools: ynl: decode link types present in tests

Using a kernel built for the net selftest target to run drivers/net
tests currently fails, because the net kernel automatically spawns
a handful of tunnel devices which YNL can't decode.

Fill in those missing link types in rt_link. We need to extend subset
support a bit for it to work.

v1: https://lore.kernel.org/20250105012523.1722231-1-kuba@kernel.org
====================

Link: https://patch.msgid.link/20250107022820.2087101-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-01-07 18:07:55 -08:00
commit acafa84ff3
4 changed files with 151 additions and 39 deletions

View File

@ -1825,6 +1825,48 @@ attribute-sets:
-
name: erspan-hwid
type: u16
-
name: linkinfo-vti-attrs
name-prefix: ifla-vti-
attributes:
-
name: link
type: u32
-
name: ikey
type: u32
-
name: okey
type: u32
-
name: local
type: binary
display-hint: ipv4
-
name: remote
type: binary
display-hint: ipv4
-
name: fwmark
type: u32
-
name: linkinfo-vti6-attrs
subset-of: linkinfo-vti-attrs
attributes:
-
name: link
-
name: ikey
-
name: okey
-
name: local
display-hint: ipv6
-
name: remote
display-hint: ipv6
-
name: fwmark
-
name: linkinfo-geneve-attrs
name-prefix: ifla-geneve-
@ -1941,6 +1983,42 @@ attribute-sets:
-
name: fwmark
type: u32
-
name: linkinfo-ip6tnl-attrs
subset-of: linkinfo-iptun-attrs
attributes:
-
name: link
-
name: local
display-hint: ipv6
-
name: remote
display-hint: ipv6
-
name: ttl
-
name: encap-limit
-
name: flowinfo
-
name: flags
# ip6tnl unlike ipip and sit has 32b flags
type: u32
-
name: proto
-
name: encap-type
-
name: encap-flags
-
name: encap-sport
-
name: encap-dport
-
name: collect-metadata
-
name: fwmark
-
name: linkinfo-tun-attrs
name-prefix: ifla-tun-
@ -2201,6 +2279,9 @@ sub-messages:
-
value: ipip
attribute-set: linkinfo-iptun-attrs
-
value: ip6tnl
attribute-set: linkinfo-ip6tnl-attrs
-
value: sit
attribute-set: linkinfo-iptun-attrs
@ -2213,6 +2294,12 @@ sub-messages:
-
value: vrf
attribute-set: linkinfo-vrf-attrs
-
value: vti
attribute-set: linkinfo-vti-attrs
-
value: vti6
attribute-set: linkinfo-vti6-attrs
-
value: netkit
attribute-set: linkinfo-netkit-attrs

View File

@ -219,7 +219,10 @@ class SpecAttrSet(SpecElement):
else:
real_set = family.attr_sets[self.subset_of]
for elem in self.yaml['attributes']:
attr = real_set[elem['name']]
real_attr = real_set[elem['name']]
combined_elem = real_attr.yaml | elem
attr = self.new_attr(combined_elem, real_attr.value)
self.attrs[attr.name] = attr
self.attrs_by_val[attr.value] = attr

View File

@ -733,41 +733,45 @@ class YnlFamily(SpecFamily):
self._rsp_add(rsp, attr_name, None, self._decode_unknown(attr))
continue
if attr_spec["type"] == 'nest':
subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs)
decoded = subdict
elif attr_spec["type"] == 'string':
decoded = attr.as_strz()
elif attr_spec["type"] == 'binary':
decoded = self._decode_binary(attr, attr_spec)
elif attr_spec["type"] == 'flag':
decoded = True
elif attr_spec.is_auto_scalar:
decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order)
elif attr_spec["type"] in NlAttr.type_formats:
decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
if 'enum' in attr_spec:
decoded = self._decode_enum(decoded, attr_spec)
elif attr_spec.display_hint:
decoded = self._formatted_string(decoded, attr_spec.display_hint)
elif attr_spec["type"] == 'indexed-array':
decoded = self._decode_array_attr(attr, attr_spec)
elif attr_spec["type"] == 'bitfield32':
value, selector = struct.unpack("II", attr.raw)
if 'enum' in attr_spec:
value = self._decode_enum(value, attr_spec)
selector = self._decode_enum(selector, attr_spec)
decoded = {"value": value, "selector": selector}
elif attr_spec["type"] == 'sub-message':
decoded = self._decode_sub_msg(attr, attr_spec, search_attrs)
elif attr_spec["type"] == 'nest-type-value':
decoded = self._decode_nest_type_value(attr, attr_spec)
else:
if not self.process_unknown:
raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
decoded = self._decode_unknown(attr)
try:
if attr_spec["type"] == 'nest':
subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs)
decoded = subdict
elif attr_spec["type"] == 'string':
decoded = attr.as_strz()
elif attr_spec["type"] == 'binary':
decoded = self._decode_binary(attr, attr_spec)
elif attr_spec["type"] == 'flag':
decoded = True
elif attr_spec.is_auto_scalar:
decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order)
elif attr_spec["type"] in NlAttr.type_formats:
decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
if 'enum' in attr_spec:
decoded = self._decode_enum(decoded, attr_spec)
elif attr_spec.display_hint:
decoded = self._formatted_string(decoded, attr_spec.display_hint)
elif attr_spec["type"] == 'indexed-array':
decoded = self._decode_array_attr(attr, attr_spec)
elif attr_spec["type"] == 'bitfield32':
value, selector = struct.unpack("II", attr.raw)
if 'enum' in attr_spec:
value = self._decode_enum(value, attr_spec)
selector = self._decode_enum(selector, attr_spec)
decoded = {"value": value, "selector": selector}
elif attr_spec["type"] == 'sub-message':
decoded = self._decode_sub_msg(attr, attr_spec, search_attrs)
elif attr_spec["type"] == 'nest-type-value':
decoded = self._decode_nest_type_value(attr, attr_spec)
else:
if not self.process_unknown:
raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
decoded = self._decode_unknown(attr)
self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
except:
print(f"Error decoding '{attr_spec.name}' from '{space}'")
raise
return rsp

View File

@ -79,6 +79,20 @@ class Type(SpecAttr):
self.enum_name = None
delattr(self, "enum_name")
def _get_real_attr(self):
# if the attr is for a subset return the "real" attr (just one down, does not recurse)
return self.family.attr_sets[self.attr_set.subset_of][self.name]
def set_request(self):
self.request = True
if self.attr_set.subset_of:
self._get_real_attr().set_request()
def set_reply(self):
self.reply = True
if self.attr_set.subset_of:
self._get_real_attr().set_reply()
def get_limit(self, limit, default=None):
value = self.checks.get(limit, default)
if value is None:
@ -106,6 +120,10 @@ class Type(SpecAttr):
enum_name = f"{self.attr_set.name_prefix}{self.name}"
self.enum_name = c_upper(enum_name)
if self.attr_set.subset_of:
if self.checks != self._get_real_attr().checks:
raise Exception("Overriding checks not supported by codegen, yet")
def is_multi_val(self):
return None
@ -1119,17 +1137,17 @@ class Family(SpecFamily):
for _, struct in self.pure_nested_structs.items():
if struct.request:
for _, arg in struct.member_list():
arg.request = True
arg.set_request()
if struct.reply:
for _, arg in struct.member_list():
arg.reply = True
arg.set_reply()
for root_set, rs_members in self.root_sets.items():
for attr, spec in self.attr_sets[root_set].items():
if attr in rs_members['request']:
spec.request = True
spec.set_request()
if attr in rs_members['reply']:
spec.reply = True
spec.set_reply()
def _load_global_policy(self):
global_set = set()