2 * lib/route/link.c Links (Interfaces)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
14 * @defgroup link Links (Interfaces)
17 * @par Link Identification
18 * A link can be identified by either its interface index or by its
19 * name. The kernel favours the interface index but falls back to the
20 * interface name if the interface index is lesser-than 0 for kernels
21 * >= 2.6.11. Therefore you can request changes without mapping a
22 * interface name to the corresponding index first.
24 * @par Changeable Attributes
25 * @anchor link_changeable
26 * - Link layer address
27 * - Link layer broadcast address
28 * - device mapping (ifmap) (>= 2.6.9)
30 * - Transmission queue length (>= 2.6.9)
32 * - Link name (only via access through interface index) (>= 2.6.9)
45 * @par Link Flags (linux/if.h)
48 * IFF_UP Status of link (up|down)
49 * IFF_BROADCAST Indicates this link allows broadcasting
50 * IFF_MULTICAST Indicates this link allows multicasting
51 * IFF_ALLMULTI Indicates this link is doing multicast routing
52 * IFF_DEBUG Tell the driver to do debugging (currently unused)
53 * IFF_LOOPBACK This is the loopback link
54 * IFF_POINTOPOINT Point-to-point link
55 * IFF_NOARP Link is unable to perform ARP
56 * IFF_PROMISC Status of promiscious mode flag
57 * IFF_MASTER Used by teql
58 * IFF_SLAVE Used by teql
59 * IFF_PORTSEL Indicates this link allows port selection
60 * IFF_AUTOMEDIA Indicates this link selects port automatically
61 * IFF_DYNAMIC Indicates the address of this link is dynamic
62 * IFF_RUNNING Link is running and carrier is ok.
63 * IFF_NOTRAILERS Unused, BSD compat.
66 * @par Notes on IFF_PROMISC and IFF_ALLMULTI flags
67 * Although you can query the status of IFF_PROMISC and IFF_ALLMULTI
68 * they do not represent the actual state in the kernel but rather
69 * whether the flag has been enabled/disabled by userspace. The link
70 * may be in promiscious mode even if IFF_PROMISC is not set in a link
71 * dump request response because promiscity might be needed by the driver
72 * for a period of time.
74 * @par 1) Retrieving information about available links
76 * // The first step is to retrieve a list of all available interfaces within
77 * // the kernel and put them into a cache.
78 * struct nl_cache *cache = rtnl_link_alloc_cache(nl_handle);
80 * // In a second step, a specific link may be looked up by either interface
81 * // index or interface name.
82 * struct rtnl_link *link = rtnl_link_get_by_name(cache, "lo");
84 * // rtnl_link_get_by_name() is the short version for translating the
85 * // interface name to an interface index first like this:
86 * int ifindex = rtnl_link_name2i(cache, "lo");
87 * struct rtnl_link *link = rtnl_link_get(cache, ifindex);
89 * // After successful usage, the object must be given back to the cache
90 * rtnl_link_put(link);
93 * @par 2) Changing link attributes
95 * // In order to change any attributes of an existing link, we must allocate
96 * // a new link to hold the change requests:
97 * struct rtnl_link *request = rtnl_link_alloc();
99 * // Now we can go on and specify the attributes we want to change:
100 * rtnl_link_set_weight(request, 300);
101 * rtnl_link_set_mtu(request, 1360);
103 * // We can also shut an interface down administratively
104 * rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
106 * // Actually, we should know which link to change, so let's look it up
107 * struct rtnl_link *old = rtnl_link_get(cache, "eth0");
109 * // Two ways exist to commit this change request, the first one is to
110 * // build the required netlink message and send it out in one single
112 * rtnl_link_change(nl_handle, old, request);
114 * // An alternative way is to build the netlink message and send it
115 * // out yourself using nl_send_auto_complete()
116 * struct nl_msg *msg = rtnl_link_build_change_request(old, request);
117 * nl_send_auto_complete(nl_handle, nlmsg_hdr(msg));
120 * // Don't forget to give back the link object ;->
121 * rtnl_link_put(old);
126 #include <netlink-local.h>
127 #include <netlink/netlink.h>
128 #include <netlink/attr.h>
129 #include <netlink/utils.h>
130 #include <netlink/object.h>
131 #include <netlink/route/rtnl.h>
132 #include <netlink/route/link.h>
135 #define LINK_ATTR_MTU 0x0001
136 #define LINK_ATTR_LINK 0x0002
137 #define LINK_ATTR_TXQLEN 0x0004
138 #define LINK_ATTR_WEIGHT 0x0008
139 #define LINK_ATTR_MASTER 0x0010
140 #define LINK_ATTR_QDISC 0x0020
141 #define LINK_ATTR_MAP 0x0040
142 #define LINK_ATTR_ADDR 0x0080
143 #define LINK_ATTR_BRD 0x0100
144 #define LINK_ATTR_FLAGS 0x0200
145 #define LINK_ATTR_IFNAME 0x0400
146 #define LINK_ATTR_IFINDEX 0x0800
147 #define LINK_ATTR_FAMILY 0x1000
148 #define LINK_ATTR_ARPTYPE 0x2000
149 #define LINK_ATTR_STATS 0x4000
150 #define LINK_ATTR_CHANGE 0x8000
152 static struct nl_cache_ops rtnl_link_ops;
155 static void link_free_data(struct nl_object *c)
157 struct rtnl_link *link = nl_object_priv(c);
160 nl_addr_put(link->l_addr);
161 nl_addr_put(link->l_bcast);
165 static struct nla_policy link_policy[IFLA_MAX+1] = {
166 [IFLA_IFNAME] = { .type = NLA_STRING,
167 .maxlen = IFNAMSIZ },
168 [IFLA_MTU] = { .type = NLA_U32 },
169 [IFLA_TXQLEN] = { .type = NLA_U32 },
170 [IFLA_LINK] = { .type = NLA_U32 },
171 [IFLA_WEIGHT] = { .type = NLA_U32 },
172 [IFLA_MASTER] = { .type = NLA_U32 },
173 [IFLA_QDISC] = { .type = NLA_STRING,
174 .maxlen = IFQDISCSIZ },
175 [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) },
176 [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) },
179 static int link_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *n,
182 struct rtnl_link *link;
183 struct ifinfomsg *ifi;
184 struct nlattr *tb[IFLA_MAX+1];
185 struct nl_parser_param *pp = arg;
188 link = rtnl_link_alloc();
190 err = nl_errno(ENOMEM);
194 link->ce_msgtype = n->nlmsg_type;
196 err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy);
200 if (tb[IFLA_IFNAME] == NULL) {
201 err = nl_error(EINVAL, "Missing link name TLV");
205 nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
208 link->l_family = ifi->ifi_family;
209 link->l_arptype = ifi->ifi_type;
210 link->l_index = ifi->ifi_index;
211 link->l_flags = ifi->ifi_flags;
212 link->l_change = ifi->ifi_change;
213 link->l_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY | LINK_ATTR_ARPTYPE|
214 LINK_ATTR_IFINDEX | LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
216 if (tb[IFLA_STATS]) {
217 struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]);
219 link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets;
220 link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes;
221 link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors;
222 link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped;
223 link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed;
224 link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors;
225 link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets;
226 link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes;
227 link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors;
228 link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped;
229 link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed;
230 link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors;
231 link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors;
232 link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors;
233 link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors;
234 link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors;
235 link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors;
236 link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors;
237 link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors;
238 link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors;
239 link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors;
240 link->l_stats[RTNL_LINK_MULTICAST] = st->multicast;
242 link->l_mask |= LINK_ATTR_STATS;
245 if (tb[IFLA_TXQLEN]) {
246 link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]);
247 link->l_mask |= LINK_ATTR_TXQLEN;
251 link->l_mtu = nla_get_u32(tb[IFLA_MTU]);
252 link->l_mask |= LINK_ATTR_MTU;
255 if (tb[IFLA_ADDRESS]) {
256 link->l_addr = nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
257 if (link->l_addr == NULL)
259 nl_addr_set_family(link->l_addr,
260 nl_addr_guess_family(link->l_addr));
261 link->l_mask |= LINK_ATTR_ADDR;
264 if (tb[IFLA_BROADCAST]) {
265 link->l_bcast = nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
266 if (link->l_bcast == NULL)
268 nl_addr_set_family(link->l_bcast,
269 nl_addr_guess_family(link->l_bcast));
270 link->l_mask |= LINK_ATTR_BRD;
274 link->l_link = nla_get_u32(tb[IFLA_LINK]);
275 link->l_mask |= LINK_ATTR_LINK;
278 if (tb[IFLA_WEIGHT]) {
279 link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]);
280 link->l_mask |= LINK_ATTR_WEIGHT;
283 if (tb[IFLA_QDISC]) {
284 nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
285 link->l_mask |= LINK_ATTR_QDISC;
289 struct rtnl_link_ifmap *map = nla_data(tb[IFLA_MAP]);
290 link->l_map.lm_mem_start = map->mem_start;
291 link->l_map.lm_mem_end = map->mem_end;
292 link->l_map.lm_base_addr = map->base_addr;
293 link->l_map.lm_irq = map->irq;
294 link->l_map.lm_dma = map->dma;
295 link->l_map.lm_port = map->port;
296 link->l_mask |= LINK_ATTR_MAP;
299 if (tb[IFLA_MASTER]) {
300 link->l_master = nla_get_u32(tb[IFLA_MASTER]);
301 link->l_mask |= LINK_ATTR_MASTER;
304 err = pp->pp_cb((struct nl_object *) link, pp);
315 static int link_request_update(struct nl_cache *c, struct nl_handle *h)
317 return nl_rtgen_request(h, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
320 static int link_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
323 struct nl_cache *cache = dp_cache(obj);
324 struct rtnl_link *link = (struct rtnl_link *) obj;
327 dp_dump(p, "%s ", link->l_name);
329 if (link->l_mask & LINK_ATTR_LINK) {
330 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
331 dp_dump(p, "@%s", ll ? ll->l_name : "NONE");
336 dp_dump(p, "%s ", nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
337 dp_dump(p, "%s ", link->l_addr ? nl_addr2str(link->l_addr, buf,
338 sizeof(buf)) : "none");
339 dp_dump(p, "mtu %u ", link->l_mtu);
341 if (link->l_mask & LINK_ATTR_MASTER) {
342 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
343 dp_dump(p, "master %s ", master ? master->l_name : "inv");
345 rtnl_link_put(master);
348 rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
350 dp_dump(p, "<%s>", buf);
357 static int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
359 struct rtnl_link *link = (struct rtnl_link *) obj;
363 line = link_dump_brief(obj, p);
364 dp_new_line(p, line++);
366 dp_dump(p, " txqlen %u weight %u ", link->l_txqlen, link->l_weight);
368 if (link->l_mask & LINK_ATTR_QDISC)
369 dp_dump(p, "qdisc %s ", link->l_qdisc);
371 if (link->l_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
372 dp_dump(p, "irq %u ", link->l_map.lm_irq);
374 if (link->l_mask & LINK_ATTR_IFINDEX)
375 dp_dump(p, "index %u ", link->l_index);
377 if (link->l_mask & LINK_ATTR_BRD)
378 dp_dump(p, "brd %s", nl_addr2str(link->l_bcast, buf,
386 static int link_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
388 struct rtnl_link *link = (struct rtnl_link *) obj;
393 line = link_dump_full(obj, p);
395 dp_dump_line(p, line++, " Stats: bytes packets errors "
396 " dropped fifo-err compressed\n");
398 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit);
400 strcpy(fmt, " RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
401 fmt[9] = *unit == 'B' ? '9' : '7';
403 dp_dump_line(p, line++, fmt,
405 link->l_stats[RTNL_LINK_RX_PACKETS],
406 link->l_stats[RTNL_LINK_RX_ERRORS],
407 link->l_stats[RTNL_LINK_RX_DROPPED],
408 link->l_stats[RTNL_LINK_RX_FIFO_ERR],
409 link->l_stats[RTNL_LINK_RX_COMPRESSED]);
411 res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit);
413 strcpy(fmt, " TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
414 fmt[9] = *unit == 'B' ? '9' : '7';
416 dp_dump_line(p, line++, fmt,
418 link->l_stats[RTNL_LINK_TX_PACKETS],
419 link->l_stats[RTNL_LINK_TX_ERRORS],
420 link->l_stats[RTNL_LINK_TX_DROPPED],
421 link->l_stats[RTNL_LINK_TX_FIFO_ERR],
422 link->l_stats[RTNL_LINK_TX_COMPRESSED]);
424 dp_dump_line(p, line++, " Errors: length over crc "
425 " frame missed multicast\n");
427 dp_dump_line(p, line++, " RX %10" PRIu64 " %10" PRIu64 " %10"
428 PRIu64 " %10" PRIu64 " %10" PRIu64 " %10"
430 link->l_stats[RTNL_LINK_RX_LEN_ERR],
431 link->l_stats[RTNL_LINK_RX_OVER_ERR],
432 link->l_stats[RTNL_LINK_RX_CRC_ERR],
433 link->l_stats[RTNL_LINK_RX_FRAME_ERR],
434 link->l_stats[RTNL_LINK_RX_MISSED_ERR],
435 link->l_stats[RTNL_LINK_MULTICAST]);
437 dp_dump_line(p, line++, " Errors: aborted carrier heartbeat "
438 " window collision\n");
440 dp_dump_line(p, line++, " TX %10" PRIu64 " %10" PRIu64 " %10"
441 PRIu64 " %10" PRIu64 " %10" PRIu64 "\n",
442 link->l_stats[RTNL_LINK_TX_ABORT_ERR],
443 link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
444 link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
445 link->l_stats[RTNL_LINK_TX_WIN_ERR],
446 link->l_stats[RTNL_LINK_TX_COLLISIONS]);
451 static int link_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
453 struct rtnl_link *link = (struct rtnl_link *) obj;
454 struct nl_cache *cache = dp_cache(obj);
458 dp_dump_line(p, line++, "<link name=\"%s\" index=\"%u\">\n",
459 link->l_name, link->l_index);
460 dp_dump_line(p, line++, " <family>%s</family>\n",
461 nl_af2str(link->l_family, buf, sizeof(buf)));
462 dp_dump_line(p, line++, " <arptype>%s</arptype>\n",
463 nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
464 dp_dump_line(p, line++, " <address>%s</address>\n",
465 nl_addr2str(link->l_addr, buf, sizeof(buf)));
466 dp_dump_line(p, line++, " <mtu>%u</mtu>\n", link->l_mtu);
467 dp_dump_line(p, line++, " <txqlen>%u</txqlen>\n", link->l_txqlen);
468 dp_dump_line(p, line++, " <weight>%u</weight>\n", link->l_weight);
470 rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
472 dp_dump_line(p, line++, " <flags>%s</flags>\n", buf);
474 if (link->l_mask & LINK_ATTR_QDISC)
475 dp_dump_line(p, line++, " <qdisc>%s</qdisc>\n", link->l_qdisc);
477 if (link->l_mask & LINK_ATTR_LINK) {
478 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
479 dp_dump_line(p, line++, " <link>%s</link>\n",
480 ll ? ll->l_name : "none");
485 if (link->l_mask & LINK_ATTR_MASTER) {
486 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
487 dp_dump_line(p, line++, " <master>%s</master>\n",
488 master ? master->l_name : "none");
490 rtnl_link_put(master);
493 if (link->l_mask & LINK_ATTR_BRD)
494 dp_dump_line(p, line++, " <broadcast>%s</broadcast>\n",
495 nl_addr2str(link->l_bcast, buf, sizeof(buf)));
497 if (link->l_mask & LINK_ATTR_STATS) {
498 dp_dump_line(p, line++, " <stats>\n");
499 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
500 rtnl_link_stat2str(i, buf, sizeof(buf));
501 dp_dump_line(p, line++,
502 " <%s>%" PRIu64 "</%s>\n",
503 buf, link->l_stats[i], buf);
505 dp_dump_line(p, line++, " </stats>\n");
508 dp_dump_line(p, line++, "</link>\n");
511 uint32_t l_change; /**< Change mask */
512 struct rtnl_lifmap l_map; /**< Interface device mapping */
518 static int link_dump_env(struct nl_object *obj, struct nl_dump_params *p)
520 struct rtnl_link *link = (struct rtnl_link *) obj;
521 struct nl_cache *cache = dp_cache(obj);
525 dp_dump_line(p, line++, "LINK_NAME=%s\n", link->l_name);
526 dp_dump_line(p, line++, "LINK_IFINDEX=%u\n", link->l_index);
527 dp_dump_line(p, line++, "LINK_FAMILY=%s\n",
528 nl_af2str(link->l_family, buf, sizeof(buf)));
529 dp_dump_line(p, line++, "LINK_TYPE=%s\n",
530 nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
531 if (link->l_mask & LINK_ATTR_ADDR)
532 dp_dump_line(p, line++, "LINK_ADDRESS=%s\n",
533 nl_addr2str(link->l_addr, buf, sizeof(buf)));
534 dp_dump_line(p, line++, "LINK_MTU=%u\n", link->l_mtu);
535 dp_dump_line(p, line++, "LINK_TXQUEUELEN=%u\n", link->l_txqlen);
536 dp_dump_line(p, line++, "LINK_WEIGHT=%u\n", link->l_weight);
538 rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf, sizeof(buf));
540 dp_dump_line(p, line++, "LINK_FLAGS=%s\n", buf);
542 if (link->l_mask & LINK_ATTR_QDISC)
543 dp_dump_line(p, line++, "LINK_QDISC=%s\n", link->l_qdisc);
545 if (link->l_mask & LINK_ATTR_LINK) {
546 struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
548 dp_dump_line(p, line++, "LINK_LINK_IFINDEX=%d\n", link->l_link);
550 dp_dump_line(p, line++, "LINK_LINK_IFNAME=%s\n",
556 if (link->l_mask & LINK_ATTR_MASTER) {
557 struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
558 dp_dump_line(p, line++, "LINK_MASTER=%s\n",
559 master ? master->l_name : "none");
561 rtnl_link_put(master);
564 if (link->l_mask & LINK_ATTR_BRD)
565 dp_dump_line(p, line++, "LINK_BROADCAST=%s\n",
566 nl_addr2str(link->l_bcast, buf, sizeof(buf)));
568 if (link->l_mask & LINK_ATTR_STATS) {
569 for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
572 sprintf(buf, "LINK_");
573 rtnl_link_stat2str(i, buf + 5, sizeof(buf) - 5);
578 dp_dump_line(p, line++,
579 "%s=%" PRIu64 "\n", buf, link->l_stats[i]);
587 static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb)
589 struct rtnl_link *l = (struct rtnl_link *) a;
590 struct nl_cache *c = dp_cache(a);
593 if (l->l_change == ~0U) {
594 if (l->ce_msgtype == RTM_NEWLINK)
597 cb->le_unregister(l);
602 if (l->l_change & IFF_SLAVE) {
603 if (l->l_flags & IFF_SLAVE) {
604 struct rtnl_link *m = rtnl_link_get(c, l->l_master);
605 cb->le_new_bonding(l, m);
609 cb->le_cancel_bonding(l);
613 if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
614 dp_dump_line(p, line++, "link %s changed state to %s.\n",
615 l->l_name, l->l_flags & IFF_UP ? "up" : "down");
617 if (l->l_change & IFF_PROMISC) {
618 dp_new_line(p, line++);
619 dp_dump(p, "link %s %s promiscuous mode.\n",
620 l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left");
624 dp_dump_line(p, line++, "link %s sent unknown event.\n",
632 static int link_filter(struct nl_object *obj, struct nl_object *filter)
634 struct rtnl_link *o = (struct rtnl_link *) obj;
635 struct rtnl_link *f = (struct rtnl_link *) filter;
637 #define REQ(F) (f->l_mask & LINK_ATTR_##F)
638 #define AVAIL(F) (o->l_mask & LINK_ATTR_##F)
639 #define F_CUS(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
640 #define F_INT(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N)))
641 if (F_INT(MTU, l_mtu) ||
642 F_INT(LINK, l_link) ||
643 F_INT(TXQLEN, l_txqlen) ||
644 F_INT(WEIGHT, l_weight) ||
645 F_INT(MASTER, l_master) ||
646 F_INT(IFINDEX, l_index) ||
647 F_INT(FAMILY, l_family) ||
648 F_CUS(QDISC, strcmp(o->l_qdisc, f->l_qdisc)) ||
649 F_CUS(IFNAME, strcmp(o->l_name, f->l_name)) ||
650 F_CUS(ADDR, nl_addr_cmp(o->l_addr, f->l_addr)) ||
651 F_CUS(BRD, nl_addr_cmp(o->l_bcast, f->l_bcast)) ||
652 F_CUS(FLAGS, f->l_flags ^ (o->l_flags & f->l_flag_mask)))
663 * @name Link Object Allocation/Freeage
668 * Allocate and initialize new link object.
669 * @note Free the memory after usage using rtnl_link_put() or rtnl_link_free().
670 * @return Newly allocated link object or NULL if an error occured.
672 struct rtnl_link *rtnl_link_alloc(void)
674 return (struct rtnl_link *) nl_object_alloc_from_ops(&rtnl_link_ops);
678 * Give back reference on link object.
679 * @arg link Link object to be given back.
681 * Decrements the reference counter and frees the object if the
682 * last reference has been released.
684 void rtnl_link_put(struct rtnl_link *link)
686 nl_object_put((struct nl_object *) link);
690 * @arg link Link object to be freed.
692 * @note Always use rtnl_link_put() unless you're absolutely sure
693 * that no other user may have a reference on this object.
695 void rtnl_link_free(struct rtnl_link *link)
697 nl_object_free((struct nl_object *) link);
703 * @name Link Cache Management
709 * Allocate link cache and fill in all configured links.
710 * @arg handle Netlink handle.
712 * Allocates a new link cache, initializes it properly and updates it
713 * to include all links currently configured in the kernel.
715 * @note Free the memory after usage.
716 * @return Newly allocated cache or NULL if an error occured.
718 struct nl_cache *rtnl_link_alloc_cache(struct nl_handle *handle)
720 struct nl_cache * cache;
722 cache = nl_cache_alloc_from_ops(&rtnl_link_ops);
726 if (nl_cache_update(handle, cache) < 0) {
727 nl_cache_free(cache);
735 * Look up link by interface index in the provided cache
736 * @arg cache link cache
737 * @arg ifindex link interface index
739 * The caller owns a reference on the returned object and
740 * must give the object back via rtnl_link_put().
742 * @return pointer to link inside the cache or NULL if no match was found.
744 struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex)
746 struct rtnl_link *link;
748 if (cache->c_ops != &rtnl_link_ops)
751 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
752 if (link->l_index == ifindex) {
753 nl_object_get((struct nl_object *) link);
762 * Look up link by link name in the provided cache
763 * @arg cache link cache
764 * @arg name link name
766 * The caller owns a reference on the returned object and
767 * must give the object back via rtnl_link_put().
769 * @return pointer to link inside the cache or NULL if no match was found.
771 struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache,
774 struct rtnl_link *link;
776 if (cache->c_ops != &rtnl_link_ops)
779 nl_list_for_each_entry(link, &cache->c_items, ce_list) {
780 if (!strcmp(name, link->l_name)) {
781 nl_object_get((struct nl_object *) link);
792 * @name Link Modifications
797 * Builds a netlink change request message to change link attributes
798 * @arg old link to be changed
799 * @arg tmpl template with requested changes
800 * @arg flags additional netlink message flags
802 * Builds a new netlink message requesting a change of link attributes.
803 * The netlink message header isn't fully equipped with all relevant
804 * fields and must be sent out via nl_send_auto_complete() or
805 * supplemented as needed.
806 * \a old must point to a link currently configured in the kernel
807 * and \a tmpl must contain the attributes to be changed set via
808 * \c rtnl_link_set_* functions.
810 * @return New netlink message
811 * @note Not all attributes can be changed, see
812 * \ref link_changeable "Changeable Attributes" for more details.
814 struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old,
815 struct rtnl_link *tmpl,
819 struct ifinfomsg ifi = {
820 .ifi_family = old->l_family,
821 .ifi_index = old->l_index,
824 if (tmpl->l_mask & LINK_ATTR_FLAGS) {
825 ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
826 ifi.ifi_flags |= tmpl->l_flags;
829 msg = nlmsg_build_simple(RTM_SETLINK, flags);
831 goto nla_put_failure;
833 if (nlmsg_append(msg, &ifi, sizeof(ifi), 1) < 0)
834 goto nla_put_failure;
836 if (tmpl->l_mask & LINK_ATTR_ADDR)
837 NLA_PUT_ADDR(msg, IFLA_ADDRESS, tmpl->l_addr);
839 if (tmpl->l_mask & LINK_ATTR_BRD)
840 NLA_PUT_ADDR(msg, IFLA_BROADCAST, tmpl->l_bcast);
842 if (tmpl->l_mask & LINK_ATTR_MTU)
843 NLA_PUT_U32(msg, IFLA_MTU, tmpl->l_mtu);
845 if (tmpl->l_mask & LINK_ATTR_TXQLEN)
846 NLA_PUT_U32(msg, IFLA_TXQLEN, tmpl->l_txqlen);
848 if (tmpl->l_mask & LINK_ATTR_WEIGHT)
849 NLA_PUT_U32(msg, IFLA_WEIGHT, tmpl->l_weight);
851 if (tmpl->l_mask & LINK_ATTR_IFNAME)
852 NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name);
862 * Change link attributes
863 * @arg handle netlink handle
864 * @arg old link to be changed
865 * @arg tmpl template with requested changes
866 * @arg flags additional netlink message flags
868 * Builds a new netlink message by calling rtnl_link_build_change_request(),
869 * sends the request to the kernel and waits for the next ACK to be
870 * received, i.e. blocks until the request has been processed.
872 * @return 0 on success or a negative error code
873 * @note Not all attributes can be changed, see
874 * \ref link_changeable "Changeable Attributes" for more details.
876 int rtnl_link_change(struct nl_handle *handle, struct rtnl_link *old,
877 struct rtnl_link *tmpl, int flags)
882 msg = rtnl_link_build_change_request(old, tmpl, flags);
884 return nl_errno(ENOMEM);
886 err = nl_send_auto_complete(handle, msg);
891 return nl_wait_for_ack(handle);
897 * @name Name <-> Index Translations
902 * Translate an interface index to the corresponding link name
903 * @arg cache link cache
904 * @arg ifindex link interface index
905 * @arg dst destination buffer
906 * @arg len length of destination buffer
908 * Translates the specified interface index to the corresponding
909 * link name and stores the name in the destination buffer.
911 * @return link name or NULL if no match was found.
913 char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst,
916 struct rtnl_link *link = rtnl_link_get(cache, ifindex);
919 strncpy(dst, link->l_name, len - 1);
928 * Translate a link name to the corresponding interface index
929 * @arg cache link cache
930 * @arg name link name
932 * @return interface index or RTNL_LINK_NOT_FOUND if no match was found.
934 int rtnl_link_name2i(struct nl_cache *cache, const char *name)
936 int ifindex = RTNL_LINK_NOT_FOUND;
937 struct rtnl_link *link;
939 link = rtnl_link_get_by_name(cache, name);
941 ifindex = link->l_index;
951 * @name Link Flags Translations
955 static struct trans_tbl link_flags[] = {
956 __ADD(IFF_LOOPBACK, loopback)
957 __ADD(IFF_BROADCAST, broadcast)
958 __ADD(IFF_POINTOPOINT, pointopoint)
959 __ADD(IFF_MULTICAST, multicast)
960 __ADD(IFF_NOARP, noarp)
961 __ADD(IFF_ALLMULTI, allmulti)
962 __ADD(IFF_PROMISC, promisc)
963 __ADD(IFF_MASTER, master)
964 __ADD(IFF_SLAVE, slave)
965 __ADD(IFF_DEBUG, debug)
966 __ADD(IFF_DYNAMIC, dynamic)
967 __ADD(IFF_AUTOMEDIA, automedia)
968 __ADD(IFF_PORTSEL, portsel)
969 __ADD(IFF_NOTRAILERS, notrailers)
971 __ADD(IFF_RUNNING, running)
972 __ADD(IFF_LOWER_UP, lowerup)
973 __ADD(IFF_DORMANT, dormant)
977 * Convert link flags to a character string (Reentrant).
978 * @arg flags link flags
979 * @arg buf destination buffer
980 * @arg len buffer length
982 * Converts link flags to a character string separated by
983 * commands and stores it in the specified destination buffer.
985 * \return The destination buffer
987 char * rtnl_link_flags2str(int flags, char *buf, size_t len)
989 return __flags2str(flags, buf, len, link_flags,
990 ARRAY_SIZE(link_flags));
994 * Convert a character string to a link flag
995 * @arg name Name of link flag
997 * Converts the provided character string specifying a link
998 * link the corresponding numeric value.
1000 * \return Link flag or a negative value if none was found.
1002 int rtnl_link_str2flags(const char *name)
1004 return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
1010 * @name Link Statistics Translations
1014 static struct trans_tbl link_stats[] = {
1015 __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
1016 __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
1017 __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
1018 __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
1019 __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
1020 __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
1021 __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
1022 __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
1023 __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
1024 __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
1025 __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
1026 __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
1027 __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
1028 __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
1029 __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
1030 __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
1031 __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
1032 __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
1033 __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
1034 __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
1035 __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
1036 __ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
1037 __ADD(RTNL_LINK_MULTICAST, multicast)
1041 * Convert a link statistic to a character string (Reentrant).
1042 * @arg st link statistic
1043 * @arg buf destination buffer
1044 * @arg len buffer length
1046 * Converts a link statistic to a character string and stores it in
1047 * the specified destination buffer.
1049 * @return The destination buffer or the statistic encoded in
1050 * hexidecimal form if no match was found.
1052 char *rtnl_link_stat2str(int st, char *buf, size_t len)
1054 return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
1058 * Convert a character string to a link statistic
1059 * @arg name name of link statistic
1061 * Converts the provided character string specifying a link
1062 * statistic to the corresponding numeric value.
1064 * @return Link statistic or a negative value if none was found.
1066 int rtnl_link_str2stat(const char *name)
1068 return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
1074 * @name Attribute Modification
1080 * @arg link link to change
1081 * @arg qdisc qdisc name
1083 void rtnl_link_set_qdisc(struct rtnl_link *link, const char *qdisc)
1085 strncpy(link->l_qdisc, qdisc, sizeof(link->l_qdisc) - 1);
1086 link->l_mask |= LINK_ATTR_QDISC;
1091 * @arg link link handle
1092 * @return Name of the qdisc or NULL if not set.
1094 char *rtnl_link_get_qdisc(struct rtnl_link *link)
1096 if (link->l_mask & LINK_ATTR_QDISC)
1097 return link->l_qdisc;
1104 * @arg link link to change
1105 * @arg name new link name
1107 void rtnl_link_set_name(struct rtnl_link *link, const char *name)
1109 strncpy(link->l_name, name, sizeof(link->l_name) - 1);
1110 link->l_mask |= LINK_ATTR_IFNAME;
1115 * @arg link link handle
1116 * @return Name of the link or NULL if not set.
1118 char *rtnl_link_get_name(struct rtnl_link *link)
1120 if (link->l_mask & LINK_ATTR_IFNAME)
1121 return link->l_name;
1126 static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
1127 struct nl_addr *new, int flag)
1135 link->l_mask |= flag;
1139 * Set link layer address
1140 * @arg link link to change
1141 * @arg addr new link layer address
1143 void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
1145 __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1149 * Get link layer address
1150 * @arg link link handle
1151 * @return link layer address or NULL if not set
1153 struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
1155 if (link->l_mask & LINK_ATTR_ADDR)
1156 return link->l_addr;
1162 * Set link layer broadcast address
1163 * @arg link link to change
1164 * @arg brd new link layer broadcast address
1166 * Assigns the new broadcast address to the specified link handle.
1168 * @note The prefix length of the address will be ignored.
1170 void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *brd)
1172 __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
1176 * Get link layer broadcast address
1177 * @arg link link handle
1178 * @return Link layer broadcast address or NULL if not set
1180 struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
1182 if (link->l_mask & LINK_ATTR_BRD)
1183 return link->l_bcast;
1190 * @arg link link to change
1191 * @arg flags flags to set (see \ref link_flags "Link Flags")
1193 void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
1195 link->l_flag_mask |= flags;
1196 link->l_flags |= flags;
1197 link->l_mask |= LINK_ATTR_FLAGS;
1202 * @arg link link to change
1203 * @arg flags flags to unset (see \ref link_flags "Link Flags")
1205 void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
1207 link->l_flag_mask |= flags;
1208 link->l_flags &= ~flags;
1209 link->l_mask |= LINK_ATTR_FLAGS;
1214 * @arg link link handle
1215 * @return Link flags
1217 unsigned int rtnl_link_get_flags(struct rtnl_link *link)
1219 return link->l_flags;
1223 * Set link layer address family
1224 * @arg link link to change
1225 * @arg family new address family
1227 void rtnl_link_set_family(struct rtnl_link *link, int family)
1229 link->l_family = family;
1230 link->l_mask |= LINK_ATTR_FAMILY;
1234 * Get link layer address family
1235 * @arg link link handle
1236 * @return Link layer address family or AF_UNSPEC if not set.
1238 int rtnl_link_get_family(struct rtnl_link *link)
1240 if (link->l_family & LINK_ATTR_FAMILY)
1241 return link->l_family;
1247 * Set link layer type
1248 * @arg link link handle
1249 * @arg arptype Link layer type.
1251 void rtnl_link_set_type(struct rtnl_link *link, unsigned int arptype)
1253 link->l_arptype = arptype;
1257 * Get link layer type
1258 * @arg link link handle
1259 * @return Link layer type.
1261 unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
1263 return link->l_arptype;
1267 * Set interface index
1268 * @arg link link to change
1269 * @arg ifindex new interface index
1271 void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
1273 link->l_index = ifindex;
1274 link->l_mask |= LINK_ATTR_IFINDEX;
1278 * Get interface index
1279 * @arg link link handle
1280 * @return interface index or RTNL_LINK_NOT_FOUND if not set.
1282 int rtnl_link_get_ifindex(struct rtnl_link *link)
1284 if (link->l_mask & LINK_ATTR_IFINDEX)
1285 return link->l_index;
1287 return RTNL_LINK_NOT_FOUND;
1291 * Set Maximum Transmission Unit
1292 * @arg link link to change
1295 void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
1298 link->l_mask |= LINK_ATTR_MTU;
1302 * Get Maximum Transmission Unit
1303 * @arg link link handle
1304 * @return Link MTU or 0 if MTU is not set.
1306 unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
1308 if (link->l_mask & LINK_ATTR_MTU)
1315 * Set Transmission Queue Length
1316 * @arg link link to change
1317 * @arg txqlen new TX queue length
1318 * @note The unit of the transmission queue length depends on the
1319 * link type, a common unit is \a packets.
1321 void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
1323 link->l_txqlen = txqlen;
1324 link->l_mask |= LINK_ATTR_TXQLEN;
1328 * Get Transmission Queue Length
1329 * @arg link link handle
1330 * @return Transmission Queue Length or UINT_MAX if not set.
1332 unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
1334 if (link->l_mask & LINK_ATTR_TXQLEN)
1335 return link->l_txqlen;
1342 * @arg link link to change
1343 * @arg weight new weight
1345 void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
1347 link->l_weight = weight;
1348 link->l_mask |= LINK_ATTR_WEIGHT;
1353 * @arg link link handle
1354 * @return Link weight or UINT_MAX if not set.
1356 unsigned int rtnl_link_get_weight(struct rtnl_link *link)
1358 if (link->l_mask & LINK_ATTR_WEIGHT)
1359 return link->l_weight;
1365 * Set parent interface index
1366 * @arg link link to change
1367 * @arg ifindex new parent's interface index
1369 void rtnl_link_set_link(struct rtnl_link *link, int ifindex)
1371 link->l_link = ifindex;
1372 link->l_mask |= LINK_ATTR_LINK;
1376 * Get parent interface index
1377 * @arg link link handle
1378 * @return Parent interface index or RTNL_LINK_NOT_FOUND if not set
1380 int rtnl_link_get_link(struct rtnl_link *link)
1382 if (link->l_mask & LINK_ATTR_LINK)
1383 return link->l_link;
1385 return RTNL_LINK_NOT_FOUND;
1389 * Set master interface index
1390 * @arg link link to change
1391 * @arg ifindex new master's interface index
1393 void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
1395 link->l_master = ifindex;
1396 link->l_mask |= LINK_ATTR_MASTER;
1400 * Get master interface index
1401 * @arg link link handle
1402 * @return Interface index of master or RTNL_LINK_NOT_FOUND if not set
1404 int rtnl_link_get_master(struct rtnl_link *link)
1406 if (link->l_mask & LINK_ATTR_MASTER)
1407 return link->l_master;
1409 return RTNL_LINK_NOT_FOUND;
1413 * Get the statistic specified by the id
1414 * @arg link link handle
1415 * @arg id statistic id
1416 * @return The current counter of the specified statistic
1418 uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
1420 if (id < 0 || id > RTNL_LINK_STATS_MAX)
1423 return link->l_stats[id];
1428 static struct nl_cache_ops rtnl_link_ops = {
1429 .co_name = "route/link",
1430 .co_size = sizeof(struct rtnl_link),
1431 .co_hdrsize = sizeof(struct ifinfomsg),
1433 { RTM_NEWLINK, "new" },
1434 { RTM_DELLINK, "delete" },
1435 { RTM_GETLINK, "get" },
1438 .co_protocol = NETLINK_ROUTE,
1439 .co_request_update = link_request_update,
1440 .co_msg_parser = link_msg_parser,
1441 .co_free_data = link_free_data,
1442 .co_dump[NL_DUMP_BRIEF] = link_dump_brief,
1443 .co_dump[NL_DUMP_FULL] = link_dump_full,
1444 .co_dump[NL_DUMP_STATS] = link_dump_stats,
1445 .co_dump[NL_DUMP_XML] = link_dump_xml,
1446 .co_dump[NL_DUMP_ENV] = link_dump_env,
1447 .co_filter = link_filter,
1450 static void __init link_init(void)
1452 nl_cache_mngt_register(&rtnl_link_ops);
1455 static void __exit link_exit(void)
1457 nl_cache_mngt_unregister(&rtnl_link_ops);