Merge branch 'netlink-auto-integers'
Jakub Kicinski says: ==================== netlink: add variable-length / auto integers Add netlink support for "common" / variable-length / auto integers which are carried at the message level as either 4B or 8B depending on the exact value. This saves space and will hopefully decrease the number of instances where we realize that we needed more bits after uAPI is set is stone. It also loosens the alignment requirements, avoiding the need for padding. This mini-series is a fuller version of the previous RFC: https://lore.kernel.org/netdev/20121204.130914.1457976839967676240.davem@davemloft.net/ No user included here. I have tested (and will use) it in the upcoming page pool API but the assumption is that it will be widely applicable. So sending without a user. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fd533a7ac7
@ -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.
|
||||
|
@ -403,10 +403,21 @@ This section describes the attribute types supported by the ``genetlink``
|
||||
compatibility level. Refer to documentation of different levels for additional
|
||||
attribute types.
|
||||
|
||||
Scalar integer types
|
||||
Common integer types
|
||||
--------------------
|
||||
|
||||
Fixed-width integer types:
|
||||
``sint`` and ``uint`` represent signed and unsigned 64 bit integers.
|
||||
If the value can fit on 32 bits only 32 bits are carried in netlink
|
||||
messages, otherwise full 64 bits are carried. Note that the payload
|
||||
is only aligned to 4B, so the full 64 bit value may be unaligned!
|
||||
|
||||
Common integer types should be preferred over fix-width types in majority
|
||||
of cases.
|
||||
|
||||
Fix-width integer types
|
||||
-----------------------
|
||||
|
||||
Fixed-width integer types include:
|
||||
``u8``, ``u16``, ``u32``, ``u64``, ``s8``, ``s16``, ``s32``, ``s64``.
|
||||
|
||||
Note that types smaller than 32 bit should be avoided as using them
|
||||
@ -416,6 +427,9 @@ See :ref:`pad_type` for padding of 64 bit attributes.
|
||||
The payload of the attribute is the integer in host order unless ``byte-order``
|
||||
specifies otherwise.
|
||||
|
||||
64 bit values are usually aligned by the kernel but it is recommended
|
||||
that the user space is able to deal with unaligned values.
|
||||
|
||||
.. _pad_type:
|
||||
|
||||
pad
|
||||
|
@ -128,6 +128,8 @@
|
||||
* nla_len(nla) length of attribute payload
|
||||
*
|
||||
* Attribute Payload Access for Basic Types:
|
||||
* nla_get_uint(nla) get payload for a uint attribute
|
||||
* nla_get_sint(nla) get payload for a sint attribute
|
||||
* nla_get_u8(nla) get payload for a u8 attribute
|
||||
* nla_get_u16(nla) get payload for a u16 attribute
|
||||
* nla_get_u32(nla) get payload for a u32 attribute
|
||||
@ -183,6 +185,8 @@ enum {
|
||||
NLA_REJECT,
|
||||
NLA_BE16,
|
||||
NLA_BE32,
|
||||
NLA_SINT,
|
||||
NLA_UINT,
|
||||
__NLA_TYPE_MAX,
|
||||
};
|
||||
|
||||
@ -229,6 +233,7 @@ enum nla_policy_validation {
|
||||
* nested header (or empty); len field is used if
|
||||
* nested_policy is also used, for the max attr
|
||||
* number in the nested policy.
|
||||
* NLA_SINT, NLA_UINT,
|
||||
* NLA_U8, NLA_U16,
|
||||
* NLA_U32, NLA_U64,
|
||||
* NLA_S8, NLA_S16,
|
||||
@ -260,12 +265,14 @@ enum nla_policy_validation {
|
||||
* while an array has the nested attributes at another
|
||||
* level down and the attribute types directly in the
|
||||
* nesting don't matter.
|
||||
* NLA_UINT,
|
||||
* NLA_U8,
|
||||
* NLA_U16,
|
||||
* NLA_U32,
|
||||
* NLA_U64,
|
||||
* NLA_BE16,
|
||||
* NLA_BE32,
|
||||
* NLA_SINT,
|
||||
* NLA_S8,
|
||||
* NLA_S16,
|
||||
* NLA_S32,
|
||||
@ -280,6 +287,7 @@ enum nla_policy_validation {
|
||||
* or NLA_POLICY_FULL_RANGE_SIGNED() macros instead.
|
||||
* Use the NLA_POLICY_MIN(), NLA_POLICY_MAX() and
|
||||
* NLA_POLICY_RANGE() macros.
|
||||
* NLA_UINT,
|
||||
* NLA_U8,
|
||||
* NLA_U16,
|
||||
* NLA_U32,
|
||||
@ -288,6 +296,7 @@ enum nla_policy_validation {
|
||||
* to a struct netlink_range_validation that indicates
|
||||
* the min/max values.
|
||||
* Use NLA_POLICY_FULL_RANGE().
|
||||
* NLA_SINT,
|
||||
* NLA_S8,
|
||||
* NLA_S16,
|
||||
* NLA_S32,
|
||||
@ -377,9 +386,11 @@ struct nla_policy {
|
||||
|
||||
#define __NLA_IS_UINT_TYPE(tp) \
|
||||
(tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || \
|
||||
tp == NLA_U64 || tp == NLA_BE16 || tp == NLA_BE32)
|
||||
tp == NLA_U64 || tp == NLA_UINT || \
|
||||
tp == NLA_BE16 || tp == NLA_BE32)
|
||||
#define __NLA_IS_SINT_TYPE(tp) \
|
||||
(tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
|
||||
(tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64 || \
|
||||
tp == NLA_SINT)
|
||||
|
||||
#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
|
||||
#define NLA_ENSURE_UINT_TYPE(tp) \
|
||||
@ -1357,6 +1368,22 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
|
||||
return nla_put(skb, attrtype, sizeof(u32), &tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_put_uint - Add a variable-size unsigned int to a socket buffer
|
||||
* @skb: socket buffer to add attribute to
|
||||
* @attrtype: attribute type
|
||||
* @value: numeric value
|
||||
*/
|
||||
static inline int nla_put_uint(struct sk_buff *skb, int attrtype, u64 value)
|
||||
{
|
||||
u64 tmp64 = value;
|
||||
u32 tmp32 = value;
|
||||
|
||||
if (tmp64 == tmp32)
|
||||
return nla_put_u32(skb, attrtype, tmp32);
|
||||
return nla_put(skb, attrtype, sizeof(u64), &tmp64);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_put_be32 - Add a __be32 netlink attribute to a socket buffer
|
||||
* @skb: socket buffer to add attribute to
|
||||
@ -1511,6 +1538,22 @@ static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value,
|
||||
return nla_put_64bit(skb, attrtype, sizeof(s64), &tmp, padattr);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_put_sint - Add a variable-size signed int to a socket buffer
|
||||
* @skb: socket buffer to add attribute to
|
||||
* @attrtype: attribute type
|
||||
* @value: numeric value
|
||||
*/
|
||||
static inline int nla_put_sint(struct sk_buff *skb, int attrtype, s64 value)
|
||||
{
|
||||
s64 tmp64 = value;
|
||||
s32 tmp32 = value;
|
||||
|
||||
if (tmp64 == tmp32)
|
||||
return nla_put_s32(skb, attrtype, tmp32);
|
||||
return nla_put(skb, attrtype, sizeof(s64), &tmp64);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_put_string - Add a string netlink attribute to a socket buffer
|
||||
* @skb: socket buffer to add attribute to
|
||||
@ -1667,6 +1710,17 @@ static inline u64 nla_get_u64(const struct nlattr *nla)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_get_uint - return payload of uint attribute
|
||||
* @nla: uint netlink attribute
|
||||
*/
|
||||
static inline u64 nla_get_uint(const struct nlattr *nla)
|
||||
{
|
||||
if (nla_len(nla) == sizeof(u32))
|
||||
return nla_get_u32(nla);
|
||||
return nla_get_u64(nla);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_get_be64 - return payload of __be64 attribute
|
||||
* @nla: __be64 netlink attribute
|
||||
@ -1729,6 +1783,17 @@ static inline s64 nla_get_s64(const struct nlattr *nla)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_get_sint - return payload of uint attribute
|
||||
* @nla: uint netlink attribute
|
||||
*/
|
||||
static inline s64 nla_get_sint(const struct nlattr *nla)
|
||||
{
|
||||
if (nla_len(nla) == sizeof(s32))
|
||||
return nla_get_s32(nla);
|
||||
return nla_get_s64(nla);
|
||||
}
|
||||
|
||||
/**
|
||||
* nla_get_flag - return payload of flag attribute
|
||||
* @nla: flag netlink attribute
|
||||
|
@ -298,6 +298,8 @@ struct nla_bitfield32 {
|
||||
* entry has attributes again, the policy for those inner ones
|
||||
* and the corresponding maxtype may be specified.
|
||||
* @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute
|
||||
* @NL_ATTR_TYPE_SINT: 32-bit or 64-bit signed attribute, aligned to 4B
|
||||
* @NL_ATTR_TYPE_UINT: 32-bit or 64-bit unsigned attribute, aligned to 4B
|
||||
*/
|
||||
enum netlink_attribute_type {
|
||||
NL_ATTR_TYPE_INVALID,
|
||||
@ -322,6 +324,9 @@ enum netlink_attribute_type {
|
||||
NL_ATTR_TYPE_NESTED_ARRAY,
|
||||
|
||||
NL_ATTR_TYPE_BITFIELD32,
|
||||
|
||||
NL_ATTR_TYPE_SINT,
|
||||
NL_ATTR_TYPE_UINT,
|
||||
};
|
||||
|
||||
/**
|
||||
|
22
lib/nlattr.c
22
lib/nlattr.c
@ -134,6 +134,7 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
|
||||
range->max = U32_MAX;
|
||||
break;
|
||||
case NLA_U64:
|
||||
case NLA_UINT:
|
||||
case NLA_MSECS:
|
||||
range->max = U64_MAX;
|
||||
break;
|
||||
@ -183,6 +184,9 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
|
||||
case NLA_U64:
|
||||
value = nla_get_u64(nla);
|
||||
break;
|
||||
case NLA_UINT:
|
||||
value = nla_get_uint(nla);
|
||||
break;
|
||||
case NLA_MSECS:
|
||||
value = nla_get_u64(nla);
|
||||
break;
|
||||
@ -248,6 +252,7 @@ void nla_get_range_signed(const struct nla_policy *pt,
|
||||
range->max = S32_MAX;
|
||||
break;
|
||||
case NLA_S64:
|
||||
case NLA_SINT:
|
||||
range->min = S64_MIN;
|
||||
range->max = S64_MAX;
|
||||
break;
|
||||
@ -295,6 +300,9 @@ static int nla_validate_int_range_signed(const struct nla_policy *pt,
|
||||
case NLA_S64:
|
||||
value = nla_get_s64(nla);
|
||||
break;
|
||||
case NLA_SINT:
|
||||
value = nla_get_sint(nla);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -320,6 +328,7 @@ static int nla_validate_int_range(const struct nla_policy *pt,
|
||||
case NLA_U16:
|
||||
case NLA_U32:
|
||||
case NLA_U64:
|
||||
case NLA_UINT:
|
||||
case NLA_MSECS:
|
||||
case NLA_BINARY:
|
||||
case NLA_BE16:
|
||||
@ -329,6 +338,7 @@ static int nla_validate_int_range(const struct nla_policy *pt,
|
||||
case NLA_S16:
|
||||
case NLA_S32:
|
||||
case NLA_S64:
|
||||
case NLA_SINT:
|
||||
return nla_validate_int_range_signed(pt, nla, extack);
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -355,6 +365,9 @@ static int nla_validate_mask(const struct nla_policy *pt,
|
||||
case NLA_U64:
|
||||
value = nla_get_u64(nla);
|
||||
break;
|
||||
case NLA_UINT:
|
||||
value = nla_get_uint(nla);
|
||||
break;
|
||||
case NLA_BE16:
|
||||
value = ntohs(nla_get_be16(nla));
|
||||
break;
|
||||
@ -433,6 +446,15 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
|
||||
goto out_err;
|
||||
break;
|
||||
|
||||
case NLA_SINT:
|
||||
case NLA_UINT:
|
||||
if (attrlen != sizeof(u32) && attrlen != sizeof(u64)) {
|
||||
NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
|
||||
"invalid attribute length");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case NLA_BITFIELD32:
|
||||
if (attrlen != sizeof(struct nla_bitfield32))
|
||||
goto out_err;
|
||||
|
@ -230,6 +230,8 @@ int netlink_policy_dump_attr_size_estimate(const struct nla_policy *pt)
|
||||
case NLA_S16:
|
||||
case NLA_S32:
|
||||
case NLA_S64:
|
||||
case NLA_SINT:
|
||||
case NLA_UINT:
|
||||
/* maximum is common, u64 min/max with padding */
|
||||
return common +
|
||||
2 * (nla_attr_size(0) + nla_attr_size(sizeof(u64)));
|
||||
@ -288,6 +290,7 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
|
||||
case NLA_U16:
|
||||
case NLA_U32:
|
||||
case NLA_U64:
|
||||
case NLA_UINT:
|
||||
case NLA_MSECS: {
|
||||
struct netlink_range_validation range;
|
||||
|
||||
@ -297,8 +300,10 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
|
||||
type = NL_ATTR_TYPE_U16;
|
||||
else if (pt->type == NLA_U32)
|
||||
type = NL_ATTR_TYPE_U32;
|
||||
else
|
||||
else if (pt->type == NLA_U64)
|
||||
type = NL_ATTR_TYPE_U64;
|
||||
else
|
||||
type = NL_ATTR_TYPE_UINT;
|
||||
|
||||
if (pt->validation_type == NLA_VALIDATE_MASK) {
|
||||
if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MASK,
|
||||
@ -320,7 +325,8 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
|
||||
case NLA_S8:
|
||||
case NLA_S16:
|
||||
case NLA_S32:
|
||||
case NLA_S64: {
|
||||
case NLA_S64:
|
||||
case NLA_SINT: {
|
||||
struct netlink_range_validation_signed range;
|
||||
|
||||
if (pt->type == NLA_S8)
|
||||
@ -329,8 +335,10 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
|
||||
type = NL_ATTR_TYPE_S16;
|
||||
else if (pt->type == NLA_S32)
|
||||
type = NL_ATTR_TYPE_S32;
|
||||
else
|
||||
else if (pt->type == NLA_S64)
|
||||
type = NL_ATTR_TYPE_S64;
|
||||
else
|
||||
type = NL_ATTR_TYPE_SINT;
|
||||
|
||||
nla_get_range_signed(pt, &range);
|
||||
|
||||
|
@ -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':
|
||||
|
@ -159,6 +159,15 @@ class Type(SpecAttr):
|
||||
spec = self._attr_policy(policy)
|
||||
cw.p(f"\t[{self.enum_name}] = {spec},")
|
||||
|
||||
def _mnl_type(self):
|
||||
# mnl does not have helpers for signed integer types
|
||||
# turn signed type into unsigned
|
||||
# this only makes sense for scalar types
|
||||
t = self.type
|
||||
if t[0] == 's':
|
||||
t = 'u' + t[1:]
|
||||
return t
|
||||
|
||||
def _attr_typol(self):
|
||||
raise Exception(f"Type policy not implemented for class type {self.type}")
|
||||
|
||||
@ -326,15 +335,13 @@ 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
|
||||
|
||||
def _mnl_type(self):
|
||||
t = self.type
|
||||
# mnl does not have a helper for signed types
|
||||
if t[0] == 's':
|
||||
t = 'u' + t[1:]
|
||||
return t
|
||||
def mnl_type(self):
|
||||
return self._mnl_type()
|
||||
|
||||
def _attr_policy(self, policy):
|
||||
if 'flags-mask' in self.checks or self.is_bitfield:
|
||||
@ -357,16 +364,16 @@ 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}']
|
||||
|
||||
def attr_put(self, ri, var):
|
||||
self._attr_put_simple(ri, var, self._mnl_type())
|
||||
self._attr_put_simple(ri, var, self.mnl_type())
|
||||
|
||||
def _attr_get(self, ri, var):
|
||||
return f"{var}->{self.c_name} = mnl_attr_get_{self._mnl_type()}(attr);", None, None
|
||||
return f"{var}->{self.c_name} = mnl_attr_get_{self.mnl_type()}(attr);", None, None
|
||||
|
||||
def _setter_lines(self, ri, member, presence):
|
||||
return [f"{member} = {self.c_name};"]
|
||||
@ -524,12 +531,8 @@ class TypeMultiAttr(Type):
|
||||
def presence_type(self):
|
||||
return 'count'
|
||||
|
||||
def _mnl_type(self):
|
||||
t = self.type
|
||||
# mnl does not have a helper for signed types
|
||||
if t[0] == 's':
|
||||
t = 'u' + t[1:]
|
||||
return t
|
||||
def mnl_type(self):
|
||||
return self._mnl_type()
|
||||
|
||||
def _complex_member_type(self, ri):
|
||||
if 'type' not in self.attr or self.attr['type'] == 'nest':
|
||||
@ -564,7 +567,7 @@ class TypeMultiAttr(Type):
|
||||
|
||||
def attr_put(self, ri, var):
|
||||
if self.attr['type'] in scalars:
|
||||
put_type = self._mnl_type()
|
||||
put_type = self.mnl_type()
|
||||
ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
|
||||
ri.cw.p(f"mnl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
|
||||
elif 'type' not in self.attr or self.attr['type'] == 'nest':
|
||||
@ -1290,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',
|
||||
@ -1580,11 +1583,8 @@ def _multi_parse(ri, struct, init_lines, local_vars):
|
||||
ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];")
|
||||
ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr))")
|
||||
ri.cw.p('return MNL_CB_ERROR;')
|
||||
elif aspec['type'] in scalars:
|
||||
t = aspec['type']
|
||||
if t[0] == 's':
|
||||
t = 'u' + t[1:]
|
||||
ri.cw.p(f"dst->{aspec.c_name}[i] = mnl_attr_get_{t}(attr);")
|
||||
elif aspec.type in scalars:
|
||||
ri.cw.p(f"dst->{aspec.c_name}[i] = mnl_attr_get_{aspec.mnl_type()}(attr);")
|
||||
else:
|
||||
raise Exception('Nest parsing type not supported yet')
|
||||
ri.cw.p('i++;')
|
||||
|
Loading…
Reference in New Issue
Block a user