summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/netlink/genetlink-legacy.yaml2
-rw-r--r--Documentation/userspace-api/netlink/genetlink-legacy.rst2
-rw-r--r--tools/net/ynl/lib/ynl.c6
-rw-r--r--tools/net/ynl/lib/ynl.h1
-rw-r--r--tools/net/ynl/lib/ynl.py13
-rwxr-xr-xtools/net/ynl/ynl-gen-c.py39
6 files changed, 58 insertions, 5 deletions
diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml
index 923de0ff1a9e..565bf615b501 100644
--- a/Documentation/netlink/genetlink-legacy.yaml
+++ b/Documentation/netlink/genetlink-legacy.yaml
@@ -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:
diff --git a/Documentation/userspace-api/netlink/genetlink-legacy.rst b/Documentation/userspace-api/netlink/genetlink-legacy.rst
index 0b3febd57ff5..70a77387f6c4 100644
--- a/Documentation/userspace-api/netlink/genetlink-legacy.rst
+++ b/Documentation/userspace-api/netlink/genetlink-legacy.rst
@@ -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>`
diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c
index 350ddc247450..830d25097009 100644
--- a/tools/net/ynl/lib/ynl.c
+++ b/tools/net/ynl/lib/ynl.c
@@ -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);
diff --git a/tools/net/ynl/lib/ynl.h b/tools/net/ynl/lib/ynl.h
index 87b4dad832f0..c883e4747cfa 100644
--- a/tools/net/ynl/lib/ynl.h
+++ b/tools/net/ynl/lib/ynl.h
@@ -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 {
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
index 3b36553a66cc..b1da4aea9336 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/lib/ynl.py
@@ -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:
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
index a9e8898c9386..7d6c318397be 100755
--- a/tools/net/ynl/ynl-gen-c.py
+++ b/tools/net/ynl/ynl-gen-c.py
@@ -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"')