tools: ynl-gen: introduce support for bitfield32 attribute type
Introduce support for attribute type bitfield32. Note that since the generated code works with struct nla_bitfield32, the generator adds netlink.h to the list of includes for userspace headers in case any bitfield32 is present. Note that this is added only to genetlink-legacy scheme as requested by Jakub Kicinski. Signed-off-by: Jiri Pirko <jiri@nvidia.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://lore.kernel.org/r/20231021112711.660606-3-jiri@resnulli.us Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
f862ed2d0b
commit
4e2846fd66
@ -192,7 +192,7 @@ properties:
|
||||
type: string
|
||||
type: &attr-type
|
||||
description: The netlink attribute type
|
||||
enum: [ unused, pad, flag, binary,
|
||||
enum: [ unused, pad, flag, binary, bitfield32,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
doc:
|
||||
|
@ -182,7 +182,7 @@ members
|
||||
|
||||
- ``name`` - The attribute name of the struct member
|
||||
- ``type`` - One of the scalar types ``u8``, ``u16``, ``u32``, ``u64``, ``s8``,
|
||||
``s16``, ``s32``, ``s64``, ``string`` or ``binary``.
|
||||
``s16``, ``s32``, ``s64``, ``string``, ``binary`` or ``bitfield32``.
|
||||
- ``byte-order`` - ``big-endian`` or ``little-endian``
|
||||
- ``doc``, ``enum``, ``enum-as-flags``, ``display-hint`` - Same as for
|
||||
:ref:`attribute definitions <attribute_properties>`
|
||||
|
@ -379,6 +379,12 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
|
||||
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
|
||||
"Invalid attribute (string %s)", policy->name);
|
||||
return -1;
|
||||
case YNL_PT_BITFIELD32:
|
||||
if (len == sizeof(struct nla_bitfield32))
|
||||
break;
|
||||
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
|
||||
"Invalid attribute (bitfield32 %s)", policy->name);
|
||||
return -1;
|
||||
default:
|
||||
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
|
||||
"Invalid attribute (unknown %s)", policy->name);
|
||||
|
@ -135,6 +135,7 @@ enum ynl_policy_type {
|
||||
YNL_PT_U64,
|
||||
YNL_PT_UINT,
|
||||
YNL_PT_NUL_STR,
|
||||
YNL_PT_BITFIELD32,
|
||||
};
|
||||
|
||||
struct ynl_policy_attr {
|
||||
|
@ -478,6 +478,8 @@ class YnlFamily(SpecFamily):
|
||||
elif attr['type'] in NlAttr.type_formats:
|
||||
format = NlAttr.get_format(attr['type'], attr.byte_order)
|
||||
attr_payload = format.pack(int(value))
|
||||
elif attr['type'] in "bitfield32":
|
||||
attr_payload = struct.pack("II", int(value["value"]), int(value["selector"]))
|
||||
else:
|
||||
raise Exception(f'Unknown type at {space} {name} {value} {attr["type"]}')
|
||||
|
||||
@ -545,14 +547,19 @@ class YnlFamily(SpecFamily):
|
||||
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["type"] == 'array-nest':
|
||||
decoded = self._decode_array_nest(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}
|
||||
else:
|
||||
raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
|
||||
|
||||
if 'enum' in attr_spec:
|
||||
decoded = self._decode_enum(decoded, attr_spec)
|
||||
|
||||
if not attr_spec.is_multi:
|
||||
rsp[attr_spec['name']] = decoded
|
||||
elif attr_spec.name in rsp:
|
||||
|
@ -488,6 +488,31 @@ class TypeBinary(Type):
|
||||
f'memcpy({member}, {self.c_name}, {presence}_len);']
|
||||
|
||||
|
||||
class TypeBitfield32(Type):
|
||||
def _complex_member_type(self, ri):
|
||||
return "struct nla_bitfield32"
|
||||
|
||||
def _attr_typol(self):
|
||||
return f'.type = YNL_PT_BITFIELD32, '
|
||||
|
||||
def _attr_policy(self, policy):
|
||||
if not 'enum' in self.attr:
|
||||
raise Exception('Enum required for bitfield32 attr')
|
||||
enum = self.family.consts[self.attr['enum']]
|
||||
mask = enum.get_mask(as_flags=True)
|
||||
return f"NLA_POLICY_BITFIELD32({mask})"
|
||||
|
||||
def attr_put(self, ri, var):
|
||||
line = f"mnl_attr_put(nlh, {self.enum_name}, sizeof(struct nla_bitfield32), &{var}->{self.c_name})"
|
||||
self._attr_put_line(ri, var, line)
|
||||
|
||||
def _attr_get(self, ri, var):
|
||||
return f"memcpy(&{var}->{self.c_name}, mnl_attr_get_payload(attr), sizeof(struct nla_bitfield32));", None, None
|
||||
|
||||
def _setter_lines(self, ri, member, presence):
|
||||
return [f"memcpy(&{member}, {self.c_name}, sizeof(struct nla_bitfield32));"]
|
||||
|
||||
|
||||
class TypeNest(Type):
|
||||
def _complex_member_type(self, ri):
|
||||
return self.nested_struct_type
|
||||
@ -786,6 +811,8 @@ class AttrSet(SpecAttrSet):
|
||||
t = TypeString(self.family, self, elem, value)
|
||||
elif elem['type'] == 'binary':
|
||||
t = TypeBinary(self.family, self, elem, value)
|
||||
elif elem['type'] == 'bitfield32':
|
||||
t = TypeBitfield32(self.family, self, elem, value)
|
||||
elif elem['type'] == 'nest':
|
||||
t = TypeNest(self.family, self, elem, value)
|
||||
elif elem['type'] == 'array-nest':
|
||||
@ -2414,6 +2441,16 @@ def render_user_family(family, cw, prototype):
|
||||
cw.block_end(line=';')
|
||||
|
||||
|
||||
def family_contains_bitfield32(family):
|
||||
for _, attr_set in family.attr_sets.items():
|
||||
if attr_set.subset_of:
|
||||
continue
|
||||
for _, attr in attr_set.items():
|
||||
if attr.type == "bitfield32":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def find_kernel_root(full_path):
|
||||
sub_path = ''
|
||||
while True:
|
||||
@ -2499,6 +2536,8 @@ def main():
|
||||
cw.p('#include <string.h>')
|
||||
if args.header:
|
||||
cw.p('#include <linux/types.h>')
|
||||
if family_contains_bitfield32(parsed):
|
||||
cw.p('#include <linux/netlink.h>')
|
||||
else:
|
||||
cw.p(f'#include "{parsed.name}-user.h"')
|
||||
cw.p('#include "ynl.h"')
|
||||
|
Loading…
Reference in New Issue
Block a user