150 #include <netlink-local.h> 151 #include <netlink/netlink.h> 152 #include <netlink/attr.h> 153 #include <netlink/utils.h> 154 #include <netlink/object.h> 155 #include <netlink/route/rtnl.h> 156 #include <netlink/route/link.h> 157 #include <netlink/route/link/info-api.h> 160 #define LINK_ATTR_MTU 0x0001 161 #define LINK_ATTR_LINK 0x0002 162 #define LINK_ATTR_TXQLEN 0x0004 163 #define LINK_ATTR_WEIGHT 0x0008 164 #define LINK_ATTR_MASTER 0x0010 165 #define LINK_ATTR_QDISC 0x0020 166 #define LINK_ATTR_MAP 0x0040 167 #define LINK_ATTR_ADDR 0x0080 168 #define LINK_ATTR_BRD 0x0100 169 #define LINK_ATTR_FLAGS 0x0200 170 #define LINK_ATTR_IFNAME 0x0400 171 #define LINK_ATTR_IFINDEX 0x0800 172 #define LINK_ATTR_FAMILY 0x1000 173 #define LINK_ATTR_ARPTYPE 0x2000 174 #define LINK_ATTR_STATS 0x4000 175 #define LINK_ATTR_CHANGE 0x8000 176 #define LINK_ATTR_OPERSTATE 0x10000 177 #define LINK_ATTR_LINKMODE 0x20000 178 #define LINK_ATTR_LINKINFO 0x40000 184 static void release_link_info(
struct rtnl_link *link)
191 link->l_info_ops = NULL;
195 static void link_free_data(
struct nl_object *c)
197 struct rtnl_link *link = nl_object_priv(c);
202 if ((io = link->l_info_ops) != NULL)
203 release_link_info(link);
205 nl_addr_put(link->l_addr);
206 nl_addr_put(link->l_bcast);
210 static int link_clone(
struct nl_object *_dst,
struct nl_object *_src)
212 struct rtnl_link *dst = nl_object_priv(_dst);
213 struct rtnl_link *src = nl_object_priv(_src);
224 if (src->l_info_ops && src->l_info_ops->io_clone) {
225 err = src->l_info_ops->io_clone(dst, src);
232 return nl_get_errno();
235 static struct nla_policy link_policy[IFLA_MAX+1] = {
237 .maxlen = IFNAMSIZ },
238 [IFLA_MTU] = { .type =
NLA_U32 },
239 [IFLA_TXQLEN] = { .type =
NLA_U32 },
240 [IFLA_LINK] = { .type =
NLA_U32 },
241 [IFLA_WEIGHT] = { .type =
NLA_U32 },
242 [IFLA_MASTER] = { .type =
NLA_U32 },
243 [IFLA_OPERSTATE]= { .type =
NLA_U8 },
244 [IFLA_LINKMODE] = { .type =
NLA_U8 },
247 .maxlen = IFQDISCSIZ },
248 [IFLA_STATS] = { .minlen =
sizeof(
struct rtnl_link_stats) },
249 [IFLA_MAP] = { .minlen =
sizeof(
struct rtnl_link_ifmap) },
252 static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = {
261 struct rtnl_link *link;
262 struct ifinfomsg *ifi;
263 struct nlattr *tb[IFLA_MAX+1];
266 link = rtnl_link_alloc();
268 err = nl_errno(ENOMEM);
274 err =
nlmsg_parse(n,
sizeof(*ifi), tb, IFLA_MAX, link_policy);
278 if (tb[IFLA_IFNAME] == NULL) {
279 err = nl_error(EINVAL,
"Missing link name TLV");
283 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
286 link->l_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 (tb[IFLA_STATS]) {
296 struct rtnl_link_stats *st =
nla_data(tb[IFLA_STATS]);
298 link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets;
299 link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes;
300 link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors;
301 link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped;
302 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed;
303 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors;
304 link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets;
305 link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes;
306 link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors;
307 link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped;
308 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed;
309 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors;
310 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors;
311 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors;
312 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors;
313 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors;
314 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors;
315 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors;
316 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors;
317 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors;
318 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors;
319 link->l_stats[RTNL_LINK_MULTICAST] = st->multicast;
321 link->ce_mask |= LINK_ATTR_STATS;
324 if (tb[IFLA_TXQLEN]) {
326 link->ce_mask |= LINK_ATTR_TXQLEN;
331 link->ce_mask |= LINK_ATTR_MTU;
334 if (tb[IFLA_ADDRESS]) {
335 link->l_addr =
nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
336 if (link->l_addr == NULL)
338 nl_addr_set_family(link->l_addr,
340 link->ce_mask |= LINK_ATTR_ADDR;
343 if (tb[IFLA_BROADCAST]) {
344 link->l_bcast =
nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
345 if (link->l_bcast == NULL)
347 nl_addr_set_family(link->l_bcast,
349 link->ce_mask |= LINK_ATTR_BRD;
354 link->ce_mask |= LINK_ATTR_LINK;
357 if (tb[IFLA_WEIGHT]) {
359 link->ce_mask |= LINK_ATTR_WEIGHT;
362 if (tb[IFLA_QDISC]) {
363 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
364 link->ce_mask |= LINK_ATTR_QDISC;
369 sizeof(
struct rtnl_link_ifmap));
370 link->ce_mask |= LINK_ATTR_MAP;
373 if (tb[IFLA_MASTER]) {
375 link->ce_mask |= LINK_ATTR_MASTER;
378 if (tb[IFLA_OPERSTATE]) {
379 link->l_operstate =
nla_get_u8(tb[IFLA_OPERSTATE]);
380 link->ce_mask |= LINK_ATTR_OPERSTATE;
383 if (tb[IFLA_LINKMODE]) {
384 link->l_linkmode =
nla_get_u8(tb[IFLA_LINKMODE]);
385 link->ce_mask |= LINK_ATTR_LINKMODE;
388 if (tb[IFLA_LINKINFO]) {
389 struct nlattr *li[IFLA_INFO_MAX+1];
396 if (li[IFLA_INFO_KIND] &&
397 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
402 ops = rtnl_link_info_ops_lookup(kind);
405 link->l_info_ops = ops;
406 err = ops->
io_parse(link, li[IFLA_INFO_DATA],
407 li[IFLA_INFO_XSTATS]);
416 err = pp->pp_cb((
struct nl_object *) link, pp);
427 static int link_request_update(
struct nl_cache *c,
struct nl_handle *h)
432 static int link_dump_brief(
struct nl_object *obj,
struct nl_dump_params *p)
435 struct nl_cache *cache = dp_cache(obj);
436 struct rtnl_link *link = (
struct rtnl_link *) obj;
439 dp_dump(p,
"%s %s ", link->l_name,
440 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
443 dp_dump(p,
"%s ",
nl_addr2str(link->l_addr, buf,
sizeof(buf)));
445 if (link->ce_mask & LINK_ATTR_MASTER) {
446 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
447 dp_dump(p,
"master %s ", master ? master->l_name :
"inv");
449 rtnl_link_put(master);
452 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
454 dp_dump(p,
"<%s> ", buf);
456 if (link->ce_mask & LINK_ATTR_LINK) {
458 dp_dump(p,
"slave-of %s ", ll ? ll->l_name :
"NONE");
463 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_BRIEF])
464 line = link->l_info_ops->io_dump[
NL_DUMP_BRIEF](link, p, line);
471 static int link_dump_full(
struct nl_object *obj,
struct nl_dump_params *p)
473 struct rtnl_link *link = (
struct rtnl_link *) obj;
477 line = link_dump_brief(obj, p);
478 dp_new_line(p, line++);
480 dp_dump(p,
" mtu %u ", link->l_mtu);
481 dp_dump(p,
"txqlen %u weight %u ", link->l_txqlen, link->l_weight);
483 if (link->ce_mask & LINK_ATTR_QDISC)
484 dp_dump(p,
"qdisc %s ", link->l_qdisc);
486 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
487 dp_dump(p,
"irq %u ", link->l_map.lm_irq);
489 if (link->ce_mask & LINK_ATTR_IFINDEX)
490 dp_dump(p,
"index %u ", link->l_index);
494 dp_new_line(p, line++);
498 if (link->ce_mask & LINK_ATTR_BRD)
499 dp_dump(p,
"brd %s ",
nl_addr2str(link->l_bcast, buf,
502 if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
503 link->l_operstate != IF_OPER_UNKNOWN) {
504 rtnl_link_operstate2str(link->l_operstate, buf,
sizeof(buf));
505 dp_dump(p,
"state %s ", buf);
508 dp_dump(p,
"mode %s\n",
509 rtnl_link_mode2str(link->l_linkmode, buf,
sizeof(buf)));
511 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_FULL])
512 line = link->l_info_ops->io_dump[
NL_DUMP_FULL](link, p, line);
517 static int link_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
519 struct rtnl_link *link = (
struct rtnl_link *) obj;
524 line = link_dump_full(obj, p);
526 dp_dump_line(p, line++,
" Stats: bytes packets errors " 527 " dropped fifo-err compressed\n");
531 strcpy(fmt,
" RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
532 fmt[9] = *unit ==
'B' ?
'9' :
'7';
534 dp_dump_line(p, line++, fmt,
536 link->l_stats[RTNL_LINK_RX_PACKETS],
537 link->l_stats[RTNL_LINK_RX_ERRORS],
538 link->l_stats[RTNL_LINK_RX_DROPPED],
539 link->l_stats[RTNL_LINK_RX_FIFO_ERR],
540 link->l_stats[RTNL_LINK_RX_COMPRESSED]);
544 strcpy(fmt,
" TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
545 fmt[9] = *unit ==
'B' ?
'9' :
'7';
547 dp_dump_line(p, line++, fmt,
549 link->l_stats[RTNL_LINK_TX_PACKETS],
550 link->l_stats[RTNL_LINK_TX_ERRORS],
551 link->l_stats[RTNL_LINK_TX_DROPPED],
552 link->l_stats[RTNL_LINK_TX_FIFO_ERR],
553 link->l_stats[RTNL_LINK_TX_COMPRESSED]);
555 dp_dump_line(p, line++,
" Errors: length over crc " 556 " frame missed multicast\n");
558 dp_dump_line(p, line++,
" RX %10" PRIu64
" %10" PRIu64
" %10" 559 PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" 561 link->l_stats[RTNL_LINK_RX_LEN_ERR],
562 link->l_stats[RTNL_LINK_RX_OVER_ERR],
563 link->l_stats[RTNL_LINK_RX_CRC_ERR],
564 link->l_stats[RTNL_LINK_RX_FRAME_ERR],
565 link->l_stats[RTNL_LINK_RX_MISSED_ERR],
566 link->l_stats[RTNL_LINK_MULTICAST]);
568 dp_dump_line(p, line++,
" Errors: aborted carrier heartbeat " 569 " window collision\n");
571 dp_dump_line(p, line++,
" TX %10" PRIu64
" %10" PRIu64
" %10" 572 PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
573 link->l_stats[RTNL_LINK_TX_ABORT_ERR],
574 link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
575 link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
576 link->l_stats[RTNL_LINK_TX_WIN_ERR],
577 link->l_stats[RTNL_LINK_TX_COLLISIONS]);
579 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_STATS])
580 line = link->l_info_ops->io_dump[
NL_DUMP_STATS](link, p, line);
585 static int link_dump_xml(
struct nl_object *obj,
struct nl_dump_params *p)
587 struct rtnl_link *link = (
struct rtnl_link *) obj;
588 struct nl_cache *cache = dp_cache(obj);
592 dp_dump_line(p, line++,
"<link name=\"%s\" index=\"%u\">\n",
593 link->l_name, link->l_index);
594 dp_dump_line(p, line++,
" <family>%s</family>\n",
595 nl_af2str(link->l_family, buf,
sizeof(buf)));
596 dp_dump_line(p, line++,
" <arptype>%s</arptype>\n",
597 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
598 dp_dump_line(p, line++,
" <address>%s</address>\n",
600 dp_dump_line(p, line++,
" <mtu>%u</mtu>\n", link->l_mtu);
601 dp_dump_line(p, line++,
" <txqlen>%u</txqlen>\n", link->l_txqlen);
602 dp_dump_line(p, line++,
" <weight>%u</weight>\n", link->l_weight);
604 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
606 dp_dump_line(p, line++,
" <flags>%s</flags>\n", buf);
608 if (link->ce_mask & LINK_ATTR_QDISC)
609 dp_dump_line(p, line++,
" <qdisc>%s</qdisc>\n", link->l_qdisc);
611 if (link->ce_mask & LINK_ATTR_LINK) {
613 dp_dump_line(p, line++,
" <link>%s</link>\n",
614 ll ? ll->l_name :
"none");
619 if (link->ce_mask & LINK_ATTR_MASTER) {
620 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
621 dp_dump_line(p, line++,
" <master>%s</master>\n",
622 master ? master->l_name :
"none");
624 rtnl_link_put(master);
627 if (link->ce_mask & LINK_ATTR_BRD)
628 dp_dump_line(p, line++,
" <broadcast>%s</broadcast>\n",
631 if (link->ce_mask & LINK_ATTR_STATS) {
632 dp_dump_line(p, line++,
" <stats>\n");
633 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
634 rtnl_link_stat2str(i, buf,
sizeof(buf));
635 dp_dump_line(p, line++,
636 " <%s>%" PRIu64
"</%s>\n",
637 buf, link->l_stats[i], buf);
639 dp_dump_line(p, line++,
" </stats>\n");
642 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_XML]) {
643 dp_dump_line(p, line++,
" <info>\n");
644 line = link->l_info_ops->io_dump[
NL_DUMP_XML](link, p, line);
645 dp_dump_line(p, line++,
" </info>\n");
648 dp_dump_line(p, line++,
"</link>\n");
652 struct rtnl_lifmap l_map;
658 static int link_dump_env(
struct nl_object *obj,
struct nl_dump_params *p)
660 struct rtnl_link *link = (
struct rtnl_link *) obj;
661 struct nl_cache *cache = dp_cache(obj);
665 dp_dump_line(p, line++,
"LINK_NAME=%s\n", link->l_name);
666 dp_dump_line(p, line++,
"LINK_IFINDEX=%u\n", link->l_index);
667 dp_dump_line(p, line++,
"LINK_FAMILY=%s\n",
668 nl_af2str(link->l_family, buf,
sizeof(buf)));
669 dp_dump_line(p, line++,
"LINK_TYPE=%s\n",
670 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
671 if (link->ce_mask & LINK_ATTR_ADDR)
672 dp_dump_line(p, line++,
"LINK_ADDRESS=%s\n",
674 dp_dump_line(p, line++,
"LINK_MTU=%u\n", link->l_mtu);
675 dp_dump_line(p, line++,
"LINK_TXQUEUELEN=%u\n", link->l_txqlen);
676 dp_dump_line(p, line++,
"LINK_WEIGHT=%u\n", link->l_weight);
678 rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf,
sizeof(buf));
680 dp_dump_line(p, line++,
"LINK_FLAGS=%s\n", buf);
682 if (link->ce_mask & LINK_ATTR_QDISC)
683 dp_dump_line(p, line++,
"LINK_QDISC=%s\n", link->l_qdisc);
685 if (link->ce_mask & LINK_ATTR_LINK) {
688 dp_dump_line(p, line++,
"LINK_LINK_IFINDEX=%d\n", link->l_link);
690 dp_dump_line(p, line++,
"LINK_LINK_IFNAME=%s\n",
696 if (link->ce_mask & LINK_ATTR_MASTER) {
697 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
698 dp_dump_line(p, line++,
"LINK_MASTER=%s\n",
699 master ? master->l_name :
"none");
701 rtnl_link_put(master);
704 if (link->ce_mask & LINK_ATTR_BRD)
705 dp_dump_line(p, line++,
"LINK_BROADCAST=%s\n",
708 if (link->ce_mask & LINK_ATTR_STATS) {
709 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
712 sprintf(buf,
"LINK_");
713 rtnl_link_stat2str(i, buf + 5,
sizeof(buf) - 5);
718 dp_dump_line(p, line++,
719 "%s=%" PRIu64
"\n", buf, link->l_stats[i]);
723 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_ENV])
724 line = link->l_info_ops->io_dump[
NL_DUMP_ENV](link, p, line);
730 static int link_handle_event(
struct nl_object *a,
struct rtnl_link_event_cb *cb)
732 struct rtnl_link *l = (
struct rtnl_link *) a;
733 struct nl_cache *c = dp_cache(a);
736 if (l->l_change == ~0U) {
737 if (l->ce_msgtype == RTM_NEWLINK)
740 cb->le_unregister(l);
745 if (l->l_change & IFF_SLAVE) {
746 if (l->l_flags & IFF_SLAVE) {
748 cb->le_new_bonding(l, m);
752 cb->le_cancel_bonding(l);
756 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
757 dp_dump_line(p, line++,
"link %s changed state to %s.\n",
758 l->l_name, l->l_flags & IFF_UP ?
"up" :
"down");
760 if (l->l_change & IFF_PROMISC) {
761 dp_new_line(p, line++);
762 dp_dump(p,
"link %s %s promiscuous mode.\n",
763 l->l_name, l->l_flags & IFF_PROMISC ?
"entered" :
"left");
767 dp_dump_line(p, line++,
"link %s sent unknown event.\n",
775 static int link_compare(
struct nl_object *_a,
struct nl_object *_b,
776 uint32_t attrs,
int flags)
778 struct rtnl_link *a = (
struct rtnl_link *) _a;
779 struct rtnl_link *b = (
struct rtnl_link *) _b;
782 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR) 784 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
785 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
786 diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
787 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
788 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
789 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
790 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
791 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
792 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
793 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
794 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
795 diff |= LINK_DIFF(ADDR,
nl_addr_cmp(a->l_addr, b->l_addr));
796 diff |= LINK_DIFF(BRD,
nl_addr_cmp(a->l_bcast, b->l_bcast));
798 if (flags & LOOSE_FLAG_COMPARISON)
799 diff |= LINK_DIFF(FLAGS,
800 (a->l_flags ^ b->l_flags) & b->l_flag_mask);
802 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
809 static struct trans_tbl link_attrs[] = {
810 __ADD(LINK_ATTR_MTU, mtu)
811 __ADD(LINK_ATTR_LINK, link)
812 __ADD(LINK_ATTR_TXQLEN, txqlen)
813 __ADD(LINK_ATTR_WEIGHT, weight)
814 __ADD(LINK_ATTR_MASTER, master)
815 __ADD(LINK_ATTR_QDISC, qdisc)
816 __ADD(LINK_ATTR_MAP, map)
817 __ADD(LINK_ATTR_ADDR, address)
818 __ADD(LINK_ATTR_BRD, broadcast)
819 __ADD(LINK_ATTR_FLAGS, flags)
820 __ADD(LINK_ATTR_IFNAME, name)
821 __ADD(LINK_ATTR_IFINDEX, ifindex)
822 __ADD(LINK_ATTR_FAMILY, family)
823 __ADD(LINK_ATTR_ARPTYPE, arptype)
824 __ADD(LINK_ATTR_STATS, stats)
825 __ADD(LINK_ATTR_CHANGE, change)
826 __ADD(LINK_ATTR_OPERSTATE, operstate)
827 __ADD(LINK_ATTR_LINKMODE, linkmode)
830 static char *link_attrs2str(
int attrs,
char *buf,
size_t len)
832 return __flags2str(attrs, buf, len, link_attrs,
833 ARRAY_SIZE(link_attrs));
841 struct rtnl_link *rtnl_link_alloc(
void)
846 void rtnl_link_put(
struct rtnl_link *link)
871 struct nl_cache * cache;
897 struct rtnl_link *link;
899 if (cache->c_ops != &rtnl_link_ops)
902 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
903 if (link->l_index == ifindex) {
925 struct rtnl_link *link;
927 if (cache->c_ops != &rtnl_link_ops)
930 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
931 if (!strcmp(name, link->l_name)) {
966 struct rtnl_link *tmpl,
970 struct ifinfomsg ifi = {
971 .ifi_family = old->l_family,
972 .ifi_index = old->l_index,
975 if (tmpl->ce_mask & LINK_ATTR_FLAGS) {
976 ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
977 ifi.ifi_flags |= tmpl->l_flags;
982 goto nla_put_failure;
984 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
985 goto nla_put_failure;
987 if (tmpl->ce_mask & LINK_ATTR_ADDR)
990 if (tmpl->ce_mask & LINK_ATTR_BRD)
993 if (tmpl->ce_mask & LINK_ATTR_MTU)
996 if (tmpl->ce_mask & LINK_ATTR_TXQLEN)
999 if (tmpl->ce_mask & LINK_ATTR_WEIGHT)
1002 if (tmpl->ce_mask & LINK_ATTR_IFNAME)
1005 if (tmpl->ce_mask & LINK_ATTR_OPERSTATE)
1006 NLA_PUT_U8(msg, IFLA_OPERSTATE, tmpl->l_operstate);
1008 if (tmpl->ce_mask & LINK_ATTR_LINKMODE)
1009 NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode);
1011 if ((tmpl->ce_mask & LINK_ATTR_LINKINFO) && tmpl->l_info_ops &&
1012 tmpl->l_info_ops->io_put_attrs) {
1013 struct nlattr *info;
1016 goto nla_put_failure;
1020 if (tmpl->l_info_ops->io_put_attrs(msg, tmpl) < 0)
1021 goto nla_put_failure;
1049 struct rtnl_link *tmpl,
int flags)
1056 return nl_errno(ENOMEM);
1091 strncpy(dst, link->l_name, len - 1);
1092 rtnl_link_put(link);
1109 struct rtnl_link *link;
1113 ifindex = link->l_index;
1114 rtnl_link_put(link);
1127 static struct trans_tbl link_flags[] = {
1128 __ADD(IFF_LOOPBACK, loopback)
1129 __ADD(IFF_BROADCAST, broadcast)
1130 __ADD(IFF_POINTOPOINT, pointopoint)
1131 __ADD(IFF_MULTICAST, multicast)
1132 __ADD(IFF_NOARP, noarp)
1133 __ADD(IFF_ALLMULTI, allmulti)
1134 __ADD(IFF_PROMISC, promisc)
1135 __ADD(IFF_MASTER, master)
1136 __ADD(IFF_SLAVE, slave)
1137 __ADD(IFF_DEBUG, debug)
1138 __ADD(IFF_DYNAMIC, dynamic)
1139 __ADD(IFF_AUTOMEDIA, automedia)
1140 __ADD(IFF_PORTSEL, portsel)
1141 __ADD(IFF_NOTRAILERS, notrailers)
1143 __ADD(IFF_RUNNING, running)
1144 __ADD(IFF_LOWER_UP, lowerup)
1145 __ADD(IFF_DORMANT, dormant)
1146 __ADD(IFF_ECHO, echo)
1149 char * rtnl_link_flags2str(
int flags,
char *buf,
size_t len)
1151 return __flags2str(flags, buf, len, link_flags,
1152 ARRAY_SIZE(link_flags));
1155 int rtnl_link_str2flags(
const char *name)
1157 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
1167 static struct trans_tbl link_stats[] = {
1168 __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
1169 __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
1170 __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
1171 __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
1172 __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
1173 __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
1174 __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
1175 __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
1176 __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
1177 __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
1178 __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
1179 __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
1180 __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
1181 __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
1182 __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
1183 __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
1184 __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
1185 __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
1186 __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
1187 __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
1188 __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
1189 __ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
1190 __ADD(RTNL_LINK_MULTICAST, multicast)
1193 char *rtnl_link_stat2str(
int st,
char *buf,
size_t len)
1195 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
1198 int rtnl_link_str2stat(
const char *name)
1200 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
1210 static struct trans_tbl link_operstates[] = {
1211 __ADD(IF_OPER_UNKNOWN, unknown)
1212 __ADD(IF_OPER_NOTPRESENT, notpresent)
1213 __ADD(IF_OPER_DOWN, down)
1214 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
1215 __ADD(IF_OPER_TESTING, testing)
1216 __ADD(IF_OPER_DORMANT, dormant)
1217 __ADD(IF_OPER_UP, up)
1220 char *rtnl_link_operstate2str(
int st,
char *buf,
size_t len)
1222 return __type2str(st, buf, len, link_operstates,
1223 ARRAY_SIZE(link_operstates));
1226 int rtnl_link_str2operstate(
const char *name)
1228 return __str2type(name, link_operstates,
1229 ARRAY_SIZE(link_operstates));
1239 static struct trans_tbl link_modes[] = {
1240 __ADD(IF_LINK_MODE_DEFAULT,
default)
1241 __ADD(IF_LINK_MODE_DORMANT, dormant)
1244 char *rtnl_link_mode2str(
int st,
char *buf,
size_t len)
1246 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
1249 int rtnl_link_str2mode(
const char *name)
1251 return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
1261 void rtnl_link_set_qdisc(
struct rtnl_link *link,
const char *qdisc)
1263 strncpy(link->l_qdisc, qdisc,
sizeof(link->l_qdisc) - 1);
1264 link->ce_mask |= LINK_ATTR_QDISC;
1267 char *rtnl_link_get_qdisc(
struct rtnl_link *link)
1269 if (link->ce_mask & LINK_ATTR_QDISC)
1270 return link->l_qdisc;
1275 void rtnl_link_set_name(
struct rtnl_link *link,
const char *name)
1277 strncpy(link->l_name, name,
sizeof(link->l_name) - 1);
1278 link->ce_mask |= LINK_ATTR_IFNAME;
1281 char *rtnl_link_get_name(
struct rtnl_link *link)
1283 if (link->ce_mask & LINK_ATTR_IFNAME)
1284 return link->l_name;
1289 static inline void __assign_addr(
struct rtnl_link *link,
struct nl_addr **pos,
1290 struct nl_addr *
new,
int flag)
1298 link->ce_mask |= flag;
1301 void rtnl_link_set_addr(
struct rtnl_link *link,
struct nl_addr *addr)
1303 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1306 struct nl_addr *rtnl_link_get_addr(
struct rtnl_link *link)
1308 if (link->ce_mask & LINK_ATTR_ADDR)
1309 return link->l_addr;
1314 void rtnl_link_set_broadcast(
struct rtnl_link *link,
struct nl_addr *brd)
1316 __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
1319 struct nl_addr *rtnl_link_get_broadcast(
struct rtnl_link *link)
1321 if (link->ce_mask & LINK_ATTR_BRD)
1322 return link->l_bcast;
1327 void rtnl_link_set_flags(
struct rtnl_link *link,
unsigned int flags)
1329 link->l_flag_mask |= flags;
1330 link->l_flags |= flags;
1331 link->ce_mask |= LINK_ATTR_FLAGS;
1334 void rtnl_link_unset_flags(
struct rtnl_link *link,
unsigned int flags)
1336 link->l_flag_mask |= flags;
1337 link->l_flags &= ~flags;
1338 link->ce_mask |= LINK_ATTR_FLAGS;
1341 unsigned int rtnl_link_get_flags(
struct rtnl_link *link)
1343 return link->l_flags;
1346 void rtnl_link_set_family(
struct rtnl_link *link,
int family)
1348 link->l_family = family;
1349 link->ce_mask |= LINK_ATTR_FAMILY;
1352 int rtnl_link_get_family(
struct rtnl_link *link)
1354 if (link->l_family & LINK_ATTR_FAMILY)
1355 return link->l_family;
1360 void rtnl_link_set_arptype(
struct rtnl_link *link,
unsigned int arptype)
1362 link->l_arptype = arptype;
1365 unsigned int rtnl_link_get_arptype(
struct rtnl_link *link)
1367 return link->l_arptype;
1370 void rtnl_link_set_ifindex(
struct rtnl_link *link,
int ifindex)
1372 link->l_index = ifindex;
1373 link->ce_mask |= LINK_ATTR_IFINDEX;
1376 int rtnl_link_get_ifindex(
struct rtnl_link *link)
1378 if (link->ce_mask & LINK_ATTR_IFINDEX)
1379 return link->l_index;
1384 void rtnl_link_set_mtu(
struct rtnl_link *link,
unsigned int mtu)
1387 link->ce_mask |= LINK_ATTR_MTU;
1390 unsigned int rtnl_link_get_mtu(
struct rtnl_link *link)
1392 if (link->ce_mask & LINK_ATTR_MTU)
1398 void rtnl_link_set_txqlen(
struct rtnl_link *link,
unsigned int txqlen)
1400 link->l_txqlen = txqlen;
1401 link->ce_mask |= LINK_ATTR_TXQLEN;
1404 unsigned int rtnl_link_get_txqlen(
struct rtnl_link *link)
1406 if (link->ce_mask & LINK_ATTR_TXQLEN)
1407 return link->l_txqlen;
1412 void rtnl_link_set_weight(
struct rtnl_link *link,
unsigned int weight)
1414 link->l_weight = weight;
1415 link->ce_mask |= LINK_ATTR_WEIGHT;
1418 unsigned int rtnl_link_get_weight(
struct rtnl_link *link)
1420 if (link->ce_mask & LINK_ATTR_WEIGHT)
1421 return link->l_weight;
1426 void rtnl_link_set_link(
struct rtnl_link *link,
int ifindex)
1428 link->l_link = ifindex;
1429 link->ce_mask |= LINK_ATTR_LINK;
1432 int rtnl_link_get_link(
struct rtnl_link *link)
1434 if (link->ce_mask & LINK_ATTR_LINK)
1435 return link->l_link;
1440 void rtnl_link_set_master(
struct rtnl_link *link,
int ifindex)
1442 link->l_master = ifindex;
1443 link->ce_mask |= LINK_ATTR_MASTER;
1446 int rtnl_link_get_master(
struct rtnl_link *link)
1448 if (link->ce_mask & LINK_ATTR_MASTER)
1449 return link->l_master;
1454 void rtnl_link_set_operstate(
struct rtnl_link *link, uint8_t operstate)
1456 link->l_operstate = operstate;
1457 link->ce_mask |= LINK_ATTR_OPERSTATE;
1460 uint8_t rtnl_link_get_operstate(
struct rtnl_link *link)
1462 if (link->ce_mask & LINK_ATTR_OPERSTATE)
1463 return link->l_operstate;
1465 return IF_OPER_UNKNOWN;
1468 void rtnl_link_set_linkmode(
struct rtnl_link *link, uint8_t linkmode)
1470 link->l_linkmode = linkmode;
1471 link->ce_mask |= LINK_ATTR_LINKMODE;
1474 uint8_t rtnl_link_get_linkmode(
struct rtnl_link *link)
1476 if (link->ce_mask & LINK_ATTR_LINKMODE)
1477 return link->l_linkmode;
1479 return IF_LINK_MODE_DEFAULT;
1482 uint64_t rtnl_link_get_stat(
struct rtnl_link *link,
int id)
1484 if (id < 0 || id > RTNL_LINK_STATS_MAX)
1487 return link->l_stats[id];
1506 if ((io = rtnl_link_info_ops_lookup(type)) == NULL)
1507 return nl_error(ENOENT,
"No such link info type exists");
1509 if (link->l_info_ops)
1510 release_link_info(link);
1512 if ((err = io->
io_alloc(link)) < 0)
1515 link->l_info_ops = io;
1529 if (link->l_info_ops)
1530 return link->l_info_ops->io_name;
1539 .oo_size =
sizeof(
struct rtnl_link),
1540 .oo_free_data = link_free_data,
1541 .oo_clone = link_clone,
1547 .oo_compare = link_compare,
1548 .oo_attrs2str = link_attrs2str,
1549 .oo_id_attrs = LINK_ATTR_IFINDEX,
1553 { AF_UNSPEC, RTNLGRP_LINK },
1554 { END_OF_GROUP_LIST },
1558 .co_name =
"route/link",
1559 .co_hdrsize =
sizeof(
struct ifinfomsg),
1561 { RTM_NEWLINK, NL_ACT_NEW,
"new" },
1562 { RTM_DELLINK, NL_ACT_DEL,
"del" },
1563 { RTM_GETLINK, NL_ACT_GET,
"get" },
1564 END_OF_MSGTYPES_LIST,
1566 .co_protocol = NETLINK_ROUTE,
1567 .co_groups = link_groups,
1568 .co_request_update = link_request_update,
1569 .co_msg_parser = link_msg_parser,
1570 .co_obj_ops = &link_obj_ops,
1573 static void __init link_init(
void)
1578 static void __exit link_exit(
void)
Dump object in a brief one-liner.
#define RTNL_LINK_NOT_FOUND
Special interface index stating the link was not found.
int rtnl_link_change(struct nl_handle *handle, struct rtnl_link *old, struct rtnl_link *tmpl, int flags)
Change link attributes.
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
struct rtnl_link * rtnl_link_get_by_name(struct nl_cache *cache, const char *name)
Look up link by link name in the provided cache.
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
uint16_t nlmsg_type
Message type (content type)
int rtnl_link_set_info_type(struct rtnl_link *link, const char *type)
Specify the info type of a link.
struct rtnl_link * rtnl_link_get(struct nl_cache *cache, int ifindex)
Look up link by interface index in the provided cache.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
attribute validation policy
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
int nla_nest_end(struct nl_msg *n, struct nlattr *start)
Finalize nesting of attributes.
#define NLA_PUT_STRING(n, attrtype, value)
Add a character string netlink attribute to a netlink message.
int nla_memcpy(void *dest, struct nlattr *src, int count)
Copy a netlink attribute into another memory area.
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old, struct rtnl_link *tmpl, int flags)
Builds a netlink change request message to change link attributes.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
#define NLA_PUT_U8(n, attrtype, value)
Add a u8 netlink attribute to a netlink message.
Dump all attribtes in XML format.
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
#define NLM_F_DUMP
Dump all entries.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
parse nested attributes
uint8_t nla_get_u8(struct nlattr *nla)
Return payload of u8 attribute.
int(* io_parse)(struct rtnl_link *, struct nlattr *, struct nlattr *)
Called to parse the link info attribute.
void * nla_data(const struct nlattr *nla)
head of payload
int nl_rtgen_request(struct nl_handle *handle, int type, int family, int flags)
Send routing netlink request message.
struct nl_addr * nla_get_addr(struct nlattr *nla, int family)
Return payload of address attribute.
#define NLA_PUT_ADDR(n, attrtype, addr)
Add a address attribute to a netlink message.
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
char * nla_get_string(struct nlattr *nla)
return payload of string attribute
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.
int nl_addr_guess_family(struct nl_addr *addr)
Guess address family of an abstract address object based on address size.
uint16_t type
Type of attribute or NLA_UNSPEC.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate an interface index to the corresponding link name.
struct nl_cache * rtnl_link_alloc_cache(struct nl_handle *handle)
Allocate link cache and fill in all configured links.
int io_refcnt
Reference count (internal, do not use)
void(* io_free)(struct rtnl_link *)
Called to release all resources previously allocated in either io_alloc() or io_parse().
struct nlattr * nla_nest_start(struct nl_msg *n, int attrtype)
Start a new level of nested attributes.
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
int rtnl_link_name2i(struct nl_cache *cache, const char *name)
Translate a link name to the corresponding interface index.
Address family to netlink group association.
char * rtnl_link_get_info_type(struct rtnl_link *link)
Return info type of a link.
int(* io_alloc)(struct rtnl_link *)
Called to assign an info type to a link.
char * oo_name
Unique name of object type.
Dump all attributes but no statistics.
Dump all attributes including statistics.
int nl_addr_iszero(struct nl_addr *addr)
Returns true if the address consists of all zeros.
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload into a sized buffer.
#define NLA_PUT_U32(n, attrtype, value)
Add a u32 netlink attribute to a netlink message.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Dump all attribtues as env variables.