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;
368 struct rtnl_link_ifmap *map =
nla_data(tb[IFLA_MAP]);
369 link->l_map.lm_mem_start = map->mem_start;
370 link->l_map.lm_mem_end = map->mem_end;
371 link->l_map.lm_base_addr = map->base_addr;
372 link->l_map.lm_irq = map->irq;
373 link->l_map.lm_dma = map->dma;
374 link->l_map.lm_port = map->port;
375 link->ce_mask |= LINK_ATTR_MAP;
378 if (tb[IFLA_MASTER]) {
380 link->ce_mask |= LINK_ATTR_MASTER;
383 if (tb[IFLA_OPERSTATE]) {
384 link->l_operstate =
nla_get_u8(tb[IFLA_OPERSTATE]);
385 link->ce_mask |= LINK_ATTR_OPERSTATE;
388 if (tb[IFLA_LINKMODE]) {
389 link->l_linkmode =
nla_get_u8(tb[IFLA_LINKMODE]);
390 link->ce_mask |= LINK_ATTR_LINKMODE;
393 if (tb[IFLA_LINKINFO]) {
394 struct nlattr *li[IFLA_INFO_MAX+1];
401 if (li[IFLA_INFO_KIND] &&
402 (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
407 ops = rtnl_link_info_ops_lookup(kind);
410 link->l_info_ops = ops;
411 err = ops->
io_parse(link, li[IFLA_INFO_DATA],
412 li[IFLA_INFO_XSTATS]);
421 err = pp->pp_cb((
struct nl_object *) link, pp);
432 static int link_request_update(
struct nl_cache *c,
struct nl_handle *h)
437 static int link_dump_brief(
struct nl_object *obj,
struct nl_dump_params *p)
440 struct nl_cache *cache = dp_cache(obj);
441 struct rtnl_link *link = (
struct rtnl_link *) obj;
444 dp_dump(p,
"%s %s ", link->l_name,
445 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
448 dp_dump(p,
"%s ",
nl_addr2str(link->l_addr, buf,
sizeof(buf)));
450 if (link->ce_mask & LINK_ATTR_MASTER) {
451 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
452 dp_dump(p,
"master %s ", master ? master->l_name :
"inv");
454 rtnl_link_put(master);
457 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
459 dp_dump(p,
"<%s> ", buf);
461 if (link->ce_mask & LINK_ATTR_LINK) {
463 dp_dump(p,
"slave-of %s ", ll ? ll->l_name :
"NONE");
468 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_BRIEF])
469 line = link->l_info_ops->io_dump[
NL_DUMP_BRIEF](link, p, line);
476 static int link_dump_full(
struct nl_object *obj,
struct nl_dump_params *p)
478 struct rtnl_link *link = (
struct rtnl_link *) obj;
482 line = link_dump_brief(obj, p);
483 dp_new_line(p, line++);
485 dp_dump(p,
" mtu %u ", link->l_mtu);
486 dp_dump(p,
"txqlen %u weight %u ", link->l_txqlen, link->l_weight);
488 if (link->ce_mask & LINK_ATTR_QDISC)
489 dp_dump(p,
"qdisc %s ", link->l_qdisc);
491 if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
492 dp_dump(p,
"irq %u ", link->l_map.lm_irq);
494 if (link->ce_mask & LINK_ATTR_IFINDEX)
495 dp_dump(p,
"index %u ", link->l_index);
499 dp_new_line(p, line++);
503 if (link->ce_mask & LINK_ATTR_BRD)
504 dp_dump(p,
"brd %s ",
nl_addr2str(link->l_bcast, buf,
507 if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
508 link->l_operstate != IF_OPER_UNKNOWN) {
509 rtnl_link_operstate2str(link->l_operstate, buf,
sizeof(buf));
510 dp_dump(p,
"state %s ", buf);
513 dp_dump(p,
"mode %s\n",
514 rtnl_link_mode2str(link->l_linkmode, buf,
sizeof(buf)));
516 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_FULL])
517 line = link->l_info_ops->io_dump[
NL_DUMP_FULL](link, p, line);
522 static int link_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
524 struct rtnl_link *link = (
struct rtnl_link *) obj;
529 line = link_dump_full(obj, p);
531 dp_dump_line(p, line++,
" Stats: bytes packets errors "
532 " dropped fifo-err compressed\n");
536 strcpy(fmt,
" RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
537 fmt[9] = *unit ==
'B' ?
'9' :
'7';
539 dp_dump_line(p, line++, fmt,
541 link->l_stats[RTNL_LINK_RX_PACKETS],
542 link->l_stats[RTNL_LINK_RX_ERRORS],
543 link->l_stats[RTNL_LINK_RX_DROPPED],
544 link->l_stats[RTNL_LINK_RX_FIFO_ERR],
545 link->l_stats[RTNL_LINK_RX_COMPRESSED]);
549 strcpy(fmt,
" TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
550 fmt[9] = *unit ==
'B' ?
'9' :
'7';
552 dp_dump_line(p, line++, fmt,
554 link->l_stats[RTNL_LINK_TX_PACKETS],
555 link->l_stats[RTNL_LINK_TX_ERRORS],
556 link->l_stats[RTNL_LINK_TX_DROPPED],
557 link->l_stats[RTNL_LINK_TX_FIFO_ERR],
558 link->l_stats[RTNL_LINK_TX_COMPRESSED]);
560 dp_dump_line(p, line++,
" Errors: length over crc "
561 " frame missed multicast\n");
563 dp_dump_line(p, line++,
" RX %10" PRIu64
" %10" PRIu64
" %10"
564 PRIu64
" %10" PRIu64
" %10" PRIu64
" %10"
566 link->l_stats[RTNL_LINK_RX_LEN_ERR],
567 link->l_stats[RTNL_LINK_RX_OVER_ERR],
568 link->l_stats[RTNL_LINK_RX_CRC_ERR],
569 link->l_stats[RTNL_LINK_RX_FRAME_ERR],
570 link->l_stats[RTNL_LINK_RX_MISSED_ERR],
571 link->l_stats[RTNL_LINK_MULTICAST]);
573 dp_dump_line(p, line++,
" Errors: aborted carrier heartbeat "
574 " window collision\n");
576 dp_dump_line(p, line++,
" TX %10" PRIu64
" %10" PRIu64
" %10"
577 PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
578 link->l_stats[RTNL_LINK_TX_ABORT_ERR],
579 link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
580 link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
581 link->l_stats[RTNL_LINK_TX_WIN_ERR],
582 link->l_stats[RTNL_LINK_TX_COLLISIONS]);
584 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_STATS])
585 line = link->l_info_ops->io_dump[
NL_DUMP_STATS](link, p, line);
590 static int link_dump_xml(
struct nl_object *obj,
struct nl_dump_params *p)
592 struct rtnl_link *link = (
struct rtnl_link *) obj;
593 struct nl_cache *cache = dp_cache(obj);
597 dp_dump_line(p, line++,
"<link name=\"%s\" index=\"%u\">\n",
598 link->l_name, link->l_index);
599 dp_dump_line(p, line++,
" <family>%s</family>\n",
600 nl_af2str(link->l_family, buf,
sizeof(buf)));
601 dp_dump_line(p, line++,
" <arptype>%s</arptype>\n",
602 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
603 dp_dump_line(p, line++,
" <address>%s</address>\n",
605 dp_dump_line(p, line++,
" <mtu>%u</mtu>\n", link->l_mtu);
606 dp_dump_line(p, line++,
" <txqlen>%u</txqlen>\n", link->l_txqlen);
607 dp_dump_line(p, line++,
" <weight>%u</weight>\n", link->l_weight);
609 rtnl_link_flags2str(link->l_flags, buf,
sizeof(buf));
611 dp_dump_line(p, line++,
" <flags>%s</flags>\n", buf);
613 if (link->ce_mask & LINK_ATTR_QDISC)
614 dp_dump_line(p, line++,
" <qdisc>%s</qdisc>\n", link->l_qdisc);
616 if (link->ce_mask & LINK_ATTR_LINK) {
618 dp_dump_line(p, line++,
" <link>%s</link>\n",
619 ll ? ll->l_name :
"none");
624 if (link->ce_mask & LINK_ATTR_MASTER) {
625 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
626 dp_dump_line(p, line++,
" <master>%s</master>\n",
627 master ? master->l_name :
"none");
629 rtnl_link_put(master);
632 if (link->ce_mask & LINK_ATTR_BRD)
633 dp_dump_line(p, line++,
" <broadcast>%s</broadcast>\n",
636 if (link->ce_mask & LINK_ATTR_STATS) {
637 dp_dump_line(p, line++,
" <stats>\n");
638 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
639 rtnl_link_stat2str(i, buf,
sizeof(buf));
640 dp_dump_line(p, line++,
641 " <%s>%" PRIu64
"</%s>\n",
642 buf, link->l_stats[i], buf);
644 dp_dump_line(p, line++,
" </stats>\n");
647 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_XML]) {
648 dp_dump_line(p, line++,
" <info>\n");
649 line = link->l_info_ops->io_dump[
NL_DUMP_XML](link, p, line);
650 dp_dump_line(p, line++,
" </info>\n");
653 dp_dump_line(p, line++,
"</link>\n");
657 struct rtnl_lifmap l_map;
663 static int link_dump_env(
struct nl_object *obj,
struct nl_dump_params *p)
665 struct rtnl_link *link = (
struct rtnl_link *) obj;
666 struct nl_cache *cache = dp_cache(obj);
670 dp_dump_line(p, line++,
"LINK_NAME=%s\n", link->l_name);
671 dp_dump_line(p, line++,
"LINK_IFINDEX=%u\n", link->l_index);
672 dp_dump_line(p, line++,
"LINK_FAMILY=%s\n",
673 nl_af2str(link->l_family, buf,
sizeof(buf)));
674 dp_dump_line(p, line++,
"LINK_TYPE=%s\n",
675 nl_llproto2str(link->l_arptype, buf,
sizeof(buf)));
676 if (link->ce_mask & LINK_ATTR_ADDR)
677 dp_dump_line(p, line++,
"LINK_ADDRESS=%s\n",
679 dp_dump_line(p, line++,
"LINK_MTU=%u\n", link->l_mtu);
680 dp_dump_line(p, line++,
"LINK_TXQUEUELEN=%u\n", link->l_txqlen);
681 dp_dump_line(p, line++,
"LINK_WEIGHT=%u\n", link->l_weight);
683 rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf,
sizeof(buf));
685 dp_dump_line(p, line++,
"LINK_FLAGS=%s\n", buf);
687 if (link->ce_mask & LINK_ATTR_QDISC)
688 dp_dump_line(p, line++,
"LINK_QDISC=%s\n", link->l_qdisc);
690 if (link->ce_mask & LINK_ATTR_LINK) {
693 dp_dump_line(p, line++,
"LINK_LINK_IFINDEX=%d\n", link->l_link);
695 dp_dump_line(p, line++,
"LINK_LINK_IFNAME=%s\n",
701 if (link->ce_mask & LINK_ATTR_MASTER) {
702 struct rtnl_link *master =
rtnl_link_get(cache, link->l_master);
703 dp_dump_line(p, line++,
"LINK_MASTER=%s\n",
704 master ? master->l_name :
"none");
706 rtnl_link_put(master);
709 if (link->ce_mask & LINK_ATTR_BRD)
710 dp_dump_line(p, line++,
"LINK_BROADCAST=%s\n",
713 if (link->ce_mask & LINK_ATTR_STATS) {
714 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
717 sprintf(buf,
"LINK_");
718 rtnl_link_stat2str(i, buf + 5,
sizeof(buf) - 5);
723 dp_dump_line(p, line++,
724 "%s=%" PRIu64
"\n", buf, link->l_stats[i]);
728 if (link->l_info_ops && link->l_info_ops->io_dump[
NL_DUMP_ENV])
729 line = link->l_info_ops->io_dump[
NL_DUMP_ENV](link, p, line);
735 static int link_handle_event(
struct nl_object *a,
struct rtnl_link_event_cb *cb)
737 struct rtnl_link *l = (
struct rtnl_link *) a;
738 struct nl_cache *c = dp_cache(a);
741 if (l->l_change == ~0U) {
742 if (l->ce_msgtype == RTM_NEWLINK)
745 cb->le_unregister(l);
750 if (l->l_change & IFF_SLAVE) {
751 if (l->l_flags & IFF_SLAVE) {
753 cb->le_new_bonding(l, m);
757 cb->le_cancel_bonding(l);
761 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
762 dp_dump_line(p, line++,
"link %s changed state to %s.\n",
763 l->l_name, l->l_flags & IFF_UP ?
"up" :
"down");
765 if (l->l_change & IFF_PROMISC) {
766 dp_new_line(p, line++);
767 dp_dump(p,
"link %s %s promiscuous mode.\n",
768 l->l_name, l->l_flags & IFF_PROMISC ?
"entered" :
"left");
772 dp_dump_line(p, line++,
"link %s sent unknown event.\n",
780 static int link_compare(
struct nl_object *_a,
struct nl_object *_b,
781 uint32_t attrs,
int flags)
783 struct rtnl_link *a = (
struct rtnl_link *) _a;
784 struct rtnl_link *b = (
struct rtnl_link *) _b;
787 #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
789 diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
790 diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
791 diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
792 diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
793 diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
794 diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
795 diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
796 diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
797 diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
798 diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
799 diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
800 diff |= LINK_DIFF(ADDR,
nl_addr_cmp(a->l_addr, b->l_addr));
801 diff |= LINK_DIFF(BRD,
nl_addr_cmp(a->l_bcast, b->l_bcast));
803 if (flags & LOOSE_FLAG_COMPARISON)
804 diff |= LINK_DIFF(FLAGS,
805 (a->l_flags ^ b->l_flags) & b->l_flag_mask);
807 diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
814 static struct trans_tbl link_attrs[] = {
815 __ADD(LINK_ATTR_MTU, mtu)
816 __ADD(LINK_ATTR_LINK, link)
817 __ADD(LINK_ATTR_TXQLEN, txqlen)
818 __ADD(LINK_ATTR_WEIGHT, weight)
819 __ADD(LINK_ATTR_MASTER, master)
820 __ADD(LINK_ATTR_QDISC, qdisc)
821 __ADD(LINK_ATTR_MAP, map)
822 __ADD(LINK_ATTR_ADDR, address)
823 __ADD(LINK_ATTR_BRD, broadcast)
824 __ADD(LINK_ATTR_FLAGS, flags)
825 __ADD(LINK_ATTR_IFNAME, name)
826 __ADD(LINK_ATTR_IFINDEX, ifindex)
827 __ADD(LINK_ATTR_FAMILY, family)
828 __ADD(LINK_ATTR_ARPTYPE, arptype)
829 __ADD(LINK_ATTR_STATS, stats)
830 __ADD(LINK_ATTR_CHANGE, change)
831 __ADD(LINK_ATTR_OPERSTATE, operstate)
832 __ADD(LINK_ATTR_LINKMODE, linkmode)
835 static
char *link_attrs2str(
int attrs,
char *buf,
size_t len)
837 return __flags2str(attrs, buf, len, link_attrs,
838 ARRAY_SIZE(link_attrs));
846 struct rtnl_link *rtnl_link_alloc(
void)
851 void rtnl_link_put(
struct rtnl_link *link)
876 struct nl_cache * cache;
902 struct rtnl_link *link;
904 if (cache->c_ops != &rtnl_link_ops)
907 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
908 if (link->l_index == ifindex) {
930 struct rtnl_link *link;
932 if (cache->c_ops != &rtnl_link_ops)
935 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
936 if (!strcmp(name, link->l_name)) {
971 struct rtnl_link *tmpl,
975 struct ifinfomsg ifi = {
976 .ifi_family = old->l_family,
977 .ifi_index = old->l_index,
980 if (tmpl->ce_mask & LINK_ATTR_FLAGS) {
981 ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
982 ifi.ifi_flags |= tmpl->l_flags;
987 goto nla_put_failure;
989 if (
nlmsg_append(msg, &ifi,
sizeof(ifi), NLMSG_ALIGNTO) < 0)
990 goto nla_put_failure;
992 if (tmpl->ce_mask & LINK_ATTR_ADDR)
995 if (tmpl->ce_mask & LINK_ATTR_BRD)
998 if (tmpl->ce_mask & LINK_ATTR_MTU)
1001 if (tmpl->ce_mask & LINK_ATTR_TXQLEN)
1004 if (tmpl->ce_mask & LINK_ATTR_WEIGHT)
1007 if (tmpl->ce_mask & LINK_ATTR_IFNAME)
1010 if (tmpl->ce_mask & LINK_ATTR_OPERSTATE)
1011 NLA_PUT_U8(msg, IFLA_OPERSTATE, tmpl->l_operstate);
1013 if (tmpl->ce_mask & LINK_ATTR_LINKMODE)
1014 NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode);
1016 if ((tmpl->ce_mask & LINK_ATTR_LINKINFO) && tmpl->l_info_ops &&
1017 tmpl->l_info_ops->io_put_attrs) {
1018 struct nlattr *info;
1021 goto nla_put_failure;
1025 if (tmpl->l_info_ops->io_put_attrs(msg, tmpl) < 0)
1026 goto nla_put_failure;
1054 struct rtnl_link *tmpl,
int flags)
1061 return nl_errno(ENOMEM);
1096 strncpy(dst, link->l_name, len - 1);
1097 rtnl_link_put(link);
1114 struct rtnl_link *link;
1118 ifindex = link->l_index;
1119 rtnl_link_put(link);
1132 static struct trans_tbl link_flags[] = {
1133 __ADD(IFF_LOOPBACK, loopback)
1134 __ADD(IFF_BROADCAST, broadcast)
1135 __ADD(IFF_POINTOPOINT, pointopoint)
1136 __ADD(IFF_MULTICAST, multicast)
1137 __ADD(IFF_NOARP, noarp)
1138 __ADD(IFF_ALLMULTI, allmulti)
1139 __ADD(IFF_PROMISC, promisc)
1140 __ADD(IFF_MASTER, master)
1141 __ADD(IFF_SLAVE, slave)
1142 __ADD(IFF_DEBUG, debug)
1143 __ADD(IFF_DYNAMIC, dynamic)
1144 __ADD(IFF_AUTOMEDIA, automedia)
1145 __ADD(IFF_PORTSEL, portsel)
1146 __ADD(IFF_NOTRAILERS, notrailers)
1148 __ADD(IFF_RUNNING, running)
1149 __ADD(IFF_LOWER_UP, lowerup)
1150 __ADD(IFF_DORMANT, dormant)
1151 __ADD(IFF_ECHO, echo)
1154 char * rtnl_link_flags2str(
int flags,
char *buf,
size_t len)
1156 return __flags2str(flags, buf, len, link_flags,
1157 ARRAY_SIZE(link_flags));
1160 int rtnl_link_str2flags(
const char *name)
1162 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
1172 static struct trans_tbl link_stats[] = {
1173 __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
1174 __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
1175 __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
1176 __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
1177 __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
1178 __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
1179 __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
1180 __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
1181 __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
1182 __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
1183 __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
1184 __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
1185 __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
1186 __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
1187 __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
1188 __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
1189 __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
1190 __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
1191 __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
1192 __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
1193 __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
1194 __ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
1195 __ADD(RTNL_LINK_MULTICAST, multicast)
1198 char *rtnl_link_stat2str(
int st,
char *buf,
size_t len)
1200 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
1203 int rtnl_link_str2stat(
const char *name)
1205 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
1215 static struct trans_tbl link_operstates[] = {
1216 __ADD(IF_OPER_UNKNOWN, unknown)
1217 __ADD(IF_OPER_NOTPRESENT, notpresent)
1218 __ADD(IF_OPER_DOWN, down)
1219 __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
1220 __ADD(IF_OPER_TESTING, testing)
1221 __ADD(IF_OPER_DORMANT, dormant)
1222 __ADD(IF_OPER_UP, up)
1225 char *rtnl_link_operstate2str(
int st,
char *buf,
size_t len)
1227 return __type2str(st, buf, len, link_operstates,
1228 ARRAY_SIZE(link_operstates));
1231 int rtnl_link_str2operstate(
const char *name)
1233 return __str2type(name, link_operstates,
1234 ARRAY_SIZE(link_operstates));
1244 static struct trans_tbl link_modes[] = {
1245 __ADD(IF_LINK_MODE_DEFAULT,
default)
1246 __ADD(IF_LINK_MODE_DORMANT, dormant)
1249 char *rtnl_link_mode2str(
int st,
char *buf,
size_t len)
1251 return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
1254 int rtnl_link_str2mode(
const char *name)
1256 return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
1266 void rtnl_link_set_qdisc(
struct rtnl_link *link,
const char *qdisc)
1268 strncpy(link->l_qdisc, qdisc,
sizeof(link->l_qdisc) - 1);
1269 link->ce_mask |= LINK_ATTR_QDISC;
1272 char *rtnl_link_get_qdisc(
struct rtnl_link *link)
1274 if (link->ce_mask & LINK_ATTR_QDISC)
1275 return link->l_qdisc;
1280 void rtnl_link_set_name(
struct rtnl_link *link,
const char *name)
1282 strncpy(link->l_name, name,
sizeof(link->l_name) - 1);
1283 link->ce_mask |= LINK_ATTR_IFNAME;
1286 char *rtnl_link_get_name(
struct rtnl_link *link)
1288 if (link->ce_mask & LINK_ATTR_IFNAME)
1289 return link->l_name;
1294 static inline void __assign_addr(
struct rtnl_link *link,
struct nl_addr **pos,
1295 struct nl_addr *
new,
int flag)
1303 link->ce_mask |= flag;
1306 void rtnl_link_set_addr(
struct rtnl_link *link,
struct nl_addr *addr)
1308 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1311 struct nl_addr *rtnl_link_get_addr(
struct rtnl_link *link)
1313 if (link->ce_mask & LINK_ATTR_ADDR)
1314 return link->l_addr;
1319 void rtnl_link_set_broadcast(
struct rtnl_link *link,
struct nl_addr *brd)
1321 __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
1324 struct nl_addr *rtnl_link_get_broadcast(
struct rtnl_link *link)
1326 if (link->ce_mask & LINK_ATTR_BRD)
1327 return link->l_bcast;
1332 void rtnl_link_set_flags(
struct rtnl_link *link,
unsigned int flags)
1334 link->l_flag_mask |= flags;
1335 link->l_flags |= flags;
1336 link->ce_mask |= LINK_ATTR_FLAGS;
1339 void rtnl_link_unset_flags(
struct rtnl_link *link,
unsigned int flags)
1341 link->l_flag_mask |= flags;
1342 link->l_flags &= ~flags;
1343 link->ce_mask |= LINK_ATTR_FLAGS;
1346 unsigned int rtnl_link_get_flags(
struct rtnl_link *link)
1348 return link->l_flags;
1351 void rtnl_link_set_family(
struct rtnl_link *link,
int family)
1353 link->l_family = family;
1354 link->ce_mask |= LINK_ATTR_FAMILY;
1357 int rtnl_link_get_family(
struct rtnl_link *link)
1359 if (link->l_family & LINK_ATTR_FAMILY)
1360 return link->l_family;
1365 void rtnl_link_set_arptype(
struct rtnl_link *link,
unsigned int arptype)
1367 link->l_arptype = arptype;
1370 unsigned int rtnl_link_get_arptype(
struct rtnl_link *link)
1372 return link->l_arptype;
1375 void rtnl_link_set_ifindex(
struct rtnl_link *link,
int ifindex)
1377 link->l_index = ifindex;
1378 link->ce_mask |= LINK_ATTR_IFINDEX;
1381 int rtnl_link_get_ifindex(
struct rtnl_link *link)
1383 if (link->ce_mask & LINK_ATTR_IFINDEX)
1384 return link->l_index;
1389 void rtnl_link_set_mtu(
struct rtnl_link *link,
unsigned int mtu)
1392 link->ce_mask |= LINK_ATTR_MTU;
1395 unsigned int rtnl_link_get_mtu(
struct rtnl_link *link)
1397 if (link->ce_mask & LINK_ATTR_MTU)
1403 void rtnl_link_set_txqlen(
struct rtnl_link *link,
unsigned int txqlen)
1405 link->l_txqlen = txqlen;
1406 link->ce_mask |= LINK_ATTR_TXQLEN;
1409 unsigned int rtnl_link_get_txqlen(
struct rtnl_link *link)
1411 if (link->ce_mask & LINK_ATTR_TXQLEN)
1412 return link->l_txqlen;
1417 void rtnl_link_set_weight(
struct rtnl_link *link,
unsigned int weight)
1419 link->l_weight = weight;
1420 link->ce_mask |= LINK_ATTR_WEIGHT;
1423 unsigned int rtnl_link_get_weight(
struct rtnl_link *link)
1425 if (link->ce_mask & LINK_ATTR_WEIGHT)
1426 return link->l_weight;
1431 void rtnl_link_set_link(
struct rtnl_link *link,
int ifindex)
1433 link->l_link = ifindex;
1434 link->ce_mask |= LINK_ATTR_LINK;
1437 int rtnl_link_get_link(
struct rtnl_link *link)
1439 if (link->ce_mask & LINK_ATTR_LINK)
1440 return link->l_link;
1445 void rtnl_link_set_master(
struct rtnl_link *link,
int ifindex)
1447 link->l_master = ifindex;
1448 link->ce_mask |= LINK_ATTR_MASTER;
1451 int rtnl_link_get_master(
struct rtnl_link *link)
1453 if (link->ce_mask & LINK_ATTR_MASTER)
1454 return link->l_master;
1459 void rtnl_link_set_operstate(
struct rtnl_link *link, uint8_t operstate)
1461 link->l_operstate = operstate;
1462 link->ce_mask |= LINK_ATTR_OPERSTATE;
1465 uint8_t rtnl_link_get_operstate(
struct rtnl_link *link)
1467 if (link->ce_mask & LINK_ATTR_OPERSTATE)
1468 return link->l_operstate;
1470 return IF_OPER_UNKNOWN;
1473 void rtnl_link_set_linkmode(
struct rtnl_link *link, uint8_t linkmode)
1475 link->l_linkmode = linkmode;
1476 link->ce_mask |= LINK_ATTR_LINKMODE;
1479 uint8_t rtnl_link_get_linkmode(
struct rtnl_link *link)
1481 if (link->ce_mask & LINK_ATTR_LINKMODE)
1482 return link->l_linkmode;
1484 return IF_LINK_MODE_DEFAULT;
1487 uint64_t rtnl_link_get_stat(
struct rtnl_link *link,
int id)
1489 if (id < 0 || id > RTNL_LINK_STATS_MAX)
1492 return link->l_stats[id];
1511 if ((io = rtnl_link_info_ops_lookup(type)) == NULL)
1512 return nl_error(ENOENT,
"No such link info type exists");
1514 if (link->l_info_ops)
1515 release_link_info(link);
1517 if ((err = io->
io_alloc(link)) < 0)
1520 link->l_info_ops = io;
1534 if (link->l_info_ops)
1535 return link->l_info_ops->io_name;
1544 .oo_size =
sizeof(
struct rtnl_link),
1545 .oo_free_data = link_free_data,
1546 .oo_clone = link_clone,
1552 .oo_compare = link_compare,
1553 .oo_attrs2str = link_attrs2str,
1554 .oo_id_attrs = LINK_ATTR_IFINDEX,
1558 { AF_UNSPEC, RTNLGRP_LINK },
1559 { END_OF_GROUP_LIST },
1563 .co_name =
"route/link",
1564 .co_hdrsize =
sizeof(
struct ifinfomsg),
1566 { RTM_NEWLINK, NL_ACT_NEW,
"new" },
1567 { RTM_DELLINK, NL_ACT_DEL,
"del" },
1568 { RTM_GETLINK, NL_ACT_GET,
"get" },
1569 END_OF_MSGTYPES_LIST,
1571 .co_protocol = NETLINK_ROUTE,
1572 .co_groups = link_groups,
1573 .co_request_update = link_request_update,
1574 .co_msg_parser = link_msg_parser,
1575 .co_obj_ops = &link_obj_ops,
1578 static void __init link_init(
void)
1583 static void __exit link_exit(
void)