18 #include <netlink-private/netlink.h>
19 #include <netlink/netlink.h>
20 #include <netlink/attr.h>
21 #include <netlink/utils.h>
22 #include <netlink/object.h>
23 #include <netlink/route/rtnl.h>
24 #include <netlink/route/link/macsec.h>
25 #include <netlink-private/route/link/api.h>
26 #include <netlink-private/utils.h>
28 #include <linux/if_macsec.h>
31 #define MACSEC_ATTR_SCI (1 << 0)
32 #define MACSEC_ATTR_ICV_LEN (1 << 1)
33 #define MACSEC_ATTR_CIPHER_SUITE (1 << 2)
34 #define MACSEC_ATTR_WINDOW (1 << 3)
35 #define MACSEC_ATTR_ENCODING_SA (1 << 4)
36 #define MACSEC_ATTR_ENCRYPT (1 << 5)
37 #define MACSEC_ATTR_PROTECT (1 << 6)
38 #define MACSEC_ATTR_INC_SCI (1 << 7)
39 #define MACSEC_ATTR_ES (1 << 8)
40 #define MACSEC_ATTR_SCB (1 << 9)
41 #define MACSEC_ATTR_REPLAY_PROTECT (1 << 10)
42 #define MACSEC_ATTR_VALIDATION (1 << 11)
43 #define MACSEC_ATTR_PORT (1 << 12)
44 #define MACSEC_ATTR_OFFLOAD (1 << 13)
50 uint64_t cipher_suite;
53 enum macsec_validation_type validate;
56 uint8_t send_sci, end_station, scb, replay_protect, protect, encrypt, offload;
61 #define DEFAULT_ICV_LEN 16
65 static struct nla_policy macsec_policy[IFLA_MACSEC_MAX+1] = {
67 [IFLA_MACSEC_ICV_LEN] = { .type =
NLA_U8 },
68 [IFLA_MACSEC_CIPHER_SUITE] = { .type =
NLA_U64 },
69 [IFLA_MACSEC_WINDOW] = { .type =
NLA_U32 },
70 [IFLA_MACSEC_ENCODING_SA] = { .type =
NLA_U8 },
71 [IFLA_MACSEC_ENCRYPT] = { .type =
NLA_U8 },
72 [IFLA_MACSEC_PROTECT] = { .type =
NLA_U8 },
73 [IFLA_MACSEC_INC_SCI] = { .type =
NLA_U8 },
74 [IFLA_MACSEC_ES] = { .type =
NLA_U8 },
75 [IFLA_MACSEC_SCB] = { .type =
NLA_U8 },
76 [IFLA_MACSEC_REPLAY_PROTECT] = { .type =
NLA_U8 },
77 [IFLA_MACSEC_VALIDATION] = { .type =
NLA_U8 },
78 [IFLA_MACSEC_OFFLOAD] = { .type =
NLA_U8 },
91 static int macsec_alloc(
struct rtnl_link *link)
93 struct macsec_info *info;
96 link->l_info = malloc(
sizeof(
struct macsec_info));
101 memset(link->l_info, 0,
sizeof(
struct macsec_info));
104 info->cipher_suite = MACSEC_DEFAULT_CIPHER_ID;
105 info->icv_len = DEFAULT_ICV_LEN;
106 info->ce_mask = MACSEC_ATTR_CIPHER_SUITE | MACSEC_ATTR_ICV_LEN;
111 static int macsec_parse(
struct rtnl_link *link,
struct nlattr *data,
112 struct nlattr *xstats)
114 struct nlattr *tb[IFLA_MACSEC_MAX+1];
115 struct macsec_info *info;
118 NL_DBG(3,
"Parsing MACsec link info\n");
123 if ((err = macsec_alloc(link)) < 0)
128 if (tb[IFLA_MACSEC_SCI]) {
130 info->ce_mask |= MACSEC_ATTR_SCI;
133 if (tb[IFLA_MACSEC_PROTECT]) {
134 info->protect =
nla_get_u8(tb[IFLA_MACSEC_PROTECT]);
135 info->ce_mask |= MACSEC_ATTR_PROTECT;
138 if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
139 info->cipher_suite =
nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
140 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
143 if (tb[IFLA_MACSEC_ICV_LEN]) {
144 info->icv_len =
nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]);
145 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
148 if (tb[IFLA_MACSEC_ENCODING_SA]) {
149 info->encoding_sa =
nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]);
150 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
153 if (tb[IFLA_MACSEC_VALIDATION]) {
154 info->validate =
nla_get_u8(tb[IFLA_MACSEC_VALIDATION]);
155 info->ce_mask |= MACSEC_ATTR_VALIDATION;
158 if (tb[IFLA_MACSEC_ENCRYPT]) {
159 info->encrypt =
nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]);
160 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
163 if (tb[IFLA_MACSEC_OFFLOAD]) {
164 info->offload =
nla_get_u8(tb[IFLA_MACSEC_OFFLOAD]);
165 info->ce_mask |= MACSEC_ATTR_OFFLOAD;
168 if (tb[IFLA_MACSEC_INC_SCI]) {
169 info->send_sci =
nla_get_u8(tb[IFLA_MACSEC_INC_SCI]);
170 info->ce_mask |= MACSEC_ATTR_INC_SCI;
173 if (tb[IFLA_MACSEC_ES]) {
174 info->end_station =
nla_get_u8(tb[IFLA_MACSEC_ES]);
175 info->ce_mask |= MACSEC_ATTR_ES;
178 if (tb[IFLA_MACSEC_SCB]) {
180 info->ce_mask |= MACSEC_ATTR_SCB;
183 if (tb[IFLA_MACSEC_REPLAY_PROTECT]) {
184 info->replay_protect =
nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]);
185 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
188 if (tb[IFLA_MACSEC_WINDOW]) {
189 info->window =
nla_get_u32(tb[IFLA_MACSEC_WINDOW]);
190 info->ce_mask |= MACSEC_ATTR_WINDOW;
198 static void macsec_free(
struct rtnl_link *link)
204 static const char *values_on_off[] = {
"off",
"on" };
206 static const char *VALIDATE_STR[] = {
207 [MACSEC_VALIDATE_DISABLED] =
"disabled",
208 [MACSEC_VALIDATE_CHECK] =
"check",
209 [MACSEC_VALIDATE_STRICT] =
"strict",
212 static char *replay_protect_str(
char *buf, uint8_t replay_protect, uint8_t window)
214 if (replay_protect == 1) {
215 sprintf(buf,
"replay_protect on window %d", window);
216 }
else if (replay_protect == 0) {
217 sprintf(buf,
"replay_protect off");
226 #define PRINT_FLAG(buf, i, field, c) ({ if (i->field == 1) *buf++ = c; })
228 static char *flags_str(
char *buf,
unsigned char len,
struct macsec_info *info)
233 PRINT_FLAG(tmp, info, protect,
'P');
234 PRINT_FLAG(tmp, info, encrypt,
'E');
235 PRINT_FLAG(tmp, info, send_sci,
'S');
236 PRINT_FLAG(tmp, info, end_station,
'e');
237 PRINT_FLAG(tmp, info, scb,
's');
238 PRINT_FLAG(tmp, info, replay_protect,
'R');
242 switch (info->validate) {
243 case MACSEC_VALIDATE_DISABLED:
246 case MACSEC_VALIDATE_CHECK:
249 case MACSEC_VALIDATE_STRICT:
256 sprintf(tmp,
" %d", info->encoding_sa);
263 struct macsec_info *info = link->l_info;
266 nl_dump(p,
"sci %016llx <%s>", ntohll(info->sci), flags_str(tmp,
sizeof(tmp), info));
271 struct macsec_info *info = link->l_info;
274 nl_dump(p,
" sci %016llx protect %s encoding_sa %d encrypt %s send_sci %s validate %s %s\n",
275 ntohll(info->sci), values_on_off[info->protect], info->encoding_sa, values_on_off[info->encrypt], values_on_off[info->send_sci],
276 VALIDATE_STR[info->validate],
277 replay_protect_str(tmp, info->replay_protect, info->window));
278 nl_dump(p,
" cipher suite: %016llx, icv_len %d\n",
279 info->cipher_suite, info->icv_len);
284 struct macsec_info *copy, *info = src->l_info;
295 memcpy(copy, info,
sizeof(
struct macsec_info));
300 static int macsec_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
302 struct macsec_info *info = link->l_info;
308 if (info->ce_mask & MACSEC_ATTR_SCI)
310 else if (info->ce_mask & MACSEC_ATTR_PORT)
311 NLA_PUT_U16(msg, IFLA_MACSEC_PORT, htons(info->port));
313 if ((info->ce_mask & MACSEC_ATTR_ENCRYPT))
314 NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, info->encrypt);
316 if ((info->ce_mask & MACSEC_ATTR_OFFLOAD))
317 NLA_PUT_U8(msg, IFLA_MACSEC_OFFLOAD, info->offload);
319 if (info->cipher_suite != MACSEC_DEFAULT_CIPHER_ID || info->icv_len != DEFAULT_ICV_LEN) {
320 NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, info->cipher_suite);
321 NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, info->icv_len);
324 if ((info->ce_mask & MACSEC_ATTR_INC_SCI))
325 NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, info->send_sci);
327 if ((info->ce_mask & MACSEC_ATTR_ES))
328 NLA_PUT_U8(msg, IFLA_MACSEC_ES, info->end_station);
330 if ((info->ce_mask & MACSEC_ATTR_SCB))
333 if ((info->ce_mask & MACSEC_ATTR_PROTECT))
334 NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, info->protect);
336 if ((info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) {
337 if (info->replay_protect && !(info->ce_mask & MACSEC_ATTR_WINDOW))
340 NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, info->replay_protect);
341 NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, info->window);
344 if ((info->ce_mask & MACSEC_ATTR_VALIDATION))
345 NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, info->validate);
347 if ((info->ce_mask & MACSEC_ATTR_ENCODING_SA))
348 NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, info->encoding_sa);
361 struct macsec_info *a = link_a->l_info;
362 struct macsec_info *b = link_b->l_info;
364 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
366 #define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR)
368 if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
369 diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
370 else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
371 diff |= MACSEC_DIFF(PORT, a->port != b->port);
373 if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
374 diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
375 diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
378 if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
379 int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
380 if (a->replay_protect && b->replay_protect)
381 d |= MACSEC_DIFF(WINDOW, a->window != b->window);
385 diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
386 diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
387 diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
388 diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
389 diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
390 diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
391 diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
398 static struct rtnl_link_info_ops macsec_info_ops = {
400 .io_alloc = macsec_alloc,
401 .io_parse = macsec_parse,
406 .io_clone = macsec_clone,
407 .io_put_attrs = macsec_put_attrs,
408 .io_free = macsec_free,
409 .io_compare = macsec_compare,
412 static void __init macsec_init(
void)
417 static void __exit macsec_exit(
void)
423 #define IS_MACSEC_LINK_ASSERT(link) \
424 if ((link)->l_info_ops != &macsec_info_ops) { \
425 APPBUG("Link is not a MACsec link. set type \"macsec\" first."); \
426 return -NLE_OPNOTSUPP; \
430 struct rtnl_link *rtnl_link_macsec_alloc(
void)
454 struct macsec_info *info = link->l_info;
456 IS_MACSEC_LINK_ASSERT(link);
459 info->ce_mask |= MACSEC_ATTR_SCI;
474 struct macsec_info *info = link->l_info;
476 IS_MACSEC_LINK_ASSERT(link);
478 if (!(info->ce_mask & MACSEC_ATTR_SCI))
496 struct macsec_info *info = link->l_info;
498 IS_MACSEC_LINK_ASSERT(link);
501 info->ce_mask |= MACSEC_ATTR_PORT;
515 struct macsec_info *info = link->l_info;
517 IS_MACSEC_LINK_ASSERT(link);
519 if (!(info->ce_mask & MACSEC_ATTR_PORT))
528 int rtnl_link_macsec_set_cipher_suite(
struct rtnl_link *link, uint64_t cipher_suite)
530 struct macsec_info *info = link->l_info;
532 IS_MACSEC_LINK_ASSERT(link);
534 info->cipher_suite = cipher_suite;
535 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
540 int rtnl_link_macsec_get_cipher_suite(
struct rtnl_link *link, uint64_t *cs)
542 struct macsec_info *info = link->l_info;
544 IS_MACSEC_LINK_ASSERT(link);
546 if (!(info->ce_mask & MACSEC_ATTR_CIPHER_SUITE))
550 *cs = info->cipher_suite;
555 int rtnl_link_macsec_set_icv_len(
struct rtnl_link *link, uint16_t icv_len)
557 struct macsec_info *info = link->l_info;
559 IS_MACSEC_LINK_ASSERT(link);
561 if (icv_len > MACSEC_STD_ICV_LEN)
564 info->icv_len = icv_len;
565 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
570 int rtnl_link_macsec_get_icv_len(
struct rtnl_link *link, uint16_t *icv_len)
572 struct macsec_info *info = link->l_info;
574 IS_MACSEC_LINK_ASSERT(link);
576 if (!(info->ce_mask & MACSEC_ATTR_ICV_LEN))
580 *icv_len = info->icv_len;
585 int rtnl_link_macsec_set_protect(
struct rtnl_link *link, uint8_t protect)
587 struct macsec_info *info = link->l_info;
589 IS_MACSEC_LINK_ASSERT(link);
594 info->protect = protect;
595 info->ce_mask |= MACSEC_ATTR_PROTECT;
600 int rtnl_link_macsec_get_protect(
struct rtnl_link *link, uint8_t *protect)
602 struct macsec_info *info = link->l_info;
604 IS_MACSEC_LINK_ASSERT(link);
606 if (!(info->ce_mask & MACSEC_ATTR_PROTECT))
610 *protect = info->protect;
615 int rtnl_link_macsec_set_encrypt(
struct rtnl_link *link, uint8_t encrypt)
617 struct macsec_info *info = link->l_info;
619 IS_MACSEC_LINK_ASSERT(link);
624 info->encrypt = encrypt;
625 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
630 int rtnl_link_macsec_get_encrypt(
struct rtnl_link *link, uint8_t *encrypt)
632 struct macsec_info *info = link->l_info;
634 IS_MACSEC_LINK_ASSERT(link);
636 if (!(info->ce_mask & MACSEC_ATTR_ENCRYPT))
640 *encrypt = info->encrypt;
645 int rtnl_link_macsec_set_offload(
struct rtnl_link *link, uint8_t offload)
647 struct macsec_info *info = link->l_info;
649 IS_MACSEC_LINK_ASSERT(link);
654 info->offload = offload;
655 info->ce_mask |= MACSEC_ATTR_OFFLOAD;
660 int rtnl_link_macsec_get_offload(
struct rtnl_link *link, uint8_t *offload)
662 struct macsec_info *info = link->l_info;
664 IS_MACSEC_LINK_ASSERT(link);
666 if (!(info->ce_mask & MACSEC_ATTR_OFFLOAD))
670 *offload = info->offload;
675 int rtnl_link_macsec_set_encoding_sa(
struct rtnl_link *link, uint8_t encoding_sa)
677 struct macsec_info *info = link->l_info;
679 IS_MACSEC_LINK_ASSERT(link);
684 info->encoding_sa = encoding_sa;
685 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
690 int rtnl_link_macsec_get_encoding_sa(
struct rtnl_link *link, uint8_t *encoding_sa)
692 struct macsec_info *info = link->l_info;
694 IS_MACSEC_LINK_ASSERT(link);
696 if (!(info->ce_mask & MACSEC_ATTR_ENCODING_SA))
700 *encoding_sa = info->encoding_sa;
705 int rtnl_link_macsec_set_validation_type(
struct rtnl_link *link,
enum macsec_validation_type validate)
707 struct macsec_info *info = link->l_info;
709 IS_MACSEC_LINK_ASSERT(link);
711 if (validate > MACSEC_VALIDATE_MAX)
714 info->validate = validate;
715 info->ce_mask |= MACSEC_ATTR_VALIDATION;
720 int rtnl_link_macsec_get_validation_type(
struct rtnl_link *link,
enum macsec_validation_type *validate)
722 struct macsec_info *info = link->l_info;
724 IS_MACSEC_LINK_ASSERT(link);
726 if (!(info->ce_mask & MACSEC_ATTR_VALIDATION))
730 *validate = info->validate;
735 int rtnl_link_macsec_set_replay_protect(
struct rtnl_link *link, uint8_t replay_protect)
737 struct macsec_info *info = link->l_info;
739 IS_MACSEC_LINK_ASSERT(link);
741 if (replay_protect > 1)
744 info->replay_protect = replay_protect;
745 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
750 int rtnl_link_macsec_get_replay_protect(
struct rtnl_link *link, uint8_t *replay_protect)
752 struct macsec_info *info = link->l_info;
754 IS_MACSEC_LINK_ASSERT(link);
756 if (!(info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT))
760 *replay_protect = info->replay_protect;
765 int rtnl_link_macsec_set_window(
struct rtnl_link *link, uint32_t window)
767 struct macsec_info *info = link->l_info;
769 IS_MACSEC_LINK_ASSERT(link);
771 info->window = window;
772 info->ce_mask |= MACSEC_ATTR_WINDOW;
777 int rtnl_link_macsec_get_window(
struct rtnl_link *link, uint32_t *window)
779 struct macsec_info *info = link->l_info;
781 IS_MACSEC_LINK_ASSERT(link);
783 if (!(info->ce_mask & MACSEC_ATTR_WINDOW))
787 *window = info->window;
792 int rtnl_link_macsec_set_send_sci(
struct rtnl_link *link, uint8_t send_sci)
794 struct macsec_info *info = link->l_info;
796 IS_MACSEC_LINK_ASSERT(link);
801 info->send_sci = send_sci;
802 info->ce_mask |= MACSEC_ATTR_INC_SCI;
807 int rtnl_link_macsec_get_send_sci(
struct rtnl_link *link, uint8_t *send_sci)
809 struct macsec_info *info = link->l_info;
811 IS_MACSEC_LINK_ASSERT(link);
813 if (!(info->ce_mask & MACSEC_ATTR_INC_SCI))
817 *send_sci = info->send_sci;
822 int rtnl_link_macsec_set_end_station(
struct rtnl_link *link, uint8_t end_station)
824 struct macsec_info *info = link->l_info;
826 IS_MACSEC_LINK_ASSERT(link);
831 info->end_station = end_station;
832 info->ce_mask |= MACSEC_ATTR_ES;
837 int rtnl_link_macsec_get_end_station(
struct rtnl_link *link, uint8_t *es)
839 struct macsec_info *info = link->l_info;
841 IS_MACSEC_LINK_ASSERT(link);
843 if (!(info->ce_mask & MACSEC_ATTR_ES))
847 *es = info->end_station;
852 int rtnl_link_macsec_set_scb(
struct rtnl_link *link, uint8_t scb)
854 struct macsec_info *info = link->l_info;
856 IS_MACSEC_LINK_ASSERT(link);
862 info->ce_mask |= MACSEC_ATTR_SCB;
867 int rtnl_link_macsec_get_scb(
struct rtnl_link *link, uint8_t *scb)
869 struct macsec_info *info = link->l_info;
871 IS_MACSEC_LINK_ASSERT(link);
873 if (!(info->ce_mask & MACSEC_ATTR_SCB))
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
#define NLA_PUT_U64(msg, attrtype, value)
Add 64 bit integer attribute to netlink message.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci)
Set SCI.
int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
Get SCI.
int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
Set port identifier.
int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
Get port identifier.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t type
Type of attribute or NLA_UNSPEC.