mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 12:14:10 +08:00
netlink: specs: add support for auto-sized scalars
Support uint / sint types in specs and YNL. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
374d345d9b
commit
7d4caf54d2
@ -149,7 +149,8 @@ properties:
|
||||
name:
|
||||
type: string
|
||||
type: &attr-type
|
||||
enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
|
||||
enum: [ unused, pad, flag, binary,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
|
@ -192,7 +192,8 @@ properties:
|
||||
type: string
|
||||
type: &attr-type
|
||||
description: The netlink attribute type
|
||||
enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
|
||||
enum: [ unused, pad, flag, binary,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
|
@ -122,7 +122,8 @@ properties:
|
||||
name:
|
||||
type: string
|
||||
type: &attr-type
|
||||
enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64,
|
||||
enum: [ unused, pad, flag, binary,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
|
@ -149,6 +149,7 @@ class SpecAttr(SpecElement):
|
||||
Represents a single attribute type within an attr space.
|
||||
|
||||
Attributes:
|
||||
type string, attribute type
|
||||
value numerical ID when serialized
|
||||
attr_set Attribute Set containing this attr
|
||||
is_multi bool, attr may repeat multiple times
|
||||
@ -157,10 +158,13 @@ class SpecAttr(SpecElement):
|
||||
len integer, optional byte length of binary types
|
||||
display_hint string, hint to help choose format specifier
|
||||
when displaying the value
|
||||
|
||||
is_auto_scalar bool, attr is a variable-size scalar
|
||||
"""
|
||||
def __init__(self, family, attr_set, yaml, value):
|
||||
super().__init__(family, yaml)
|
||||
|
||||
self.type = yaml['type']
|
||||
self.value = value
|
||||
self.attr_set = attr_set
|
||||
self.is_multi = yaml.get('multi-attr', False)
|
||||
@ -170,6 +174,8 @@ class SpecAttr(SpecElement):
|
||||
self.len = yaml.get('len')
|
||||
self.display_hint = yaml.get('display-hint')
|
||||
|
||||
self.is_auto_scalar = self.type == "sint" or self.type == "uint"
|
||||
|
||||
|
||||
class SpecAttrSet(SpecElement):
|
||||
""" Netlink Attribute Set class.
|
||||
|
@ -352,6 +352,12 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
|
||||
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
|
||||
"Invalid attribute (u64 %s)", policy->name);
|
||||
return -1;
|
||||
case YNL_PT_UINT:
|
||||
if (len == sizeof(__u32) || len == sizeof(__u64))
|
||||
break;
|
||||
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
|
||||
"Invalid attribute (uint %s)", policy->name);
|
||||
return -1;
|
||||
case YNL_PT_FLAG:
|
||||
/* Let flags grow into real attrs, why not.. */
|
||||
break;
|
||||
|
@ -133,6 +133,7 @@ enum ynl_policy_type {
|
||||
YNL_PT_U16,
|
||||
YNL_PT_U32,
|
||||
YNL_PT_U64,
|
||||
YNL_PT_UINT,
|
||||
YNL_PT_NUL_STR,
|
||||
};
|
||||
|
||||
@ -234,4 +235,20 @@ int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
|
||||
void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
|
||||
int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
|
||||
|
||||
#ifndef MNL_HAS_AUTO_SCALARS
|
||||
static inline uint64_t mnl_attr_get_uint(const struct nlattr *attr)
|
||||
{
|
||||
if (mnl_attr_get_len(attr) == 4)
|
||||
return mnl_attr_get_u32(attr);
|
||||
return mnl_attr_get_u64(attr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mnl_attr_put_uint(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
|
||||
{
|
||||
if ((uint32_t)data == (uint64_t)data)
|
||||
return mnl_attr_put_u32(nlh, type, data);
|
||||
return mnl_attr_put_u64(nlh, type, data);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -130,6 +130,13 @@ class NlAttr:
|
||||
format = self.get_format(attr_type, byte_order)
|
||||
return format.unpack(self.raw)[0]
|
||||
|
||||
def as_auto_scalar(self, attr_type, byte_order=None):
|
||||
if len(self.raw) != 4 and len(self.raw) != 8:
|
||||
raise Exception(f"Auto-scalar len payload be 4 or 8 bytes, got {len(self.raw)}")
|
||||
real_type = attr_type[0] + str(len(self.raw) * 8)
|
||||
format = self.get_format(real_type, byte_order)
|
||||
return format.unpack(self.raw)[0]
|
||||
|
||||
def as_strz(self):
|
||||
return self.raw.decode('ascii')[:-1]
|
||||
|
||||
@ -463,6 +470,11 @@ class YnlFamily(SpecFamily):
|
||||
attr_payload = bytes.fromhex(value)
|
||||
else:
|
||||
raise Exception(f'Unknown type for binary attribute, value: {value}')
|
||||
elif attr.is_auto_scalar:
|
||||
scalar = int(value)
|
||||
real_type = attr["type"][0] + ('32' if scalar.bit_length() <= 32 else '64')
|
||||
format = NlAttr.get_format(real_type, attr.byte_order)
|
||||
attr_payload = format.pack(int(value))
|
||||
elif attr['type'] in NlAttr.type_formats:
|
||||
format = NlAttr.get_format(attr['type'], attr.byte_order)
|
||||
attr_payload = format.pack(int(value))
|
||||
@ -529,6 +541,8 @@ class YnlFamily(SpecFamily):
|
||||
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)
|
||||
elif attr_spec["type"] == 'array-nest':
|
||||
|
@ -335,6 +335,8 @@ class TypeScalar(Type):
|
||||
maybe_enum = not self.is_bitfield and 'enum' in self.attr
|
||||
if maybe_enum and self.family.consts[self.attr['enum']].enum_name:
|
||||
self.type_name = f"enum {self.family.name}_{c_lower(self.attr['enum'])}"
|
||||
elif self.is_auto_scalar:
|
||||
self.type_name = '__' + self.type[0] + '64'
|
||||
else:
|
||||
self.type_name = '__' + self.type
|
||||
|
||||
@ -362,7 +364,7 @@ class TypeScalar(Type):
|
||||
return super()._attr_policy(policy)
|
||||
|
||||
def _attr_typol(self):
|
||||
return f'.type = YNL_PT_U{self.type[1:]}, '
|
||||
return f'.type = YNL_PT_U{c_upper(self.type[1:])}, '
|
||||
|
||||
def arg_member(self, ri):
|
||||
return [f'{self.type_name} {self.c_name}{self.byte_order_comment}']
|
||||
@ -1291,7 +1293,7 @@ class CodeWriter:
|
||||
self.p(line)
|
||||
|
||||
|
||||
scalars = {'u8', 'u16', 'u32', 'u64', 's32', 's64'}
|
||||
scalars = {'u8', 'u16', 'u32', 'u64', 's32', 's64', 'uint', 'sint'}
|
||||
|
||||
direction_to_suffix = {
|
||||
'reply': '_rsp',
|
||||
|
Loading…
Reference in New Issue
Block a user