15#include "nl-default.h"
17#include <linux/if_arp.h>
19#include <netlink/netlink.h>
20#include <netlink/attr.h>
21#include <netlink/utils.h>
22#include <netlink/object.h>
23#include <netlink/hashtable.h>
24#include <netlink/data.h>
25#include <netlink/route/rtnl.h>
26#include <netlink/route/link.h>
28#include "nl-aux-route/nl-route.h"
29#include "nl-priv-dynamic-core/nl-core.h"
30#include "nl-priv-dynamic-core/cache-api.h"
32#include "link-sriov.h"
33#include "link/link-api.h"
36#define LINK_ATTR_MTU (1 << 0)
37#define LINK_ATTR_LINK (1 << 1)
38#define LINK_ATTR_TXQLEN (1 << 2)
39#define LINK_ATTR_WEIGHT (1 << 3)
40#define LINK_ATTR_MASTER (1 << 4)
41#define LINK_ATTR_QDISC (1 << 5)
42#define LINK_ATTR_MAP (1 << 6)
43#define LINK_ATTR_ADDR (1 << 7)
44#define LINK_ATTR_BRD (1 << 8)
45#define LINK_ATTR_FLAGS (1 << 9)
46#define LINK_ATTR_IFNAME (1 << 10)
47#define LINK_ATTR_IFINDEX (1 << 11)
48#define LINK_ATTR_FAMILY (1 << 12)
49#define LINK_ATTR_ARPTYPE (1 << 13)
50#define LINK_ATTR_STATS (1 << 14)
51#define LINK_ATTR_CHANGE (1 << 15)
52#define LINK_ATTR_OPERSTATE (1 << 16)
53#define LINK_ATTR_LINKMODE (1 << 17)
54#define LINK_ATTR_LINKINFO (1 << 18)
55#define LINK_ATTR_IFALIAS (1 << 19)
56#define LINK_ATTR_NUM_VF (1 << 20)
57#define LINK_ATTR_PROMISCUITY (1 << 21)
58#define LINK_ATTR_NUM_TX_QUEUES (1 << 22)
59#define LINK_ATTR_NUM_RX_QUEUES (1 << 23)
60#define LINK_ATTR_GROUP (1 << 24)
61#define LINK_ATTR_CARRIER (1 << 25)
62#define LINK_ATTR_PROTINFO (1 << 26)
63#define LINK_ATTR_AF_SPEC (1 << 27)
64#define LINK_ATTR_PHYS_PORT_ID (1 << 28)
65#define LINK_ATTR_NS_FD (1 << 29)
66#define LINK_ATTR_NS_PID (1 << 30)
68#define LINK_ATTR_LINK_NETNSID ((uint64_t) 1 << 32)
69#define LINK_ATTR_VF_LIST ((uint64_t) 1 << 33)
70#define LINK_ATTR_CARRIER_CHANGES ((uint64_t) 1 << 34)
71#define LINK_ATTR_PHYS_PORT_NAME ((uint64_t) 1 << 35)
72#define LINK_ATTR_PHYS_SWITCH_ID ((uint64_t) 1 << 36)
73#define LINK_ATTR_GSO_MAX_SEGS ((uint64_t) 1 << 37)
74#define LINK_ATTR_GSO_MAX_SIZE ((uint64_t) 1 << 38)
75#define LINK_ATTR_LINKINFO_SLAVE_KIND ((uint64_t) 1 << 39)
76#define LINK_ATTR_PERMANENT_ADDR ((uint64_t) 1 << 40)
78static struct nl_cache_ops rtnl_link_ops;
79static struct nl_object_ops link_obj_ops;
82struct rtnl_link *link_lookup(
struct nl_cache *cache,
int ifindex)
85 cache = __nl_cache_mngt_require(
"route/link");
111 void *data,
void *arg)
121static int af_request_type(
int af_type,
struct rtnl_link *changes)
126 if (ops && ops->ao_override_rtm && ops->ao_override_rtm(changes))
133 void *data,
void *arg)
145 void *data,
void *arg)
147 struct nl_msg *msg = arg;
148 struct nlattr *af_attr = NULL;
158 if ((err = ops->
ao_fill_af(link, arg, data)) < 0)
168 void *data,
void *arg)
170 struct nl_msg *msg = arg;
171 struct nlattr *pi_attr;
172 int err, pi_type = IFLA_PROTINFO;
183 if ((err = ops->
ao_fill_pi(link, arg, data)) < 0)
192 void *data,
void *arg)
203 void *data,
void *arg)
214 void *data,
void *arg)
224static int do_foreach_af(
struct rtnl_link *link,
231 for (i = 0; i < AF_MAX; i++) {
232 if (link->l_af_data[i]) {
238 err = cb(link, ops, link->l_af_data[i], arg);
247static void release_link_info(
struct rtnl_link *link)
256 BUG_ON(link->l_info);
259 link->l_info_ops = NULL;
263static void link_free_data(
struct nl_object *c)
265 struct rtnl_link *link = nl_object_priv(c);
268 release_link_info(link);
277 free(link->l_ifalias);
278 free(link->l_info_kind);
279 free(link->l_info_slave_kind);
281 do_foreach_af(link, af_free, NULL);
286 if (link->ce_mask & LINK_ATTR_VF_LIST)
287 rtnl_link_sriov_free_data(link);
291static int link_clone(
struct nl_object *_dst,
struct nl_object *_src)
293 struct rtnl_link *dst = nl_object_priv(_dst);
294 struct rtnl_link *src = nl_object_priv(_src);
300 dst->l_info_kind = NULL;
301 dst->l_info_slave_kind = NULL;
302 dst->l_info_ops = NULL;
303 memset(dst->l_af_data, 0, sizeof (dst->l_af_data));
305 dst->l_ifalias = NULL;
306 dst->l_af_ops = NULL;
307 dst->l_phys_port_id = NULL;
308 dst->l_phys_switch_id = NULL;
309 dst->l_vf_list = NULL;
324 if (!(dst->l_ifalias = strdup(src->l_ifalias)))
327 if (src->l_info_kind)
328 if (!(dst->l_info_kind = strdup(src->l_info_kind)))
331 if (src->l_info_slave_kind)
332 if (!(dst->l_info_slave_kind = strdup(src->l_info_slave_kind)))
335 if (src->l_info_ops) {
338 dst->l_info_ops = src->l_info_ops;
341 err = src->l_info_ops->
io_clone(dst, src);
347 if ((err = do_foreach_af(src, af_clone, dst)) < 0)
351 dst->l_af_ops = af_lookup_and_alloc(dst, src->l_af_ops->
ao_family);
353 if (src->l_phys_port_id)
354 if (!(dst->l_phys_port_id =
nl_data_clone(src->l_phys_port_id)))
357 if (src->l_phys_switch_id)
358 if (!(dst->l_phys_switch_id =
nl_data_clone(src->l_phys_switch_id)))
361 if (src->ce_mask & LINK_ATTR_VF_LIST)
362 if ((err = rtnl_link_sriov_clone(dst, src)) < 0)
370 .maxlen = IFNAMSIZ },
380 .maxlen = IFQDISCSIZ },
383 [
IFLA_MAP] = { .minlen =
sizeof(
struct rtnl_link_ifmap) },
384 [IFLA_IFALIAS] = { .type =
NLA_STRING, .maxlen = IFALIASZ },
385 [IFLA_NUM_VF] = { .type =
NLA_U32 },
388 [IFLA_PROMISCUITY] = { .type =
NLA_U32 },
389 [IFLA_NUM_TX_QUEUES] = { .type =
NLA_U32 },
390 [IFLA_NUM_RX_QUEUES] = { .type =
NLA_U32 },
391 [IFLA_GSO_MAX_SEGS] = { .type =
NLA_U32 },
392 [IFLA_GSO_MAX_SIZE] = { .type =
NLA_U32 },
393 [IFLA_GROUP] = { .type =
NLA_U32 },
394 [IFLA_CARRIER] = { .type =
NLA_U8 },
395 [IFLA_CARRIER_CHANGES] = { .type =
NLA_U32 },
397 [IFLA_PHYS_PORT_NAME] = { .type =
NLA_STRING, .maxlen = IFNAMSIZ },
398 [IFLA_PHYS_SWITCH_ID] = { .type =
NLA_UNSPEC },
399 [IFLA_NET_NS_PID] = { .type =
NLA_U32 },
400 [IFLA_NET_NS_FD] = { .type =
NLA_U32 },
412 return -NLE_MISSING_ATTR;
418 struct rtnl_link_stats *st =
nla_data(tb[IFLA_STATS]);
450 if (_nla_len(tb[IFLA_STATS]) >= _nl_offsetofend (
struct rtnl_link_stats, rx_nohandler))
455 link->ce_mask |= LINK_ATTR_STATS;
458 if (tb[IFLA_STATS64]) {
466 struct rtnl_link_stats64 st = { 0 };
468 nla_memcpy(&st, tb[IFLA_STATS64],
sizeof (st));
502 link->ce_mask |= LINK_ATTR_STATS;
505 if (tb[IFLA_TXQLEN]) {
507 link->ce_mask |= LINK_ATTR_TXQLEN;
512 link->ce_mask |= LINK_ATTR_MTU;
515 if (tb[IFLA_ADDRESS]) {
517 if (link->l_addr == NULL)
521 link->ce_mask |= LINK_ATTR_ADDR;
524 if (tb[IFLA_PERM_ADDRESS]) {
526 if (link->l_paddr == NULL)
530 link->ce_mask |= LINK_ATTR_PERMANENT_ADDR;
533 if (tb[IFLA_BROADCAST]) {
536 if (link->l_bcast == NULL)
540 link->ce_mask |= LINK_ATTR_BRD;
545 link->ce_mask |= LINK_ATTR_LINK;
548 if (tb[IFLA_LINK_NETNSID]) {
549 link->l_link_netnsid =
nla_get_s32(tb[IFLA_LINK_NETNSID]);
550 link->ce_mask |= LINK_ATTR_LINK_NETNSID;
553 if (tb[IFLA_WEIGHT]) {
555 link->ce_mask |= LINK_ATTR_WEIGHT;
558 if (tb[IFLA_QDISC]) {
559 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
560 link->ce_mask |= LINK_ATTR_QDISC;
565 sizeof(
struct rtnl_link_ifmap));
566 link->ce_mask |= LINK_ATTR_MAP;
569 if (tb[IFLA_MASTER]) {
571 link->ce_mask |= LINK_ATTR_MASTER;
574 if (tb[IFLA_CARRIER]) {
575 link->l_carrier =
nla_get_u8(tb[IFLA_CARRIER]);
576 link->ce_mask |= LINK_ATTR_CARRIER;
579 if (tb[IFLA_CARRIER_CHANGES]) {
580 link->l_carrier_changes =
nla_get_u32(tb[IFLA_CARRIER_CHANGES]);
581 link->ce_mask |= LINK_ATTR_CARRIER_CHANGES;
584 if (tb[IFLA_OPERSTATE]) {
585 link->l_operstate =
nla_get_u8(tb[IFLA_OPERSTATE]);
586 link->ce_mask |= LINK_ATTR_OPERSTATE;
589 if (tb[IFLA_LINKMODE]) {
590 link->l_linkmode =
nla_get_u8(tb[IFLA_LINKMODE]);
591 link->ce_mask |= LINK_ATTR_LINKMODE;
594 if (tb[IFLA_IFALIAS]) {
595 link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]);
596 if (link->l_ifalias == NULL)
598 link->ce_mask |= LINK_ATTR_IFALIAS;
601 if (tb[IFLA_NET_NS_FD]) {
603 link->ce_mask |= LINK_ATTR_NS_FD;
606 if (tb[IFLA_NET_NS_PID]) {
608 link->ce_mask |= LINK_ATTR_NS_PID;
614static int link_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
615 struct nlmsghdr *n,
struct nl_parser_param *pp)
617 _nl_auto_rtnl_link
struct rtnl_link *link = NULL;
621 struct ifinfomsg *ifi;
622 struct nlattr *tb[IFLA_MAX+1];
629 link->ce_msgtype = n->nlmsg_type;
631 if (!nlmsg_valid_hdr(n,
sizeof(*ifi)))
632 return -NLE_MSG_TOOSHORT;
635 link->l_family = family = ifi->ifi_family;
636 link->l_arptype = ifi->ifi_type;
637 link->l_index = ifi->ifi_index;
638 link->l_flags = ifi->ifi_flags;
639 link->l_change = ifi->ifi_change;
640 link->ce_mask = (LINK_ATTR_FAMILY |
641 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
642 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
644 if ((link->l_af_ops = af_lookup_and_alloc(link, family))) {
646 _NL_STATIC_ASSERT (
sizeof(rtln_link_policy) ==
sizeof(real_link_policy));
647 memcpy(&real_link_policy, rtln_link_policy,
sizeof(rtln_link_policy));
648 memcpy(&real_link_policy[IFLA_PROTINFO],
651 link_policy = real_link_policy;
655 af_ops_family = link->l_af_ops;
657 err =
nlmsg_parse(n,
sizeof(*ifi), tb, IFLA_MAX, link_policy);
661 err = rtnl_link_info_parse(link, tb);
665 if (tb[IFLA_NUM_VF]) {
667 link->ce_mask |= LINK_ATTR_NUM_VF;
668 if (link->l_num_vf && tb[IFLA_VFINFO_LIST]) {
669 if ((err = rtnl_link_sriov_parse_vflist(link, tb)) < 0)
671 link->ce_mask |= LINK_ATTR_VF_LIST;
675 if (tb[IFLA_LINKINFO]) {
676 struct nlattr *li[IFLA_INFO_MAX+1];
683 if (li[IFLA_INFO_KIND]) {
692 if ( (af = nl_str2af(kind)) >= 0
694 && (link->l_af_ops = af_lookup_and_alloc(link, af))) {
700 ops = link->l_info_ops;
704 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
705 err = ops->
io_parse(link, li[IFLA_INFO_DATA],
706 li[IFLA_INFO_XSTATS]);
714 link->ce_mask |= LINK_ATTR_LINKINFO;
717 if (li[IFLA_INFO_SLAVE_KIND]) {
724 link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND;
728 if ( tb[IFLA_PROTINFO]
732 link->l_af_data[link->l_family]);
735 link->ce_mask |= LINK_ATTR_PROTINFO;
738 if (tb[IFLA_AF_SPEC]) {
746 link->l_af_data[af_ops_family->
ao_family]);
749 link->ce_mask |= LINK_ATTR_AF_SPEC;
750 }
else if (family == AF_UNSPEC) {
751 struct nlattr *af_attr;
757 af_ops = af_lookup_and_alloc(link,
nla_type(af_attr));
759 char *af_data = link->l_af_data[
nla_type(af_attr)];
766 link->ce_mask |= LINK_ATTR_AF_SPEC;
768 NL_DBG(3,
"IFLA_AF_SPEC parsing not implemented for family %d\n",
773 if (tb[IFLA_PROMISCUITY]) {
774 link->l_promiscuity =
nla_get_u32(tb[IFLA_PROMISCUITY]);
775 link->ce_mask |= LINK_ATTR_PROMISCUITY;
778 if (tb[IFLA_NUM_TX_QUEUES]) {
779 link->l_num_tx_queues =
nla_get_u32(tb[IFLA_NUM_TX_QUEUES]);
780 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
783 if (tb[IFLA_NUM_RX_QUEUES]) {
784 link->l_num_rx_queues =
nla_get_u32(tb[IFLA_NUM_RX_QUEUES]);
785 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
788 if (tb[IFLA_GSO_MAX_SEGS]) {
789 link->l_gso_max_segs =
nla_get_u32(tb[IFLA_GSO_MAX_SEGS]);
790 link->ce_mask |= LINK_ATTR_GSO_MAX_SEGS;
793 if (tb[IFLA_GSO_MAX_SIZE]) {
794 link->l_gso_max_size =
nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
795 link->ce_mask |= LINK_ATTR_GSO_MAX_SIZE;
798 if (tb[IFLA_GROUP]) {
800 link->ce_mask |= LINK_ATTR_GROUP;
803 if (tb[IFLA_PHYS_PORT_ID]) {
805 if (link->l_phys_port_id == NULL)
807 link->ce_mask |= LINK_ATTR_PHYS_PORT_ID;
810 if (tb[IFLA_PHYS_PORT_NAME]) {
811 nla_strlcpy(link->l_phys_port_name, tb[IFLA_PHYS_PORT_NAME], IFNAMSIZ);
812 link->ce_mask |= LINK_ATTR_PHYS_PORT_NAME;
815 if (tb[IFLA_PHYS_SWITCH_ID]) {
817 if (link->l_phys_switch_id == NULL)
819 link->ce_mask |= LINK_ATTR_PHYS_SWITCH_ID;
822 return pp->pp_cb((
struct nl_object *) link, pp);
825static int link_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
827 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
828 int family = cache->c_iarg1;
829 struct ifinfomsg hdr = { .ifi_family = family };
832 __u32 ext_filter_mask = RTEXT_FILTER_VF;
838 if (
nlmsg_append(msg, &hdr,
sizeof(hdr), NLMSG_ALIGNTO) < 0)
843 err = ops->
ao_get_af(msg, &ext_filter_mask);
848 if (ext_filter_mask) {
849 err =
nla_put(msg, IFLA_EXT_MASK,
sizeof(ext_filter_mask), &ext_filter_mask);
861static void link_dump_line(
struct nl_object *obj,
struct nl_dump_params *p)
864 struct nl_cache *cache = obj->ce_cache;
866 int fetched_cache = 0;
873 if (link->l_family != AF_UNSPEC)
874 nl_dump_line(p,
"%s ", nl_af2str(link->l_family, buf,
sizeof(buf)));
876 nl_dump_line(p,
"%s %s ", link->l_name,
877 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
885 if (link->ce_mask & LINK_ATTR_MASTER) {
889 nl_dump(p,
"master %s ", master ? master->l_name :
"inv");
891 nl_dump(p,
"master %d ", link->l_master);
894 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
898 if (link->ce_mask & LINK_ATTR_LINK) {
900 && !(link->ce_mask & LINK_ATTR_LINK_NETNSID)) {
903 nl_dump(p,
"slave-of %s ", ll ? ll->l_name :
"NONE");
905 nl_dump(p,
"slave-of %d ", link->l_link);
907 if (link->ce_mask & LINK_ATTR_LINK_NETNSID)
908 nl_dump(p,
"link-netnsid %d ", link->l_link_netnsid);
910 if (link->ce_mask & LINK_ATTR_GROUP)
911 nl_dump(p,
"group %u ", link->l_group);
916 do_foreach_af(link, af_dump_line, p);
924static void link_dump_details(
struct nl_object *obj,
struct nl_dump_params *p)
929 link_dump_line(obj, p);
931 nl_dump_line(p,
" mtu %u ", link->l_mtu);
932 nl_dump(p,
"txqlen %u weight %u ", link->l_txqlen, link->l_weight);
934 if (link->ce_mask & LINK_ATTR_QDISC)
935 nl_dump(p,
"qdisc %s ", link->l_qdisc);
937 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
938 nl_dump(p,
"irq %u ", link->l_map.lm_irq);
940 if (link->ce_mask & LINK_ATTR_IFINDEX)
941 nl_dump(p,
"index %u ", link->l_index);
943 if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0)
944 nl_dump(p,
"promisc-mode (%u users) ", link->l_promiscuity);
948 if (link->ce_mask & LINK_ATTR_IFALIAS)
949 nl_dump_line(p,
" alias %s\n", link->l_ifalias);
951 nl_dump_line(p,
" ");
953 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
954 nl_dump(p,
"txq %u ", link->l_num_tx_queues);
956 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
957 nl_dump(p,
"rxq %u ", link->l_num_rx_queues);
959 if (link->ce_mask & LINK_ATTR_BRD)
963 if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
964 link->l_operstate != IF_OPER_UNKNOWN) {
965 rtnl_link_operstate2str(link->l_operstate, buf,
sizeof(buf));
969 if (link->ce_mask & LINK_ATTR_NUM_VF)
970 nl_dump(p,
"num-vf %u ", link->l_num_vf);
973 rtnl_link_mode2str(link->l_linkmode, buf,
sizeof(buf)));
976 rtnl_link_carrier2str(link->l_carrier, buf,
sizeof(buf)));
978 if (link->ce_mask & LINK_ATTR_CARRIER_CHANGES)
979 nl_dump(p,
" carrier-changes %u", link->l_carrier_changes);
986 do_foreach_af(link, af_dump_details, p);
988 if (link->ce_mask & LINK_ATTR_VF_LIST)
989 rtnl_link_sriov_dump_details(link, p);
992static void link_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
998 link_dump_details(obj, p);
1000 nl_dump_line(p,
" Stats: bytes packets errors "
1001 " dropped fifo-err compressed\n");
1005 strcpy(fmt,
" RX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
1006 fmt[9] = *unit ==
'B' ?
'9' :
'7';
1008 nl_dump_line(p, fmt, res, unit,
1017 strcpy(fmt,
" TX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
1018 fmt[9] = *unit ==
'B' ?
'9' :
'7';
1020 nl_dump_line(p, fmt, res, unit,
1027 nl_dump_line(p,
" Errors: length over crc "
1028 " frame missed multicast\n");
1030 nl_dump_line(p,
" RX %10" PRIu64
" %10" PRIu64
" %10"
1031 PRIu64
" %10" PRIu64
" %10" PRIu64
" %10"
1040 nl_dump_line(p,
" aborted carrier heartbeat "
1041 " window collision\n");
1043 nl_dump_line(p,
" TX %10" PRIu64
" %10" PRIu64
" %10"
1044 PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
1054 do_foreach_af(link, af_dump_stats, p);
1056 if (link->ce_mask & LINK_ATTR_VF_LIST)
1057 rtnl_link_sriov_dump_stats(link, p);
1061static int link_handle_event(
struct nl_object *a,
struct rtnl_link_event_cb *cb)
1064 struct nl_cache *c = dp_cache(a);
1067 if (l->l_change == ~0U) {
1068 if (l->ce_msgtype == RTM_NEWLINK)
1071 cb->le_unregister(l);
1076 if (l->l_change & IFF_SLAVE) {
1077 if (l->l_flags & IFF_SLAVE) {
1079 cb->le_new_bonding(l, m);
1083 cb->le_cancel_bonding(l);
1087 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
1088 dp_dump_line(p, line++,
"link %s changed state to %s.\n",
1089 l->l_name, l->l_flags & IFF_UP ?
"up" :
"down");
1091 if (l->l_change & IFF_PROMISC) {
1092 dp_new_line(p, line++);
1093 dp_dump(p,
"link %s %s promiscuous mode.\n",
1094 l->l_name, l->l_flags & IFF_PROMISC ?
"entered" :
"left");
1098 dp_dump_line(p, line++,
"link %s sent unknown event.\n",
1107static void link_keygen(
struct nl_object *obj, uint32_t *hashkey,
1111 unsigned int lkey_sz;
1112 struct link_hash_key {
1117 lkey_sz =
sizeof(lkey);
1118 lkey.l_index = link->l_index;
1119 lkey.l_family = link->l_family;
1121 *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz;
1123 NL_DBG(5,
"link %p key (dev %d fam %d) keysz %d, hash 0x%x\n",
1124 link, lkey.l_index, lkey.l_family, lkey_sz, *hashkey);
1129static uint64_t link_compare(
struct nl_object *_a,
struct nl_object *_b,
1130 uint64_t attrs,
int flags)
1136#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
1137 diff |= _DIFF(LINK_ATTR_IFINDEX, a->l_index != b->l_index);
1138 diff |= _DIFF(LINK_ATTR_MTU, a->l_mtu != b->l_mtu);
1139 diff |= _DIFF(LINK_ATTR_LINK, a->l_link != b->l_link);
1140 diff |= _DIFF(LINK_ATTR_LINK_NETNSID,
1141 a->l_link_netnsid != b->l_link_netnsid);
1142 diff |= _DIFF(LINK_ATTR_TXQLEN, a->l_txqlen != b->l_txqlen);
1143 diff |= _DIFF(LINK_ATTR_WEIGHT, a->l_weight != b->l_weight);
1144 diff |= _DIFF(LINK_ATTR_MASTER, a->l_master != b->l_master);
1145 diff |= _DIFF(LINK_ATTR_FAMILY, a->l_family != b->l_family);
1146 diff |= _DIFF(LINK_ATTR_OPERSTATE, a->l_operstate != b->l_operstate);
1147 diff |= _DIFF(LINK_ATTR_LINKMODE, a->l_linkmode != b->l_linkmode);
1148 diff |= _DIFF(LINK_ATTR_QDISC, strcmp(a->l_qdisc, b->l_qdisc));
1149 diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name));
1150 diff |= _DIFF(LINK_ATTR_ADDR,
nl_addr_cmp(a->l_addr, b->l_addr));
1151 diff |= _DIFF(LINK_ATTR_BRD,
nl_addr_cmp(a->l_bcast, b->l_bcast));
1152 diff |= _DIFF(LINK_ATTR_PERMANENT_ADDR,
nl_addr_cmp(a->l_paddr, b->l_paddr));
1153 diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
1154 diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf);
1155 diff |= _DIFF(LINK_ATTR_PROMISCUITY,
1156 a->l_promiscuity != b->l_promiscuity);
1157 diff |= _DIFF(LINK_ATTR_NUM_TX_QUEUES,
1158 a->l_num_tx_queues != b->l_num_tx_queues);
1159 diff |= _DIFF(LINK_ATTR_NUM_RX_QUEUES,
1160 a->l_num_rx_queues != b->l_num_rx_queues);
1161 diff |= _DIFF(LINK_ATTR_GROUP, a->l_group != b->l_group);
1163 if (flags & LOOSE_COMPARISON)
1164 diff |= _DIFF(LINK_ATTR_FLAGS,
1165 (a->l_flags ^ b->l_flags) & b->l_flag_mask);
1167 diff |= _DIFF(LINK_ATTR_FLAGS, a->l_flags != b->l_flags);
1172 if (a->l_family == b->l_family) {
1174 goto protinfo_mismatch;
1182 diff |= _DIFF(LINK_ATTR_PROTINFO, 1);
1188static const struct trans_tbl link_attrs[] = {
1189 __ADD(LINK_ATTR_MTU, mtu),
1190 __ADD(LINK_ATTR_LINK, link),
1191 __ADD(LINK_ATTR_TXQLEN, txqlen),
1192 __ADD(LINK_ATTR_WEIGHT, weight),
1193 __ADD(LINK_ATTR_MASTER, master),
1194 __ADD(LINK_ATTR_QDISC, qdisc),
1195 __ADD(LINK_ATTR_MAP, map),
1196 __ADD(LINK_ATTR_ADDR, address),
1197 __ADD(LINK_ATTR_BRD, broadcast),
1198 __ADD(LINK_ATTR_FLAGS, flags),
1199 __ADD(LINK_ATTR_IFNAME, name),
1200 __ADD(LINK_ATTR_IFINDEX, ifindex),
1201 __ADD(LINK_ATTR_FAMILY, family),
1202 __ADD(LINK_ATTR_ARPTYPE, arptype),
1203 __ADD(LINK_ATTR_STATS, stats),
1204 __ADD(LINK_ATTR_CHANGE, change),
1205 __ADD(LINK_ATTR_OPERSTATE, operstate),
1206 __ADD(LINK_ATTR_LINKMODE, linkmode),
1207 __ADD(LINK_ATTR_IFALIAS, ifalias),
1208 __ADD(LINK_ATTR_NUM_VF, num_vf),
1209 __ADD(LINK_ATTR_PROMISCUITY, promiscuity),
1210 __ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues),
1211 __ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues),
1212 __ADD(LINK_ATTR_GSO_MAX_SEGS, gso_max_segs),
1213 __ADD(LINK_ATTR_GSO_MAX_SIZE, gso_max_size),
1214 __ADD(LINK_ATTR_GROUP, group),
1215 __ADD(LINK_ATTR_CARRIER, carrier),
1216 __ADD(LINK_ATTR_CARRIER_CHANGES, carrier_changes),
1217 __ADD(LINK_ATTR_PHYS_PORT_ID, phys_port_id),
1218 __ADD(LINK_ATTR_PHYS_PORT_NAME, phys_port_name),
1219 __ADD(LINK_ATTR_PHYS_SWITCH_ID, phys_switch_id),
1220 __ADD(LINK_ATTR_NS_FD, ns_fd),
1221 __ADD(LINK_ATTR_NS_PID, ns_pid),
1222 __ADD(LINK_ATTR_LINK_NETNSID, link_netnsid),
1225static char *link_attrs2str(
int attrs,
char *buf,
size_t len)
1227 return __flags2str(attrs, buf, len, link_attrs,
1228 ARRAY_SIZE(link_attrs));
1263 struct nl_cache **result,
unsigned int flags)
1265 struct nl_cache * cache;
1272 cache->c_iarg1 = family;
1335 if (cache->c_ops != &rtnl_link_ops)
1338 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
1339 if (link->l_index == ((
unsigned)ifindex)) {
1368 if (cache->c_ops != &rtnl_link_ops)
1371 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
1372 if (!strcmp(name, link->l_name)) {
1396 struct nl_msg **result)
1398 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
1399 struct ifinfomsg ifi;
1400 __u32 vf_mask = RTEXT_FILTER_VF;
1402 if (ifindex <= 0 && !name) {
1403 APPBUG(
"ifindex or name must be specified");
1404 return -NLE_MISSING_ATTR;
1407 memset(&ifi, 0,
sizeof(ifi));
1413 ifi.ifi_index = ifindex;
1415 _NL_RETURN_ON_PUT_ERR(
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO));
1420 _NL_RETURN_ON_PUT_ERR(
nla_put(msg, IFLA_EXT_MASK,
sizeof(vf_mask), &vf_mask));
1422 *result = _nl_steal_pointer(&msg);
1450 _nl_auto_rtnl_link
struct rtnl_link *link = NULL;
1451 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
1464 if ( syserr == -EINVAL
1472 return -NLE_OPNOTSUPP;
1478 if (err == 0 && link)
1481 *result = _nl_steal_pointer(&link);
1502 _nl_auto_rtnl_link
struct rtnl_link *link = NULL;
1506 _nl_strncpy_trunc(dst, link->l_name, len);
1524 _nl_auto_rtnl_link
struct rtnl_link *link = NULL;
1528 return link->l_index;
1535int rtnl_link_fill_info(
struct nl_msg *msg,
struct rtnl_link *link)
1537 if (link->ce_mask & LINK_ATTR_ADDR)
1540 if (link->ce_mask & LINK_ATTR_BRD)
1543 if (link->ce_mask & LINK_ATTR_MTU)
1546 if (link->ce_mask & LINK_ATTR_TXQLEN)
1549 if (link->ce_mask & LINK_ATTR_WEIGHT)
1552 if (link->ce_mask & LINK_ATTR_IFNAME)
1555 if (link->ce_mask & LINK_ATTR_OPERSTATE)
1556 NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate);
1558 if (link->ce_mask & LINK_ATTR_CARRIER)
1559 NLA_PUT_U8(msg, IFLA_CARRIER, link->l_carrier);
1561 if (link->ce_mask & LINK_ATTR_LINKMODE)
1562 NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode);
1564 if (link->ce_mask & LINK_ATTR_IFALIAS)
1567 if (link->ce_mask & LINK_ATTR_LINK)
1570 if (link->ce_mask & LINK_ATTR_LINK_NETNSID)
1571 NLA_PUT_S32(msg, IFLA_LINK_NETNSID, link->l_link_netnsid);
1573 if (link->ce_mask & LINK_ATTR_MASTER)
1576 if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
1577 NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues);
1579 if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
1580 NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues);
1582 if (link->ce_mask & LINK_ATTR_NS_FD)
1585 if (link->ce_mask & LINK_ATTR_NS_PID)
1586 NLA_PUT_U32(msg, IFLA_NET_NS_PID, link->l_ns_pid);
1591 return -NLE_MSGSIZE;
1594static int build_link_msg(
int cmd,
struct ifinfomsg *hdr,
1595 struct rtnl_link *link,
int flags,
struct nl_msg **result)
1597 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
1598 struct nlattr *af_spec;
1604 if (
nlmsg_append(msg, hdr,
sizeof(*hdr), NLMSG_ALIGNTO) < 0)
1605 goto nla_put_failure;
1607 if (rtnl_link_fill_info(msg, link))
1608 goto nla_put_failure;
1610 if (link->ce_mask & LINK_ATTR_GROUP)
1613 if (link->ce_mask & (LINK_ATTR_LINKINFO|LINK_ATTR_LINKINFO_SLAVE_KIND)) {
1614 struct nlattr *info;
1617 goto nla_put_failure;
1619 if (link->ce_mask & LINK_ATTR_LINKINFO) {
1622 if (link->l_info_ops) {
1625 goto nla_put_failure;
1629 if (link->ce_mask & LINK_ATTR_LINKINFO_SLAVE_KIND) {
1630 NLA_PUT_STRING(msg, IFLA_INFO_SLAVE_KIND, link->l_info_slave_kind);
1636 if (link->ce_mask & LINK_ATTR_VF_LIST) {
1637 if (rtnl_link_sriov_fill_vflist(msg, link) < 0)
1638 goto nla_put_failure;
1641 if (do_foreach_af(link, af_fill_pi, msg) < 0)
1642 goto nla_put_failure;
1645 goto nla_put_failure;
1647 if (do_foreach_af(link, af_fill, msg) < 0)
1648 goto nla_put_failure;
1652 *result = _nl_steal_pointer(&msg);
1656 return -NLE_MSGSIZE;
1681 struct nl_msg **result)
1683 struct ifinfomsg ifi = {
1684 .ifi_family = link->l_family,
1685 .ifi_index = link->l_index,
1686 .ifi_flags = link->l_flags,
1687 .ifi_change = link->l_flag_mask,
1690 return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result);
1744 struct nl_msg **result)
1746 struct ifinfomsg ifi = {
1747 .ifi_family = orig->l_family,
1748 .ifi_index = orig->l_index,
1752 if (changes->ce_mask & LINK_ATTR_FLAGS) {
1753 ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask;
1754 ifi.ifi_flags |= changes->l_flags;
1755 ifi.ifi_change = changes->l_flag_mask;
1758 if (changes->l_family && changes->l_family != orig->l_family) {
1759 APPBUG(
"link change: family is immutable");
1760 return -NLE_IMMUTABLE;
1764 if (orig->ce_mask & LINK_ATTR_IFINDEX &&
1765 orig->ce_mask & LINK_ATTR_IFNAME &&
1766 changes->ce_mask & LINK_ATTR_IFNAME &&
1767 !strcmp(orig->l_name, changes->l_name))
1768 changes->ce_mask &= ~LINK_ATTR_IFNAME;
1770 rt = af_request_type(orig->l_family, changes);
1772 if ((err = build_link_msg(rt, &ifi, changes, flags, result)) < 0)
1816 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
1829 err = wait_for_ack(sk);
1830 if ( err == -NLE_OPNOTSUPP
1831 && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) {
1832 msg->nm_nlh->nlmsg_type = RTM_SETLINK;
1864 struct nl_msg **result)
1866 _nl_auto_nl_msg
struct nl_msg *msg = NULL;
1867 struct ifinfomsg ifi = {
1868 .ifi_index = link->l_index,
1871 if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) {
1872 APPBUG(
"ifindex or name must be specified");
1873 return -NLE_MISSING_ATTR;
1879 _NL_RETURN_ON_PUT_ERR(
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO));
1881 if (link->ce_mask & LINK_ATTR_IFNAME)
1882 _NL_RETURN_ON_PUT_ERR(
nla_put_string(msg, IFLA_IFNAME, link->l_name));
1884 *result = _nl_steal_pointer(&msg);
1966 _nl_strncpy_trunc(link->l_name, name,
sizeof(link->l_name));
1967 link->ce_mask |= LINK_ATTR_IFNAME;
1980 return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL;
1990 link->l_group = group;
1991 link->ce_mask |= LINK_ATTR_GROUP;
2002 return link->l_group;
2005static inline void __assign_addr(
struct rtnl_link *link,
struct nl_addr **pos,
2006 struct nl_addr *
new,
int flag)
2014 link->ce_mask |= flag;
2030 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
2044 return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL;
2057 return link->ce_mask & LINK_ATTR_PERMANENT_ADDR ? link->l_paddr : NULL;
2074 __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD);
2088 return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL;
2101 link->l_flag_mask |= flags;
2102 link->l_flags |= flags;
2103 link->ce_mask |= LINK_ATTR_FLAGS;
2116 link->l_flag_mask |= flags;
2117 link->l_flags &= ~flags;
2118 link->ce_mask |= LINK_ATTR_FLAGS;
2132 return link->l_flags;
2142 link->l_family = family;
2143 link->ce_mask |= LINK_ATTR_FAMILY;
2145 if (link->l_af_ops) {
2146 int ao_family = link->l_af_ops->
ao_family;
2148 af_free(link, link->l_af_ops, link->l_af_data[ao_family], NULL);
2149 link->l_af_data[ao_family] = NULL;
2152 link->l_af_ops = af_lookup_and_alloc(link, family);
2164 return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC;
2178 link->l_arptype = arptype;
2179 link->ce_mask |= LINK_ATTR_ARPTYPE;
2192 if (link->ce_mask & LINK_ATTR_ARPTYPE)
2193 return link->l_arptype;
2208 link->l_index = ifindex;
2209 link->ce_mask |= LINK_ATTR_IFINDEX;
2223 return link->l_index;
2237 link->ce_mask |= LINK_ATTR_MTU;
2265 link->l_txqlen = txqlen;
2266 link->ce_mask |= LINK_ATTR_TXQLEN;
2281 return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
2284void rtnl_link_set_link(
struct rtnl_link *link,
int ifindex)
2286 link->l_link = ifindex;
2287 link->ce_mask |= LINK_ATTR_LINK;
2290int rtnl_link_get_link(
struct rtnl_link *link)
2292 return link->l_link;
2305 link->l_link_netnsid = link_netnsid;
2306 link->ce_mask |= LINK_ATTR_LINK_NETNSID;
2322 if (!(link->ce_mask & LINK_ATTR_LINK_NETNSID))
2325 *out_link_netnsid = link->l_link_netnsid;
2338 link->l_master = ifindex;
2339 link->ce_mask |= LINK_ATTR_MASTER;
2351 return link->l_master;
2363 link->l_carrier = status;
2364 link->ce_mask |= LINK_ATTR_CARRIER;
2376 return link->l_carrier;
2388 if (!(link->ce_mask & LINK_ATTR_CARRIER_CHANGES))
2391 if (carrier_changes)
2392 *carrier_changes = link->l_carrier_changes;
2407 link->l_operstate = status;
2408 link->ce_mask |= LINK_ATTR_OPERSTATE;
2421 return link->l_operstate;
2434 link->l_linkmode = mode;
2435 link->ce_mask |= LINK_ATTR_LINKMODE;
2448 return link->l_linkmode;
2461 return link->l_ifalias;
2478 free(link->l_ifalias);
2481 link->l_ifalias = strdup(alias);
2482 link->ce_mask |= LINK_ATTR_IFALIAS;
2484 link->l_ifalias = NULL;
2485 link->ce_mask &= ~LINK_ATTR_IFALIAS;
2504 _nl_strncpy_trunc(link->l_qdisc, name,
sizeof(link->l_qdisc));
2505 link->ce_mask |= LINK_ATTR_QDISC;
2518 return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL;
2531 if (link->ce_mask & LINK_ATTR_NUM_VF) {
2532 *num_vf = link->l_num_vf;
2535 return -NLE_OPNOTSUPP;
2547 if (
id > RTNL_LINK_STATS_MAX)
2550 return link->l_stats[id];
2565 const uint64_t value)
2567 if (
id > RTNL_LINK_STATS_MAX)
2570 link->l_stats[id] = value;
2590 _nl_auto_free
char *kind = NULL;
2593 free(link->l_info_kind);
2594 link->ce_mask &= ~LINK_ATTR_LINKINFO;
2595 release_link_info(link);
2600 kind = strdup(type);
2607 _nl_clear_free(&kind);
2611 link->l_info_ops = io;
2614 link->l_info_kind = _nl_steal_pointer(&kind);
2615 link->ce_mask |= LINK_ATTR_LINKINFO;
2629 return link->l_info_kind;
2647 kind = strdup(type);
2652 free(link->l_info_slave_kind);
2653 link->l_info_slave_kind = kind;
2656 link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND;
2658 link->ce_mask &= ~LINK_ATTR_LINKINFO_SLAVE_KIND;
2671 return link->l_info_slave_kind;
2686 link->l_promiscuity = count;
2687 link->ce_mask |= LINK_ATTR_PROMISCUITY;
2699 return link->l_promiscuity;
2718 link->l_num_tx_queues = nqueues;
2719 link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
2730 return link->l_num_tx_queues;
2749 link->l_num_rx_queues = nqueues;
2750 link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
2761 return link->l_num_rx_queues;
2773 if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SEGS))
2777 *gso_max_segs = link->l_gso_max_segs;
2791 if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SIZE))
2795 *gso_max_size = link->l_gso_max_size;
2808 return link->l_phys_port_id;
2819 return link->l_phys_port_name;
2828struct nl_data *rtnl_link_get_phys_switch_id(
struct rtnl_link *link)
2830 return link->l_phys_switch_id;
2833void rtnl_link_set_ns_fd(
struct rtnl_link *link,
int fd)
2836 link->ce_mask |= LINK_ATTR_NS_FD;
2839int rtnl_link_get_ns_fd(
struct rtnl_link *link)
2841 return link->l_ns_fd;
2844void rtnl_link_set_ns_pid(
struct rtnl_link *link, pid_t pid)
2846 link->l_ns_pid = pid;
2847 link->ce_mask |= LINK_ATTR_NS_PID;
2850pid_t rtnl_link_get_ns_pid(
struct rtnl_link *link)
2852 return link->l_ns_pid;
2877 _nl_auto_rtnl_link
struct rtnl_link *link = NULL;
2902 return -NLE_OPNOTSUPP;
2982static const struct trans_tbl link_flags[] = {
2983 __ADD(IFF_LOOPBACK, loopback),
2984 __ADD(IFF_BROADCAST, broadcast),
2985 __ADD(IFF_POINTOPOINT, pointopoint),
2986 __ADD(IFF_MULTICAST, multicast),
2987 __ADD(IFF_NOARP, noarp),
2988 __ADD(IFF_ALLMULTI, allmulti),
2989 __ADD(IFF_PROMISC, promisc),
2990 __ADD(IFF_MASTER, master),
2991 __ADD(IFF_SLAVE, slave),
2992 __ADD(IFF_DEBUG, debug),
2993 __ADD(IFF_DYNAMIC, dynamic),
2994 __ADD(IFF_AUTOMEDIA, automedia),
2995 __ADD(IFF_PORTSEL, portsel),
2996 __ADD(IFF_NOTRAILERS, notrailers),
2998 __ADD(IFF_RUNNING, running),
2999 __ADD(IFF_LOWER_UP, lowerup),
3000 __ADD(IFF_DORMANT, dormant),
3001 __ADD(IFF_ECHO, echo),
3004char *rtnl_link_flags2str(
int flags,
char *buf,
size_t len)
3006 return __flags2str(flags, buf, len, link_flags,
3007 ARRAY_SIZE(link_flags));
3010int rtnl_link_str2flags(
const char *name)
3012 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
3015static const struct trans_tbl link_stats[] = {
3083char *rtnl_link_stat2str(
int st,
char *buf,
size_t len)
3085 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
3088int rtnl_link_str2stat(
const char *name)
3090 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
3093static const struct trans_tbl link_operstates[] = {
3094 __ADD(IF_OPER_UNKNOWN, unknown),
3095 __ADD(IF_OPER_NOTPRESENT, notpresent),
3096 __ADD(IF_OPER_DOWN, down),
3097 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown),
3098 __ADD(IF_OPER_TESTING, testing),
3099 __ADD(IF_OPER_DORMANT, dormant),
3100 __ADD(IF_OPER_UP, up),
3103char *rtnl_link_operstate2str(uint8_t st,
char *buf,
size_t len)
3105 return __type2str(st, buf, len, link_operstates,
3106 ARRAY_SIZE(link_operstates));
3109int rtnl_link_str2operstate(
const char *name)
3111 return __str2type(name, link_operstates,
3112 ARRAY_SIZE(link_operstates));
3115static const struct trans_tbl link_modes[] = {
3116 __ADD(IF_LINK_MODE_DEFAULT,
default),
3117 __ADD(IF_LINK_MODE_DORMANT, dormant),
3120static const struct trans_tbl carrier_states[] = {
3125char *rtnl_link_mode2str(uint8_t st,
char *buf,
size_t len)
3127 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
3130int rtnl_link_str2mode(
const char *name)
3132 return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
3135char *rtnl_link_carrier2str(uint8_t st,
char *buf,
size_t len)
3137 return __type2str(st, buf, len, carrier_states,
3138 ARRAY_SIZE(carrier_states));
3141int rtnl_link_str2carrier(
const char *name)
3143 return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states));
3146int rtnl_link_has_vf_list(
struct rtnl_link *link) {
3147 if (link->ce_mask & LINK_ATTR_VF_LIST)
3153void rtnl_link_set_vf_list(
struct rtnl_link *link)
3155 if (!rtnl_link_has_vf_list(link))
3156 link->ce_mask |= LINK_ATTR_VF_LIST;
3159void rtnl_link_unset_vf_list(
struct rtnl_link *link)
3161 if (rtnl_link_has_vf_list(link))
3162 link->ce_mask &= ~LINK_ATTR_VF_LIST;
3192 link->l_weight = weight;
3193 link->ce_mask |= LINK_ATTR_WEIGHT;
3201 return link->l_weight;
3206static struct nl_object_ops link_obj_ops = {
3207 .oo_name =
"route/link",
3209 .oo_free_data = link_free_data,
3210 .oo_clone = link_clone,
3216 .oo_compare = link_compare,
3217 .oo_keygen = link_keygen,
3218 .oo_attrs2str = link_attrs2str,
3219 .oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY,
3222static struct nl_af_group link_groups[] = {
3223 { AF_UNSPEC, RTNLGRP_LINK },
3224 { AF_BRIDGE, RTNLGRP_LINK },
3225 { AF_INET6, RTNLGRP_IPV6_IFINFO },
3226 { END_OF_GROUP_LIST },
3229static struct nl_cache_ops rtnl_link_ops = {
3230 .co_name =
"route/link",
3231 .co_hdrsize =
sizeof(
struct ifinfomsg),
3233 { RTM_NEWLINK, NL_ACT_NEW,
"new" },
3234 { RTM_DELLINK, NL_ACT_DEL,
"del" },
3235 { RTM_GETLINK, NL_ACT_GET,
"get" },
3236 { RTM_SETLINK, NL_ACT_CHANGE,
"set" },
3237 END_OF_MSGTYPES_LIST,
3239 .co_protocol = NETLINK_ROUTE,
3240 .co_groups = link_groups,
3241 .co_request_update = link_request_update,
3242 .co_msg_parser = link_msg_parser,
3243 .co_obj_ops = &link_obj_ops,
3246static void _nl_init link_init(
void)
3251static void _nl_exit link_exit(
void)
int nl_addr_iszero(const struct nl_addr *addr)
Returns true if the address consists of all zeros.
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
void nl_addr_set_family(struct nl_addr *addr, int family)
Set address family.
int nl_addr_guess_family(const struct nl_addr *addr)
Guess address family of abstract address based on address size.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
#define NLA_PUT_S32(msg, attrtype, value)
Add 32 bit signed integer attribute to netlink message.
int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
Add string attribute to netlink message.
int nla_type(const struct nlattr *nla)
Return type of the attribute.
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
#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.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
char * nla_get_string(const struct nlattr *nla)
Return payload of string attribute.
int32_t nla_get_s32(const struct nlattr *nla)
Return payload of 32 bit signed integer attribute.
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.
@ NLA_STRING
NUL terminated character string.
@ NLA_UNSPEC
Unspecified type, binary data chunk.
@ NLA_NESTED
Nested attributes.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags)
Set cache flags.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
struct nl_data * nl_data_clone(const struct nl_data *src)
Clone an abstract data object.
void nl_data_free(struct nl_data *data)
Free an abstract data object.
struct nl_data * nl_data_alloc_attr(const struct nlattr *nla)
Allocate abstract data object based on netlink attribute.
void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops)
Give back reference to a set of operations.
void * rtnl_link_af_alloc(struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Allocate and return data buffer for link address family modules.
int rtnl_link_info_data_compare(struct rtnl_link *a, struct rtnl_link *b, int flags)
Compare link info data.
void rtnl_link_info_ops_get(struct rtnl_link_info_ops *ops)
Take reference to a set of operations.
struct rtnl_link_info_ops * rtnl_link_info_ops_lookup(const char *name)
Return operations of a specific link info type.
int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b, int family)
Compare af data for a link address family.
void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops)
Give back reference to a set of operations.
struct rtnl_link_af_ops * rtnl_link_af_ops_lookup(const unsigned int family)
Return operations of a specific link address family.
int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave)
Release slave link from its master.
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr)
Set link layer broadcast address of link object.
void rtnl_link_set_carrier(struct rtnl_link *link, uint8_t status)
Set carrier of link object.
uint8_t rtnl_link_get_linkmode(struct rtnl_link *link)
Return link mode of link object.
uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id)
Return value of link statistics counter.
int rtnl_link_get_master(struct rtnl_link *link)
Return master link of link object.
void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
Set Maximum Transmission Unit of link object.
int rtnl_link_set_link_netnsid(struct rtnl_link *link, int32_t link_netnsid)
Set the netnsid of the link.
uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link)
Return number of RX queues.
unsigned int rtnl_link_get_weight(struct rtnl_link *link)
int rtnl_link_release_ifindex(struct nl_sock *sock, int slave)
Release slave link from its master.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
Set link layer address of link object.
void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype)
Set hardware type of link object.
void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags of link object.
void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode)
Set link mode of link object.
uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link)
Return number of TX queues.
uint32_t rtnl_link_get_group(struct rtnl_link *link)
Return the group identifier of link object.
struct nl_data * rtnl_link_get_phys_port_id(struct rtnl_link *link)
Return physical port id of link object.
const char * rtnl_link_get_slave_type(const struct rtnl_link *link)
Return type of enslaved link.
uint8_t rtnl_link_get_operstate(struct rtnl_link *link)
Return operational status of link object.
int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link)
Delete link.
struct nl_addr * rtnl_link_get_broadcast(struct rtnl_link *link)
Return link layer broadcast address of link object.
int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf)
Return number of PCI virtual functions of link object.
int rtnl_link_set_slave_type(struct rtnl_link *link, const char *type)
Set type of slave link object.
char * rtnl_link_get_phys_port_name(struct rtnl_link *link)
Return physical port name of link object.
int rtnl_link_build_change_request(struct rtnl_link *orig, struct rtnl_link *changes, int flags, struct nl_msg **result)
Build a netlink message requesting the modification of link.
void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias)
Set alias name of link object (SNMP IfAlias)
uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link)
Return link promiscuity count.
void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues)
Set number of TX queues.
int rtnl_link_build_add_request(struct rtnl_link *link, int flags, struct nl_msg **result)
Build a netlink message requesting the addition of new virtual link.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
char * rtnl_link_get_type(struct rtnl_link *link)
Return type of link.
char * rtnl_link_get_qdisc(struct rtnl_link *link)
Return name of queueing discipline of link object.
void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues)
Set number of RX queues.
struct rtnl_link * rtnl_link_get_by_name(struct nl_cache *cache, const char *name)
Lookup link in cache by link name.
int rtnl_link_name2i(struct nl_cache *cache, const char *name)
Translate link name to corresponding interface index.
int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
Allocate link cache and fill in all configured links.
unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
Get hardware type of link object.
void rtnl_link_set_group(struct rtnl_link *link, uint32_t group)
Set the group identifier of a link object.
int rtnl_link_get_family(struct rtnl_link *link)
Return address family of link object.
int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result)
Get a link object directly from kernel.
void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags of link object.
void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name)
Set queueing discipline name of link object.
struct rtnl_link * rtnl_link_get(struct nl_cache *cache, int ifindex)
Lookup link in cache by interface index.
unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
Return transmission queue length.
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, const uint64_t value)
Set value of link statistics counter.
int rtnl_link_alloc_cache_flags(struct nl_sock *sk, int family, struct nl_cache **result, unsigned int flags)
Allocate link cache and fill in all configured links.
char * rtnl_link_get_info_type(struct rtnl_link *link)
struct nl_addr * rtnl_link_get_perm_addr(struct rtnl_link *link)
Return permanent link layer adress of link object.
int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave)
Enslave slave link to master link.
int rtnl_link_build_delete_request(const struct rtnl_link *link, struct nl_msg **result)
Build a netlink message requesting the deletion of a link.
void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status)
Set operational status of link object.
int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master, struct rtnl_link *slave)
Enslave slave link to master link.
void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count)
Set link promiscuity count.
int rtnl_link_get_gso_max_segs(struct rtnl_link *link, uint32_t *gso_max_segs)
Return maximum number of segments for generic segmentation offload.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate interface index to corresponding link name.
void rtnl_link_set_family(struct rtnl_link *link, int family)
Set address family of link object.
uint8_t rtnl_link_get_carrier(struct rtnl_link *link)
Return carrier status of link object.
void rtnl_link_put(struct rtnl_link *link)
Release a link object reference.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
int rtnl_link_set_info_type(struct rtnl_link *link, const char *type)
const char * rtnl_link_get_ifalias(struct rtnl_link *link)
Return alias name of link object (SNMP IfAlias)
int rtnl_link_get_gso_max_size(struct rtnl_link *link, uint32_t *gso_max_size)
Return maximum size for generic segmentation offload.
void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
Set master link of link object.
unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
Return maximum transmission unit of link object.
void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
Set transmission queue length.
int rtnl_link_build_get_request(int ifindex, const char *name, struct nl_msg **result)
Construct RTM_GETLINK netlink message.
void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
Set interface index of link object.
struct nl_addr * rtnl_link_get_addr(struct rtnl_link *link)
Return link layer address of link object.
int rtnl_link_get_carrier_changes(struct rtnl_link *link, uint32_t *carrier_changes)
Return carrier on/off changes of link object.
int rtnl_link_get_link_netnsid(const struct rtnl_link *link, int32_t *out_link_netnsid)
Get the netnsid of the link.
unsigned int rtnl_link_get_flags(struct rtnl_link *link)
Return flags of link object.
int rtnl_link_get_ifindex(struct rtnl_link *link)
Return interface index of link object.
int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig, struct rtnl_link *changes, int flags)
Change link.
@ RTNL_LINK_IP6_INBCASTOCTETS
@ RTNL_LINK_RX_COMPRESSED
@ RTNL_LINK_REASM_OVERLAPS
@ RTNL_LINK_IP6_INTRUNCATEDPKTS
@ RTNL_LINK_IP6_INNOROUTES
@ RTNL_LINK_IP6_OUTMCASTOCTETS
@ RTNL_LINK_IP6_INMCASTPKTS
@ RTNL_LINK_IP6_OUTBCASTOCTETS
@ RTNL_LINK_IP6_INDELIVERS
@ RTNL_LINK_IP6_REASMTIMEOUT
@ RTNL_LINK_IP6_OUTOCTETS
@ RTNL_LINK_ICMP6_INERRORS
@ RTNL_LINK_IP6_FRAGFAILS
@ RTNL_LINK_ICMP6_OUTMSGS
@ RTNL_LINK_IP6_CSUMERRORS
@ RTNL_LINK_IP6_INUNKNOWNPROTOS
@ RTNL_LINK_ICMP6_CSUMERRORS
@ RTNL_LINK_IP6_INBCASTPKTS
@ RTNL_LINK_TX_COMPRESSED
@ RTNL_LINK_IP6_INHDRERRORS
@ RTNL_LINK_IP6_REASMREQDS
@ RTNL_LINK_TX_CARRIER_ERR
@ RTNL_LINK_RX_MISSED_ERR
@ RTNL_LINK_IP6_OUTFORWDATAGRAMS
@ RTNL_LINK_IP6_INDISCARDS
@ RTNL_LINK_IP6_NOECTPKTS
@ RTNL_LINK_IP6_OUTNOROUTES
@ RTNL_LINK_IP6_OUTDISCARDS
@ RTNL_LINK_IP6_FRAGCREATES
@ RTNL_LINK_ICMP6_OUTERRORS
@ RTNL_LINK_IP6_INMCASTOCTETS
@ RTNL_LINK_IP6_INADDRERRORS
@ RTNL_LINK_IP6_INTOOBIGERRORS
@ RTNL_LINK_IP6_OUTMCASTPKTS
@ RTNL_LINK_IP6_OUTBCASTPKTS
@ RTNL_LINK_IP6_REASMFAILS
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
#define NL_AUTO_SEQ
May be used to refer to a sequence number which should be automatically set just before sending the m...
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
Finalize and transmit Netlink message.
int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
Finalize and transmit Netlink message and wait for ACK or error message.
int nl_pickup_keep_syserr(struct nl_sock *sk, int(*parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *), struct nl_object **result, int *syserror)
Pickup netlink answer, parse is and return object with preserving system error.
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
@ NL_DUMP_STATS
Dump all attributes including statistics.
@ 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.
Available operations to modules implementing a link address family.
const struct nla_policy * ao_protinfo_policy
Validation policy for IFLA_PROTINFO attribute.
int(* ao_parse_protinfo)(struct rtnl_link *, struct nlattr *, void *)
Called if a IFLA_PROTINFO attribute needs to be parsed.
void(* ao_free)(struct rtnl_link *, void *)
Called when the link gets freed.
int(* ao_fill_pi)(struct rtnl_link *, struct nl_msg *msg, void *)
Called if a link message is sent to the kernel.
const int ao_fill_af_no_nest
IFLA_AF_SPEC nesting override.
const unsigned int ao_family
The address family this operations set implements.
void(* ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *, struct nl_dump_params *, void *)
Dump address family specific link attributes.
int(* ao_parse_af)(struct rtnl_link *, struct nlattr *, void *)
Called if a IFLA_AF_SPEC attribute needs to be parsed.
int(* ao_parse_af_full)(struct rtnl_link *, struct nlattr *, void *)
Called if the full IFLA_AF_SPEC data needs to be parsed.
int(* ao_get_af)(struct nl_msg *msg, uint32_t *ext_filter_mask)
Called for GETLINK message to the kernel.
int(* ao_fill_af)(struct rtnl_link *, struct nl_msg *msg, void *)
Called if a link message is sent to the kernel.
const int ao_fill_pi_flags
PROTINFO type.
void *(* ao_clone)(struct rtnl_link *, void *)
Called when the link is cloned, must allocate a clone of the address family specific buffer and retur...
Available operations to modules implementing a link info type.
void(* io_dump[NL_DUMP_MAX+1])(struct rtnl_link *, struct nl_dump_params *)
Called when the link object is dumped.
void(* io_free)(struct rtnl_link *)
Called to release all resources previously allocated in either io_alloc() or io_parse().
int(* io_alloc)(struct rtnl_link *)
Called to assign an info type to a link.
int(* io_parse)(struct rtnl_link *, struct nlattr *, struct nlattr *)
Called to parse the link info attribute.
int(* io_clone)(struct rtnl_link *, struct rtnl_link *)
Called when a link object is cloned.
int(* io_put_attrs)(struct nl_msg *, struct rtnl_link *)
Called when construction a link netlink message.