21 #include <netlink-local.h>
22 #include <netlink/netlink.h>
23 #include <netlink/attr.h>
24 #include <netlink/utils.h>
25 #include <netlink/object.h>
26 #include <netlink/route/rtnl.h>
27 #include <netlink/route/link.h>
28 #include <netlink/route/link/api.h>
31 #define LINK_ATTR_MTU 0x0001
32 #define LINK_ATTR_LINK 0x0002
33 #define LINK_ATTR_TXQLEN 0x0004
34 #define LINK_ATTR_WEIGHT 0x0008
35 #define LINK_ATTR_MASTER 0x0010
36 #define LINK_ATTR_QDISC 0x0020
37 #define LINK_ATTR_MAP 0x0040
38 #define LINK_ATTR_ADDR 0x0080
39 #define LINK_ATTR_BRD 0x0100
40 #define LINK_ATTR_FLAGS 0x0200
41 #define LINK_ATTR_IFNAME 0x0400
42 #define LINK_ATTR_IFINDEX 0x0800
43 #define LINK_ATTR_FAMILY 0x1000
44 #define LINK_ATTR_ARPTYPE 0x2000
45 #define LINK_ATTR_STATS 0x4000
46 #define LINK_ATTR_CHANGE 0x8000
47 #define LINK_ATTR_OPERSTATE 0x10000
48 #define LINK_ATTR_LINKMODE 0x20000
49 #define LINK_ATTR_LINKINFO 0x40000
50 #define LINK_ATTR_IFALIAS 0x80000
51 #define LINK_ATTR_NUM_VF 0x100000
74 void *data,
void *arg)
85 void *data,
void *arg)
97 void *data,
void *arg)
99 struct nl_msg *msg = arg;
100 struct nlattr *af_attr;
109 if ((err = ops->
ao_fill_af(link, arg, data)) < 0)
118 void *data,
void *arg)
129 void *data,
void *arg)
140 void *data,
void *arg)
150 static int do_foreach_af(
struct rtnl_link *link,
157 for (i = 0; i < AF_MAX; i++) {
158 if (link->l_af_data[i]) {
164 if ((err = cb(link, ops, link->l_af_data[i], arg)) < 0)
172 static void release_link_info(
struct rtnl_link *link)
180 link->l_info_ops = NULL;
184 static void link_free_data(
struct nl_object *c)
186 struct rtnl_link *link = nl_object_priv(c);
191 if ((io = link->l_info_ops) != NULL)
192 release_link_info(link);
194 nl_addr_put(link->l_addr);
195 nl_addr_put(link->l_bcast);
197 free(link->l_ifalias);
198 free(link->l_info_kind);
200 do_foreach_af(link, af_free, NULL);
206 struct rtnl_link *dst = nl_object_priv(_dst);
207 struct rtnl_link *src = nl_object_priv(_src);
219 if (!(dst->l_ifalias = strdup(src->l_ifalias)))
222 if (src->l_info_kind)
223 if (!(dst->l_info_kind = strdup(src->l_info_kind)))
226 if (src->l_info_ops && src->l_info_ops->io_clone) {
227 err = src->l_info_ops->io_clone(dst, src);
232 if ((err = do_foreach_af(src, af_clone, dst)) < 0)
238 static struct nla_policy link_policy[IFLA_MAX+1] = {
240 .maxlen = IFNAMSIZ },
241 [IFLA_MTU] = { .type =
NLA_U32 },
242 [IFLA_TXQLEN] = { .type =
NLA_U32 },
243 [IFLA_LINK] = { .type =
NLA_U32 },
244 [IFLA_WEIGHT] = { .type =
NLA_U32 },
245 [IFLA_MASTER] = { .type =
NLA_U32 },
246 [IFLA_OPERSTATE]= { .type =
NLA_U8 },
247 [IFLA_LINKMODE] = { .type =
NLA_U8 },
250 .maxlen = IFQDISCSIZ },
251 [IFLA_STATS] = { .minlen =
sizeof(
struct rtnl_link_stats) },
252 [IFLA_STATS64] = { .minlen =
sizeof(
struct rtnl_link_stats64) },
253 [IFLA_MAP] = { .minlen =
sizeof(
struct rtnl_link_ifmap) },
254 [IFLA_IFALIAS] = { .type =
NLA_STRING, .maxlen = IFALIASZ },
255 [IFLA_NUM_VF] = { .type =
NLA_U32 },
259 static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = {
265 static int link_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
269 struct ifinfomsg *ifi;
270 struct nlattr *tb[IFLA_MAX+1];
280 link->ce_msgtype = n->nlmsg_type;
282 if (!nlmsg_valid_hdr(n,
sizeof(*ifi)))
283 return -NLE_MSG_TOOSHORT;
286 link->l_family = family = ifi->ifi_family;
287 link->l_arptype = ifi->ifi_type;
288 link->l_index = ifi->ifi_index;
289 link->l_flags = ifi->ifi_flags;
290 link->l_change = ifi->ifi_change;
291 link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY |
292 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
293 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
295 if ((af_ops = af_lookup_and_alloc(link, family))) {
297 memcpy(&link_policy[IFLA_PROTINFO],
303 err =
nlmsg_parse(n,
sizeof(*ifi), tb, IFLA_MAX, link_policy);
307 if (tb[IFLA_IFNAME] == NULL) {
308 err = -NLE_MISSING_ATTR;
312 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
315 if (tb[IFLA_STATS]) {
316 struct rtnl_link_stats *st =
nla_data(tb[IFLA_STATS]);
345 link->ce_mask |= LINK_ATTR_STATS;
348 if (tb[IFLA_STATS64]) {
356 struct rtnl_link_stats64 st;
359 sizeof(
struct rtnl_link_stats64));
388 link->ce_mask |= LINK_ATTR_STATS;
391 if (tb[IFLA_TXQLEN]) {
393 link->ce_mask |= LINK_ATTR_TXQLEN;
398 link->ce_mask |= LINK_ATTR_MTU;
401 if (tb[IFLA_ADDRESS]) {
403 if (link->l_addr == NULL) {
407 nl_addr_set_family(link->l_addr,
409 link->ce_mask |= LINK_ATTR_ADDR;
412 if (tb[IFLA_BROADCAST]) {
415 if (link->l_bcast == NULL) {
419 nl_addr_set_family(link->l_bcast,
421 link->ce_mask |= LINK_ATTR_BRD;
426 link->ce_mask |= LINK_ATTR_LINK;
429 if (tb[IFLA_WEIGHT]) {
431 link->ce_mask |= LINK_ATTR_WEIGHT;
434 if (tb[IFLA_QDISC]) {
435 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
436 link->ce_mask |= LINK_ATTR_QDISC;
441 sizeof(
struct rtnl_link_ifmap));
442 link->ce_mask |= LINK_ATTR_MAP;
445 if (tb[IFLA_MASTER]) {
447 link->ce_mask |= LINK_ATTR_MASTER;
450 if (tb[IFLA_OPERSTATE]) {
451 link->l_operstate =
nla_get_u8(tb[IFLA_OPERSTATE]);
452 link->ce_mask |= LINK_ATTR_OPERSTATE;
455 if (tb[IFLA_LINKMODE]) {
456 link->l_linkmode =
nla_get_u8(tb[IFLA_LINKMODE]);
457 link->ce_mask |= LINK_ATTR_LINKMODE;
460 if (tb[IFLA_IFALIAS]) {
461 link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]);
462 if (link->l_ifalias == NULL) {
466 link->ce_mask |= LINK_ATTR_IFALIAS;
469 if (tb[IFLA_NUM_VF]) {
471 link->ce_mask |= LINK_ATTR_NUM_VF;
474 if (tb[IFLA_LINKINFO]) {
475 struct nlattr *li[IFLA_INFO_MAX+1];
482 if (li[IFLA_INFO_KIND]) {
486 kind = nla_strdup(li[IFLA_INFO_KIND]);
491 link->l_info_kind = kind;
492 link->ce_mask |= LINK_ATTR_LINKINFO;
495 link->l_info_ops = ops;
499 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
500 err = ops->
io_parse(link, li[IFLA_INFO_DATA],
501 li[IFLA_INFO_XSTATS]);
513 link->l_af_data[link->l_family]);
518 if (tb[IFLA_AF_SPEC]) {
519 struct nlattr *af_attr;
523 af_ops = af_lookup_and_alloc(link,
nla_type(af_attr));
525 char *af_data = link->l_af_data[
nla_type(af_attr)];
545 static int link_event_filter(
struct nl_cache *cache,
struct nl_object *obj)
552 if (link->l_family == AF_BRIDGE)
558 static int link_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
560 int family = cache->c_iarg1;
568 struct nl_cache *cache = dp_cache(obj);
571 nl_dump_line(p,
"%s %s ", link->l_name,
572 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
577 if (link->ce_mask & LINK_ATTR_MASTER) {
579 nl_dump(p,
"master %s ", master ? master->l_name :
"inv");
584 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
588 if (link->ce_mask & LINK_ATTR_LINK) {
590 nl_dump(p,
"slave-of %s ", ll ? ll->l_name :
"NONE");
595 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_LINE])
598 do_foreach_af(link, af_dump_line, p);
608 link_dump_line(obj, p);
610 nl_dump_line(p,
" mtu %u ", link->l_mtu);
611 nl_dump(p,
"txqlen %u weight %u ", link->l_txqlen, link->l_weight);
613 if (link->ce_mask & LINK_ATTR_QDISC)
614 nl_dump(p,
"qdisc %s ", link->l_qdisc);
616 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
617 nl_dump(p,
"irq %u ", link->l_map.lm_irq);
619 if (link->ce_mask & LINK_ATTR_IFINDEX)
620 nl_dump(p,
"index %u ", link->l_index);
625 if (link->ce_mask & LINK_ATTR_IFALIAS)
626 nl_dump_line(p,
" alias %s\n", link->l_ifalias);
628 nl_dump_line(p,
" ");
630 if (link->ce_mask & LINK_ATTR_BRD)
634 if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
635 link->l_operstate != IF_OPER_UNKNOWN) {
636 rtnl_link_operstate2str(link->l_operstate, buf,
sizeof(buf));
640 if (link->ce_mask & LINK_ATTR_NUM_VF)
641 nl_dump(p,
"num-vf %u ", link->l_num_vf);
644 rtnl_link_mode2str(link->l_linkmode, buf,
sizeof(buf)));
649 do_foreach_af(link, af_dump_details, p);
658 link_dump_details(obj, p);
660 nl_dump_line(p,
" Stats: bytes packets errors "
661 " dropped fifo-err compressed\n");
665 strcpy(fmt,
" RX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
666 fmt[9] = *unit ==
'B' ?
'9' :
'7';
668 nl_dump_line(p, fmt, res, unit,
677 strcpy(fmt,
" TX %X.2f %s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n");
678 fmt[9] = *unit ==
'B' ?
'9' :
'7';
680 nl_dump_line(p, fmt, res, unit,
687 nl_dump_line(p,
" Errors: length over crc "
688 " frame missed multicast\n");
690 nl_dump_line(p,
" RX %10" PRIu64
" %10" PRIu64
" %10"
691 PRIu64
" %10" PRIu64
" %10" PRIu64
" %10"
700 nl_dump_line(p,
" aborted carrier heartbeat "
701 " window collision\n");
703 nl_dump_line(p,
" TX %10" PRIu64
" %10" PRIu64
" %10"
704 PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
711 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_STATS])
714 do_foreach_af(link, af_dump_stats, p);
718 static int link_handle_event(
struct nl_object *a,
struct rtnl_link_event_cb *cb)
721 struct nl_cache *c = dp_cache(a);
724 if (l->l_change == ~0U) {
725 if (l->ce_msgtype == RTM_NEWLINK)
728 cb->le_unregister(l);
733 if (l->l_change & IFF_SLAVE) {
734 if (l->l_flags & IFF_SLAVE) {
736 cb->le_new_bonding(l, m);
740 cb->le_cancel_bonding(l);
744 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
745 dp_dump_line(p, line++,
"link %s changed state to %s.\n",
746 l->l_name, l->l_flags & IFF_UP ?
"up" :
"down");
748 if (l->l_change & IFF_PROMISC) {
749 dp_new_line(p, line++);
750 dp_dump(p,
"link %s %s promiscuous mode.\n",
751 l->l_name, l->l_flags & IFF_PROMISC ?
"entered" :
"left");
755 dp_dump_line(p, line++,
"link %s sent unknown event.\n",
764 uint32_t attrs,
int flags)
770 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
772 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
773 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
774 diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
775 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
776 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
777 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
778 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
779 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
780 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
781 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
782 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
783 diff |= LINK_DIFF(ADDR,
nl_addr_cmp(a->l_addr, b->l_addr));
784 diff |= LINK_DIFF(BRD,
nl_addr_cmp(a->l_bcast, b->l_bcast));
785 diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
786 diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf);
788 if (flags & LOOSE_COMPARISON)
789 diff |= LINK_DIFF(FLAGS,
790 (a->l_flags ^ b->l_flags) & b->l_flag_mask);
792 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
799 static const struct trans_tbl link_attrs[] = {
800 __ADD(LINK_ATTR_MTU, mtu)
801 __ADD(LINK_ATTR_LINK, link)
802 __ADD(LINK_ATTR_TXQLEN, txqlen)
803 __ADD(LINK_ATTR_WEIGHT, weight)
804 __ADD(LINK_ATTR_MASTER, master)
805 __ADD(LINK_ATTR_QDISC, qdisc)
806 __ADD(LINK_ATTR_MAP, map)
807 __ADD(LINK_ATTR_ADDR, address)
808 __ADD(LINK_ATTR_BRD, broadcast)
809 __ADD(LINK_ATTR_FLAGS, flags)
810 __ADD(LINK_ATTR_IFNAME, name)
811 __ADD(LINK_ATTR_IFINDEX, ifindex)
812 __ADD(LINK_ATTR_FAMILY, family)
813 __ADD(LINK_ATTR_ARPTYPE, arptype)
814 __ADD(LINK_ATTR_STATS, stats)
815 __ADD(LINK_ATTR_CHANGE, change)
816 __ADD(LINK_ATTR_OPERSTATE, operstate)
817 __ADD(LINK_ATTR_LINKMODE, linkmode)
818 __ADD(LINK_ATTR_IFALIAS, ifalias)
819 __ADD(LINK_ATTR_NUM_VF, num_vf)
822 static
char *link_attrs2str(
int attrs,
char *buf,
size_t len)
824 return __flags2str(attrs, buf, len, link_attrs,
825 ARRAY_SIZE(link_attrs));
859 struct nl_cache * cache;
866 cache->c_iarg1 = family;
896 if (cache->c_ops != &rtnl_link_ops)
899 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
900 if (link->l_index == ifindex) {
929 if (cache->c_ops != &rtnl_link_ops)
932 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
933 if (!strcmp(name, link->l_name)) {
957 struct nl_msg **result)
959 struct ifinfomsg ifi;
962 if (ifindex <= 0 && !name) {
963 APPBUG(
"ifindex or name must be specified");
964 return -NLE_MISSING_ATTR;
967 memset(&ifi, 0,
sizeof(ifi));
973 ifi.ifi_index = ifindex;
975 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
976 goto nla_put_failure;
1008 struct nl_msg *msg = NULL;
1020 if ((err =
nl_pickup(sk, link_msg_parser, &obj)) < 0)
1027 if (err == 0 && obj)
1053 strncpy(dst, link->l_name, len - 1);
1077 ifindex = link->l_index;
1086 static int build_link_msg(
int cmd,
struct ifinfomsg *hdr,
1087 struct rtnl_link *link,
int flags,
struct nl_msg **result)
1090 struct nlattr *af_spec;
1096 if (
nlmsg_append(msg, hdr,
sizeof(*hdr), NLMSG_ALIGNTO) < 0)
1097 goto nla_put_failure;
1099 if (link->ce_mask & LINK_ATTR_ADDR)
1102 if (link->ce_mask & LINK_ATTR_BRD)
1105 if (link->ce_mask & LINK_ATTR_MTU)
1108 if (link->ce_mask & LINK_ATTR_TXQLEN)
1111 if (link->ce_mask & LINK_ATTR_WEIGHT)
1114 if (link->ce_mask & LINK_ATTR_IFNAME)
1117 if (link->ce_mask & LINK_ATTR_OPERSTATE)
1118 NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate);
1120 if (link->ce_mask & LINK_ATTR_LINKMODE)
1121 NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode);
1123 if (link->ce_mask & LINK_ATTR_IFALIAS)
1126 if (link->ce_mask & LINK_ATTR_LINK)
1129 if (link->ce_mask & LINK_ATTR_MASTER)
1132 if (link->ce_mask & LINK_ATTR_LINKINFO) {
1133 struct nlattr *info;
1136 goto nla_put_failure;
1140 if (link->l_info_ops) {
1141 if (link->l_info_ops->io_put_attrs &&
1142 link->l_info_ops->io_put_attrs(msg, link) < 0)
1143 goto nla_put_failure;
1150 goto nla_put_failure;
1152 if (do_foreach_af(link, af_fill, msg) < 0)
1153 goto nla_put_failure;
1162 return -NLE_MSGSIZE;
1187 struct nl_msg **result)
1189 struct ifinfomsg ifi = {
1190 .ifi_family = link->l_family,
1191 .ifi_index = link->l_index,
1192 .ifi_flags = link->l_flags,
1195 return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result);
1249 struct nl_msg **result)
1251 struct ifinfomsg ifi = {
1252 .ifi_family = orig->l_family,
1253 .ifi_index = orig->l_index,
1257 if (changes->ce_mask & LINK_ATTR_FLAGS) {
1258 ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask;
1259 ifi.ifi_flags |= changes->l_flags;
1262 if (changes->l_family && changes->l_family != orig->l_family) {
1263 APPBUG(
"link change: family is immutable");
1264 return -NLE_IMMUTABLE;
1268 if (orig->ce_mask & LINK_ATTR_IFINDEX &&
1269 orig->ce_mask & LINK_ATTR_IFNAME &&
1270 changes->ce_mask & LINK_ATTR_IFNAME &&
1271 !strcmp(orig->l_name, changes->l_name))
1272 changes->ce_mask &= ~LINK_ATTR_IFNAME;
1274 if ((err = build_link_msg(RTM_NEWLINK, &ifi, changes, flags, result)) < 0)
1325 err = nl_send_auto_complete(sk, msg);
1329 err = wait_for_ack(sk);
1330 if (err == -NLE_OPNOTSUPP && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) {
1331 msg->nm_nlh->nlmsg_type = RTM_SETLINK;
1361 struct nl_msg **result)
1364 struct ifinfomsg ifi = {
1365 .ifi_index = link->l_index,
1368 if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) {
1369 APPBUG(
"ifindex or name must be specified");
1370 return -NLE_MISSING_ATTR;
1376 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
1377 goto nla_put_failure;
1379 if (link->ce_mask & LINK_ATTR_IFNAME)
1387 return -NLE_MSGSIZE;
1468 strncpy(link->l_name, name,
sizeof(link->l_name) - 1);
1469 link->ce_mask |= LINK_ATTR_IFNAME;
1482 return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL;
1485 static inline void __assign_addr(
struct rtnl_link *link,
struct nl_addr **pos,
1486 struct nl_addr *
new,
int flag)
1494 link->ce_mask |= flag;
1510 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1524 return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL;
1541 __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD);
1555 return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL;
1568 link->l_flag_mask |= flags;
1569 link->l_flags |= flags;
1570 link->ce_mask |= LINK_ATTR_FLAGS;
1583 link->l_flag_mask |= flags;
1584 link->l_flags &= ~flags;
1585 link->ce_mask |= LINK_ATTR_FLAGS;
1599 return link->l_flags;
1609 link->l_family = family;
1610 link->ce_mask |= LINK_ATTR_FAMILY;
1622 return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC;
1636 link->l_arptype = arptype;
1637 link->ce_mask |= LINK_ATTR_ARPTYPE;
1650 if (link->ce_mask & LINK_ATTR_ARPTYPE)
1651 return link->l_arptype;
1666 link->l_index = ifindex;
1667 link->ce_mask |= LINK_ATTR_IFINDEX;
1681 return link->l_index;
1695 link->ce_mask |= LINK_ATTR_MTU;
1723 link->l_txqlen = txqlen;
1724 link->ce_mask |= LINK_ATTR_TXQLEN;
1739 return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
1742 void rtnl_link_set_link(
struct rtnl_link *link,
int ifindex)
1744 link->l_link = ifindex;
1745 link->ce_mask |= LINK_ATTR_LINK;
1748 int rtnl_link_get_link(
struct rtnl_link *link)
1750 return link->l_link;
1762 link->l_master = ifindex;
1763 link->ce_mask |= LINK_ATTR_MASTER;
1775 return link->l_master;
1788 link->l_operstate = status;
1789 link->ce_mask |= LINK_ATTR_OPERSTATE;
1802 return link->l_operstate;
1815 link->l_linkmode = mode;
1816 link->ce_mask |= LINK_ATTR_LINKMODE;
1829 return link->l_linkmode;
1842 return link->l_ifalias;
1859 free(link->l_ifalias);
1860 link->ce_mask &= ~LINK_ATTR_IFALIAS;
1863 link->l_ifalias = strdup(alias);
1864 link->ce_mask |= LINK_ATTR_IFALIAS;
1883 strncpy(link->l_qdisc, name,
sizeof(link->l_qdisc) - 1);
1884 link->ce_mask |= LINK_ATTR_QDISC;
1897 return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL;
1910 if (link->ce_mask & LINK_ATTR_NUM_VF) {
1911 *num_vf = link->l_num_vf;
1914 return -NLE_OPNOTSUPP;
1926 if (
id > RTNL_LINK_STATS_MAX)
1929 return link->l_stats[id];
1944 const uint64_t value)
1946 if (
id > RTNL_LINK_STATS_MAX)
1949 link->l_stats[id] = value;
1972 free(link->l_info_kind);
1973 link->ce_mask &= ~LINK_ATTR_LINKINFO;
1974 if (link->l_info_ops)
1975 release_link_info(link);
1980 kind = strdup(type);
1989 link->l_info_ops = io;
1992 link->l_info_kind = kind;
1993 link->ce_mask |= LINK_ATTR_LINKINFO;
2011 return link->l_info_kind;
2061 err = -NLE_OPNOTSUPP;
2144 static const struct trans_tbl link_flags[] = {
2145 __ADD(IFF_LOOPBACK, loopback)
2146 __ADD(IFF_BROADCAST, broadcast)
2147 __ADD(IFF_POINTOPOINT, pointopoint)
2148 __ADD(IFF_MULTICAST, multicast)
2149 __ADD(IFF_NOARP, noarp)
2150 __ADD(IFF_ALLMULTI, allmulti)
2151 __ADD(IFF_PROMISC, promisc)
2152 __ADD(IFF_MASTER, master)
2153 __ADD(IFF_SLAVE, slave)
2154 __ADD(IFF_DEBUG, debug)
2155 __ADD(IFF_DYNAMIC, dynamic)
2156 __ADD(IFF_AUTOMEDIA, automedia)
2157 __ADD(IFF_PORTSEL, portsel)
2158 __ADD(IFF_NOTRAILERS, notrailers)
2160 __ADD(IFF_RUNNING, running)
2161 __ADD(IFF_LOWER_UP, lowerup)
2162 __ADD(IFF_DORMANT, dormant)
2163 __ADD(IFF_ECHO, echo)
2166 char *rtnl_link_flags2str(
int flags,
char *buf,
size_t len)
2168 return __flags2str(flags, buf, len, link_flags,
2169 ARRAY_SIZE(link_flags));
2172 int rtnl_link_str2flags(
const char *name)
2174 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
2177 static const struct trans_tbl link_stats[] = {
2237 char *rtnl_link_stat2str(
int st,
char *buf,
size_t len)
2239 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
2242 int rtnl_link_str2stat(
const char *name)
2244 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
2247 static const struct trans_tbl link_operstates[] = {
2248 __ADD(IF_OPER_UNKNOWN, unknown)
2249 __ADD(IF_OPER_NOTPRESENT, notpresent)
2250 __ADD(IF_OPER_DOWN, down)
2251 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
2252 __ADD(IF_OPER_TESTING, testing)
2253 __ADD(IF_OPER_DORMANT, dormant)
2254 __ADD(IF_OPER_UP, up)
2257 char *rtnl_link_operstate2str(uint8_t st,
char *buf,
size_t len)
2259 return __type2str(st, buf, len, link_operstates,
2260 ARRAY_SIZE(link_operstates));
2263 int rtnl_link_str2operstate(
const char *name)
2265 return __str2type(name, link_operstates,
2266 ARRAY_SIZE(link_operstates));
2269 static const struct trans_tbl link_modes[] = {
2270 __ADD(IF_LINK_MODE_DEFAULT,
default)
2271 __ADD(IF_LINK_MODE_DORMANT, dormant)
2274 char *rtnl_link_mode2str(uint8_t st,
char *buf,
size_t len)
2276 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
2279 int rtnl_link_str2mode(
const char *name)
2281 return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
2311 link->l_weight = weight;
2312 link->ce_mask |= LINK_ATTR_WEIGHT;
2320 return link->l_weight;
2328 .oo_free_data = link_free_data,
2329 .oo_clone = link_clone,
2335 .oo_compare = link_compare,
2336 .oo_attrs2str = link_attrs2str,
2337 .oo_id_attrs = LINK_ATTR_IFINDEX,
2341 { AF_UNSPEC, RTNLGRP_LINK },
2342 { END_OF_GROUP_LIST },
2347 .co_hdrsize =
sizeof(
struct ifinfomsg),
2349 { RTM_NEWLINK, NL_ACT_NEW,
"new" },
2350 { RTM_DELLINK, NL_ACT_DEL,
"del" },
2351 { RTM_GETLINK, NL_ACT_GET,
"get" },
2352 { RTM_SETLINK, NL_ACT_CHANGE,
"set" },
2353 END_OF_MSGTYPES_LIST,
2355 .co_protocol = NETLINK_ROUTE,
2356 .co_groups = link_groups,
2357 .co_request_update = link_request_update,
2358 .co_msg_parser = link_msg_parser,
2359 .co_event_filter = link_event_filter,
2360 .co_obj_ops = &link_obj_ops,
2363 static void __init link_init(
void)
2368 static void __exit link_exit(
void)