link.c revision 44d362409d5469aed47d19e7908d19bd194493a
144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/link.c	Links (Interfaces)
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup link Links (Interfaces)
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Link Identification
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * A link can be identified by either its interface index or by its
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf * name. The kernel favours the interface index but falls back to the
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * interface name if the interface index is lesser-than 0 for kernels
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * >= 2.6.11. Therefore you can request changes without mapping a
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * interface name to the corresponding index first.
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Changeable Attributes
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @anchor link_changeable
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Link layer address
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Link layer broadcast address
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - device mapping (ifmap) (>= 2.6.9)
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - MTU (>= 2.6.9)
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Transmission queue length (>= 2.6.9)
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Weight (>= 2.6.9)
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Link name (only via access through interface index) (>= 2.6.9)
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf *  - Flags (>= 2.6.9)
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_DEBUG
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_NOTRAILERS
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_NOARP
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_DYNAMIC
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_MULTICAST
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_PORTSEL
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_AUTOMEDIA
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_UP
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_PROMISC
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf *    - IFF_ALLMULTI
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Link Flags (linux/if.h)
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @anchor link_flags
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_UP            Status of link (up|down)
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_BROADCAST     Indicates this link allows broadcasting
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_MULTICAST     Indicates this link allows multicasting
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_ALLMULTI      Indicates this link is doing multicast routing
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_DEBUG         Tell the driver to do debugging (currently unused)
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_LOOPBACK      This is the loopback link
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_POINTOPOINT   Point-to-point link
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_NOARP         Link is unable to perform ARP
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_PROMISC       Status of promiscious mode flag
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_MASTER        Used by teql
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_SLAVE         Used by teql
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_PORTSEL       Indicates this link allows port selection
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_AUTOMEDIA     Indicates this link selects port automatically
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_DYNAMIC       Indicates the address of this link is dynamic
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_RUNNING       Link is running and carrier is ok.
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf *   IFF_NOTRAILERS    Unused, BSD compat.
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Notes on IFF_PROMISC and IFF_ALLMULTI flags
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Although you can query the status of IFF_PROMISC and IFF_ALLMULTI
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf * they do not represent the actual state in the kernel but rather
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * whether the flag has been enabled/disabled by userspace. The link
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * may be in promiscious mode even if IFF_PROMISC is not set in a link
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf * dump request response because promiscity might be needed by the driver
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf * for a period of time.
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note The unit of the transmission queue length depends on the
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf *       link type, a common unit is \a packets.
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Retrieving information about available links
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // The first step is to retrieve a list of all available interfaces within
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * // the kernel and put them into a cache.
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_cache *cache = rtnl_link_alloc_cache(nl_handle);
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // In a second step, a specific link may be looked up by either interface
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // index or interface name.
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_link *link = rtnl_link_get_by_name(cache, "lo");
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // rtnl_link_get_by_name() is the short version for translating the
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // interface name to an interface index first like this:
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf * int ifindex = rtnl_link_name2i(cache, "lo");
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_link *link = rtnl_link_get(cache, ifindex);
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // After successful usage, the object must be given back to the cache
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_put(link);
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 2) Changing link attributes
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // In order to change any attributes of an existing link, we must allocate
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // a new link to hold the change requests:
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_link *request = rtnl_link_alloc();
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Now we can go on and specify the attributes we want to change:
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_set_weight(request, 300);
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_set_mtu(request, 1360);
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf * // We can also shut an interface down administratively
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Actually, we should know which link to change, so let's look it up
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct rtnl_link *old = rtnl_link_get(cache, "eth0");
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Two ways exist to commit this change request, the first one is to
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // build the required netlink message and send it out in one single
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf * // step:
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_change(nl_handle, old, request);
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // An alternative way is to build the netlink message and send it
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // out yourself using nl_send_auto_complete()
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_msg *msg = rtnl_link_build_change_request(old, request);
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf * nl_send_auto_complete(nl_handle, nlmsg_hdr(msg));
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf * nlmsg_free(msg);
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Don't forget to give back the link object ;->
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * rtnl_link_put(old);
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf
12944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h>
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
13344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/object.h>
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h>
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h>
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_MTU     0x0001
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_LINK    0x0002
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_TXQLEN  0x0004
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_WEIGHT  0x0008
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_MASTER  0x0010
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_QDISC   0x0020
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_MAP     0x0040
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_ADDR    0x0080
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_BRD     0x0100
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_FLAGS   0x0200
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_IFNAME  0x0400
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_IFINDEX 0x0800
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_FAMILY  0x1000
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_ARPTYPE 0x2000
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_STATS   0x4000
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_ATTR_CHANGE  0x8000
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf
15544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_link_ops;
15644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops link_obj_ops;
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf
15944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void link_free_data(struct nl_object *c)
16044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = nl_object_priv(c);
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link) {
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_put(link->l_addr);
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_put(link->l_bcast);
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf
16944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_clone(struct nl_object *_dst, struct nl_object *_src)
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *dst = nl_object_priv(_dst);
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *src = nl_object_priv(_src);
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->l_addr)
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!(dst->l_addr = nl_addr_clone(src->l_addr)))
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf			goto errout;
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->l_bcast)
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!(dst->l_bcast = nl_addr_clone(src->l_bcast)))
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf			goto errout;
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
18344d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_get_errno();
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf
18744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy link_policy[IFLA_MAX+1] = {
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_IFNAME]	= { .type = NLA_STRING,
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf			    .maxlen = IFNAMSIZ },
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_MTU]	= { .type = NLA_U32 },
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_TXQLEN]	= { .type = NLA_U32 },
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_LINK]	= { .type = NLA_U32 },
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_WEIGHT]	= { .type = NLA_U32 },
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_MASTER]	= { .type = NLA_U32 },
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_QDISC]	= { .type = NLA_STRING,
19644d362409d5469aed47d19e7908d19bd194493aThomas Graf			    .maxlen = IFQDISCSIZ },
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_STATS]	= { .minlen = sizeof(struct rtnl_link_stats) },
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf	[IFLA_MAP]	= { .minlen = sizeof(struct rtnl_link_ifmap) },
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf};
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf
20144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf			   struct nlmsghdr *n, void *arg)
20344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link;
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct ifinfomsg *ifi;
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlattr *tb[IFLA_MAX+1];
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_parser_param *pp = arg;
20844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf	link = rtnl_link_alloc();
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link == NULL) {
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf		err = nl_errno(ENOMEM);
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
21444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_msgtype = n->nlmsg_type;
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy);
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_IFNAME] == NULL) {
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf		err = nl_error(EINVAL, "Missing link name TLV");
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf	nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
22844d362409d5469aed47d19e7908d19bd194493aThomas Graf
22944d362409d5469aed47d19e7908d19bd194493aThomas Graf	ifi = nlmsg_data(n);
23044d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_family = ifi->ifi_family;
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_arptype = ifi->ifi_type;
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_index = ifi->ifi_index;
23344d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_flags = ifi->ifi_flags;
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_change = ifi->ifi_change;
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY |
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf			  LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf			  LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_STATS]) {
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]);
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_PACKETS]	= st->rx_packets;
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_BYTES]	= st->rx_bytes;
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_ERRORS]	= st->rx_errors;
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_DROPPED]	= st->rx_dropped;
24644d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_COMPRESSED]	= st->rx_compressed;
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_FIFO_ERR]	= st->rx_fifo_errors;
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_PACKETS]	= st->tx_packets;
24944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_BYTES]	= st->tx_bytes;
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_ERRORS]	= st->tx_errors;
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_DROPPED]	= st->tx_dropped;
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_COMPRESSED]	= st->tx_compressed;
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_FIFO_ERR]	= st->tx_fifo_errors;
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_LEN_ERR]	= st->rx_length_errors;
25544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_OVER_ERR]	= st->rx_over_errors;
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_CRC_ERR]	= st->rx_crc_errors;
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_FRAME_ERR]	= st->rx_frame_errors;
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_MISSED_ERR]	= st->rx_missed_errors;
25944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_ABORT_ERR]	= st->tx_aborted_errors;
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_CARRIER_ERR]	= st->tx_carrier_errors;
26144d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_HBEAT_ERR]	= st->tx_heartbeat_errors;
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_WIN_ERR]	= st->tx_window_errors;
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_MULTICAST]	= st->multicast;
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf
26544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_STATS;
26644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf
26844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_TXQLEN]) {
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]);
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_TXQLEN;
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf
27344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_MTU]) {
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_mtu = nla_get_u32(tb[IFLA_MTU]);
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_MTU;
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_ADDRESS]) {
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_addr = nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (link->l_addr == NULL)
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf			goto errout;
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_set_family(link->l_addr,
28344d362409d5469aed47d19e7908d19bd194493aThomas Graf				   nl_addr_guess_family(link->l_addr));
28444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_ADDR;
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_BROADCAST]) {
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_bcast = nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (link->l_bcast == NULL)
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf			goto errout;
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_set_family(link->l_bcast,
29244d362409d5469aed47d19e7908d19bd194493aThomas Graf				   nl_addr_guess_family(link->l_bcast));
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_BRD;
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_LINK]) {
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_link = nla_get_u32(tb[IFLA_LINK]);
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_LINK;
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_WEIGHT]) {
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]);
30344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_WEIGHT;
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_QDISC]) {
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf		nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
30844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_QDISC;
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_MAP]) {
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link_ifmap *map =  nla_data(tb[IFLA_MAP]);
31344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_mem_start = map->mem_start;
31444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_mem_end   = map->mem_end;
31544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_base_addr = map->base_addr;
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_irq       = map->irq;
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_dma       = map->dma;
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_map.lm_port      = map->port;
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_MAP;
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
32144d362409d5469aed47d19e7908d19bd194493aThomas Graf
32244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tb[IFLA_MASTER]) {
32344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_master = nla_get_u32(tb[IFLA_MASTER]);
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->ce_mask |= LINK_ATTR_MASTER;
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf
32744d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = pp->pp_cb((struct nl_object *) link, pp);
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
33044d362409d5469aed47d19e7908d19bd194493aThomas Graf
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return P_ACCEPT;
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf
33344d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf	rtnl_link_put(link);
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return err;
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf
33844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_request_update(struct nl_cache *c, struct nl_handle *h)
33944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_rtgen_request(h, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf
34344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
34444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[128];
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache *cache = dp_cache(obj);
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = (struct rtnl_link *) obj;
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf	int line = 1;
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "%s ", link->l_name);
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf
35244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_LINK) {
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "@%s", ll ? ll->l_name : "NONE");
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (ll)
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(ll);
35744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
35844d362409d5469aed47d19e7908d19bd194493aThomas Graf
35944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "%s ", nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "%s ", link->l_addr ?  nl_addr2str(link->l_addr, buf,
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf						     sizeof(buf)) : "none");
36244d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "mtu %u ", link->l_mtu);
36344d362409d5469aed47d19e7908d19bd194493aThomas Graf
36444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MASTER) {
36544d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
36644d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "master %s ", master ? master->l_name : "inv");
36744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (master)
36844d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(master);
36944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
37044d362409d5469aed47d19e7908d19bd194493aThomas Graf
37144d362409d5469aed47d19e7908d19bd194493aThomas Graf	rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (buf[0])
37344d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "<%s>", buf);
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf
37544d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "\n");
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf
37744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return line;
37844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
37944d362409d5469aed47d19e7908d19bd194493aThomas Graf
38044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
38144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
38244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = (struct rtnl_link *) obj;
38344d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[64];
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int line;
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf
38644d362409d5469aed47d19e7908d19bd194493aThomas Graf	line = link_dump_brief(obj, p);
38744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_new_line(p, line++);
38844d362409d5469aed47d19e7908d19bd194493aThomas Graf
38944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "    txqlen %u weight %u ", link->l_txqlen, link->l_weight);
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf
39144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_QDISC)
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "qdisc %s ", link->l_qdisc);
39344d362409d5469aed47d19e7908d19bd194493aThomas Graf
39444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
39544d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "irq %u ", link->l_map.lm_irq);
39644d362409d5469aed47d19e7908d19bd194493aThomas Graf
39744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_IFINDEX)
39844d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "index %u ", link->l_index);
39944d362409d5469aed47d19e7908d19bd194493aThomas Graf
40044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_BRD)
40144d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "brd %s", nl_addr2str(link->l_bcast, buf,
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf						   sizeof(buf)));
40344d362409d5469aed47d19e7908d19bd194493aThomas Graf
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump(p, "\n");
40544d362409d5469aed47d19e7908d19bd194493aThomas Graf
40644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return line;
40744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
40844d362409d5469aed47d19e7908d19bd194493aThomas Graf
40944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
41044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
41144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = (struct rtnl_link *) obj;
41244d362409d5469aed47d19e7908d19bd194493aThomas Graf	char *unit, fmt[64];
41344d362409d5469aed47d19e7908d19bd194493aThomas Graf	float res;
41444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int line;
41544d362409d5469aed47d19e7908d19bd194493aThomas Graf
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf	line = link_dump_full(obj, p);
41744d362409d5469aed47d19e7908d19bd194493aThomas Graf
41844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "    Stats:    bytes    packets     errors "
41944d362409d5469aed47d19e7908d19bd194493aThomas Graf				"   dropped   fifo-err compressed\n");
42044d362409d5469aed47d19e7908d19bd194493aThomas Graf
42144d362409d5469aed47d19e7908d19bd194493aThomas Graf	res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit);
42244d362409d5469aed47d19e7908d19bd194493aThomas Graf
42344d362409d5469aed47d19e7908d19bd194493aThomas Graf	strcpy(fmt, "    RX  %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
42444d362409d5469aed47d19e7908d19bd194493aThomas Graf	fmt[9] = *unit == 'B' ? '9' : '7';
42544d362409d5469aed47d19e7908d19bd194493aThomas Graf
42644d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, fmt,
42744d362409d5469aed47d19e7908d19bd194493aThomas Graf		res, unit,
42844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_PACKETS],
42944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_ERRORS],
43044d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_DROPPED],
43144d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_FIFO_ERR],
43244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_COMPRESSED]);
43344d362409d5469aed47d19e7908d19bd194493aThomas Graf
43444d362409d5469aed47d19e7908d19bd194493aThomas Graf	res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit);
43544d362409d5469aed47d19e7908d19bd194493aThomas Graf
43644d362409d5469aed47d19e7908d19bd194493aThomas Graf	strcpy(fmt, "    TX  %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
43744d362409d5469aed47d19e7908d19bd194493aThomas Graf	fmt[9] = *unit == 'B' ? '9' : '7';
43844d362409d5469aed47d19e7908d19bd194493aThomas Graf
43944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, fmt,
44044d362409d5469aed47d19e7908d19bd194493aThomas Graf		res, unit,
44144d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_PACKETS],
44244d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_ERRORS],
44344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_DROPPED],
44444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_FIFO_ERR],
44544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_COMPRESSED]);
44644d362409d5469aed47d19e7908d19bd194493aThomas Graf
44744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "    Errors:  length       over        crc "
44844d362409d5469aed47d19e7908d19bd194493aThomas Graf				"     frame     missed  multicast\n");
44944d362409d5469aed47d19e7908d19bd194493aThomas Graf
45044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "    RX   %10" PRIu64 " %10" PRIu64 " %10"
45144d362409d5469aed47d19e7908d19bd194493aThomas Graf				PRIu64 " %10" PRIu64 " %10" PRIu64 " %10"
45244d362409d5469aed47d19e7908d19bd194493aThomas Graf				PRIu64 "\n",
45344d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_LEN_ERR],
45444d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_OVER_ERR],
45544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_CRC_ERR],
45644d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_FRAME_ERR],
45744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_RX_MISSED_ERR],
45844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_MULTICAST]);
45944d362409d5469aed47d19e7908d19bd194493aThomas Graf
46044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "    Errors: aborted    carrier  heartbeat "
46144d362409d5469aed47d19e7908d19bd194493aThomas Graf				"    window  collision\n");
46244d362409d5469aed47d19e7908d19bd194493aThomas Graf
46344d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "    TX   %10" PRIu64 " %10" PRIu64 " %10"
46444d362409d5469aed47d19e7908d19bd194493aThomas Graf				PRIu64 " %10" PRIu64 " %10" PRIu64 "\n",
46544d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_ABORT_ERR],
46644d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
46744d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
46844d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_WIN_ERR],
46944d362409d5469aed47d19e7908d19bd194493aThomas Graf		link->l_stats[RTNL_LINK_TX_COLLISIONS]);
47044d362409d5469aed47d19e7908d19bd194493aThomas Graf
47144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return line;
47244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
47344d362409d5469aed47d19e7908d19bd194493aThomas Graf
47444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
47544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
47644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = (struct rtnl_link *) obj;
47744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache *cache = dp_cache(obj);
47844d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[128];
47944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, line = 0;
48044d362409d5469aed47d19e7908d19bd194493aThomas Graf
48144d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "<link name=\"%s\" index=\"%u\">\n",
48244d362409d5469aed47d19e7908d19bd194493aThomas Graf		     link->l_name, link->l_index);
48344d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <family>%s</family>\n",
48444d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_af2str(link->l_family, buf, sizeof(buf)));
48544d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <arptype>%s</arptype>\n",
48644d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
48744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <address>%s</address>\n",
48844d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_addr2str(link->l_addr, buf, sizeof(buf)));
48944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <mtu>%u</mtu>\n", link->l_mtu);
49044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <txqlen>%u</txqlen>\n", link->l_txqlen);
49144d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "  <weight>%u</weight>\n", link->l_weight);
49244d362409d5469aed47d19e7908d19bd194493aThomas Graf
49344d362409d5469aed47d19e7908d19bd194493aThomas Graf	rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
49444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (buf[0])
49544d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <flags>%s</flags>\n", buf);
49644d362409d5469aed47d19e7908d19bd194493aThomas Graf
49744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_QDISC)
49844d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <qdisc>%s</qdisc>\n", link->l_qdisc);
49944d362409d5469aed47d19e7908d19bd194493aThomas Graf
50044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_LINK) {
50144d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
50244d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <link>%s</link>\n",
50344d362409d5469aed47d19e7908d19bd194493aThomas Graf			     ll ? ll->l_name : "none");
50444d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (ll)
50544d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(ll);
50644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
50744d362409d5469aed47d19e7908d19bd194493aThomas Graf
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MASTER) {
50944d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <master>%s</master>\n",
51144d362409d5469aed47d19e7908d19bd194493aThomas Graf			     master ? master->l_name : "none");
51244d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (master)
51344d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(master);
51444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf
51644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_BRD)
51744d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <broadcast>%s</broadcast>\n",
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf			     nl_addr2str(link->l_bcast, buf, sizeof(buf)));
51944d362409d5469aed47d19e7908d19bd194493aThomas Graf
52044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_STATS) {
52144d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  <stats>\n");
52244d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
52344d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_stat2str(i, buf, sizeof(buf));
52444d362409d5469aed47d19e7908d19bd194493aThomas Graf			dp_dump_line(p, line++,
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf				     "    <%s>%" PRIu64 "</%s>\n",
52644d362409d5469aed47d19e7908d19bd194493aThomas Graf				     buf, link->l_stats[i], buf);
52744d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "  </stats>\n");
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "</link>\n");
53244d362409d5469aed47d19e7908d19bd194493aThomas Graf
53344d362409d5469aed47d19e7908d19bd194493aThomas Graf#if 0
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf	uint32_t	l_change;	/**< Change mask */
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_lifmap l_map;	/**< Interface device mapping */
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
53744d362409d5469aed47d19e7908d19bd194493aThomas Graf
53844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return line;
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf
54144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_dump_env(struct nl_object *obj, struct nl_dump_params *p)
54244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
54344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = (struct rtnl_link *) obj;
54444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache *cache = dp_cache(obj);
54544d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[128];
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, line = 0;
54744d362409d5469aed47d19e7908d19bd194493aThomas Graf
54844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_NAME=%s\n", link->l_name);
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_IFINDEX=%u\n", link->l_index);
55044d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_FAMILY=%s\n",
55144d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_af2str(link->l_family, buf, sizeof(buf)));
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_TYPE=%s\n",
55344d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
55444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_ADDR)
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_ADDRESS=%s\n",
55644d362409d5469aed47d19e7908d19bd194493aThomas Graf			     nl_addr2str(link->l_addr, buf, sizeof(buf)));
55744d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_MTU=%u\n", link->l_mtu);
55844d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_TXQUEUELEN=%u\n", link->l_txqlen);
55944d362409d5469aed47d19e7908d19bd194493aThomas Graf	dp_dump_line(p, line++, "LINK_WEIGHT=%u\n", link->l_weight);
56044d362409d5469aed47d19e7908d19bd194493aThomas Graf
56144d362409d5469aed47d19e7908d19bd194493aThomas Graf	rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf, sizeof(buf));
56244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (buf[0])
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_FLAGS=%s\n", buf);
56444d362409d5469aed47d19e7908d19bd194493aThomas Graf
56544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_QDISC)
56644d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_QDISC=%s\n", link->l_qdisc);
56744d362409d5469aed47d19e7908d19bd194493aThomas Graf
56844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_LINK) {
56944d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
57044d362409d5469aed47d19e7908d19bd194493aThomas Graf
57144d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_LINK_IFINDEX=%d\n", link->l_link);
57244d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (ll) {
57344d362409d5469aed47d19e7908d19bd194493aThomas Graf			dp_dump_line(p, line++, "LINK_LINK_IFNAME=%s\n",
57444d362409d5469aed47d19e7908d19bd194493aThomas Graf				     ll->l_name);
57544d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(ll);
57644d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
57744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
57844d362409d5469aed47d19e7908d19bd194493aThomas Graf
57944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MASTER) {
58044d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
58144d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_MASTER=%s\n",
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf			     master ? master->l_name : "none");
58344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (master)
58444d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_put(master);
58544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
58644d362409d5469aed47d19e7908d19bd194493aThomas Graf
58744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_BRD)
58844d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "LINK_BROADCAST=%s\n",
58944d362409d5469aed47d19e7908d19bd194493aThomas Graf			     nl_addr2str(link->l_bcast, buf, sizeof(buf)));
59044d362409d5469aed47d19e7908d19bd194493aThomas Graf
59144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_STATS) {
59244d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
59344d362409d5469aed47d19e7908d19bd194493aThomas Graf			char *c = buf;
59444d362409d5469aed47d19e7908d19bd194493aThomas Graf
59544d362409d5469aed47d19e7908d19bd194493aThomas Graf			sprintf(buf, "LINK_");
59644d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_link_stat2str(i, buf + 5, sizeof(buf) - 5);
59744d362409d5469aed47d19e7908d19bd194493aThomas Graf			while (*c) {
59844d362409d5469aed47d19e7908d19bd194493aThomas Graf				*c = toupper(*c);
59944d362409d5469aed47d19e7908d19bd194493aThomas Graf				c++;
60044d362409d5469aed47d19e7908d19bd194493aThomas Graf			}
60144d362409d5469aed47d19e7908d19bd194493aThomas Graf			dp_dump_line(p, line++,
60244d362409d5469aed47d19e7908d19bd194493aThomas Graf				     "%s=%" PRIu64 "\n", buf, link->l_stats[i]);
60344d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
60444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
60544d362409d5469aed47d19e7908d19bd194493aThomas Graf
60644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return line;
60744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
60844d362409d5469aed47d19e7908d19bd194493aThomas Graf
60944d362409d5469aed47d19e7908d19bd194493aThomas Graf#if 0
61044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb)
61144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
61244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *l = (struct rtnl_link *) a;
61344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache *c = dp_cache(a);
61444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int nevents = 0;
61544d362409d5469aed47d19e7908d19bd194493aThomas Graf
61644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l->l_change == ~0U) {
61744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (l->ce_msgtype == RTM_NEWLINK)
61844d362409d5469aed47d19e7908d19bd194493aThomas Graf			cb->le_register(l);
61944d362409d5469aed47d19e7908d19bd194493aThomas Graf		else
62044d362409d5469aed47d19e7908d19bd194493aThomas Graf			cb->le_unregister(l);
62144d362409d5469aed47d19e7908d19bd194493aThomas Graf
62244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 1;
62344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
62444d362409d5469aed47d19e7908d19bd194493aThomas Graf
62544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l->l_change & IFF_SLAVE) {
62644d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (l->l_flags & IFF_SLAVE) {
62744d362409d5469aed47d19e7908d19bd194493aThomas Graf			struct rtnl_link *m = rtnl_link_get(c, l->l_master);
62844d362409d5469aed47d19e7908d19bd194493aThomas Graf			cb->le_new_bonding(l, m);
62944d362409d5469aed47d19e7908d19bd194493aThomas Graf			if (m)
63044d362409d5469aed47d19e7908d19bd194493aThomas Graf				rtnl_link_put(m);
63144d362409d5469aed47d19e7908d19bd194493aThomas Graf		} else
63244d362409d5469aed47d19e7908d19bd194493aThomas Graf			cb->le_cancel_bonding(l);
63344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
63444d362409d5469aed47d19e7908d19bd194493aThomas Graf
63544d362409d5469aed47d19e7908d19bd194493aThomas Graf#if 0
63644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
63744d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "link %s changed state to %s.\n",
63844d362409d5469aed47d19e7908d19bd194493aThomas Graf			l->l_name, l->l_flags & IFF_UP ? "up" : "down");
63944d362409d5469aed47d19e7908d19bd194493aThomas Graf
64044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (l->l_change & IFF_PROMISC) {
64144d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_new_line(p, line++);
64244d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump(p, "link %s %s promiscuous mode.\n",
64344d362409d5469aed47d19e7908d19bd194493aThomas Graf		    l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left");
64444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
64544d362409d5469aed47d19e7908d19bd194493aThomas Graf
64644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (line == 0)
64744d362409d5469aed47d19e7908d19bd194493aThomas Graf		dp_dump_line(p, line++, "link %s sent unknown event.\n",
64844d362409d5469aed47d19e7908d19bd194493aThomas Graf			     l->l_name);
64944d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
65044d362409d5469aed47d19e7908d19bd194493aThomas Graf
65144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nevents;
65244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65344d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif
65444d362409d5469aed47d19e7908d19bd194493aThomas Graf
65544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int link_compare(struct nl_object *_a, struct nl_object *_b,
65644d362409d5469aed47d19e7908d19bd194493aThomas Graf			uint32_t attrs, int flags)
65744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
65844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *a = (struct rtnl_link *) _a;
65944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *b = (struct rtnl_link *) _b;
66044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int diff = 0;
66144d362409d5469aed47d19e7908d19bd194493aThomas Graf
66244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
66344d362409d5469aed47d19e7908d19bd194493aThomas Graf
66444d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(IFINDEX,	a->l_index != b->l_index);
66544d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(MTU,		a->l_mtu != b->l_mtu);
66644d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(LINK,		a->l_link != b->l_link);
66744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(TXQLEN,	a->l_txqlen != b->l_txqlen);
66844d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(WEIGHT,	a->l_weight != b->l_weight);
66944d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(MASTER,	a->l_master != b->l_master);
67044d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(FAMILY,	a->l_family != b->l_family);
67144d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(QDISC,	strcmp(a->l_qdisc, b->l_qdisc));
67244d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(IFNAME,	strcmp(a->l_name, b->l_name));
67344d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(ADDR,		nl_addr_cmp(a->l_addr, b->l_addr));
67444d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= LINK_DIFF(BRD,		nl_addr_cmp(a->l_bcast, b->l_bcast));
67544d362409d5469aed47d19e7908d19bd194493aThomas Graf
67644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (flags & LOOSE_FLAG_COMPARISON)
67744d362409d5469aed47d19e7908d19bd194493aThomas Graf		diff |= LINK_DIFF(FLAGS,
67844d362409d5469aed47d19e7908d19bd194493aThomas Graf				  (a->l_flags ^ b->l_flags) & b->l_flag_mask);
67944d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
68044d362409d5469aed47d19e7908d19bd194493aThomas Graf		diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
68144d362409d5469aed47d19e7908d19bd194493aThomas Graf
68244d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef LINK_DIFF
68344d362409d5469aed47d19e7908d19bd194493aThomas Graf
68444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return diff;
68544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
68644d362409d5469aed47d19e7908d19bd194493aThomas Graf
68744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl link_attrs[] = {
68844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_MTU, mtu)
68944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_LINK, link)
69044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_TXQLEN, txqlen)
69144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_WEIGHT, weight)
69244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_MASTER, master)
69344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_QDISC, qdisc)
69444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_MAP, map)
69544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_ADDR, address)
69644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_BRD, broadcast)
69744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_FLAGS, flags)
69844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_IFNAME, name)
69944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_IFINDEX, ifindex)
70044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_FAMILY, family)
70144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_ARPTYPE, arptype)
70244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_STATS, stats)
70344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(LINK_ATTR_CHANGE, change)
70444d362409d5469aed47d19e7908d19bd194493aThomas Graf};
70544d362409d5469aed47d19e7908d19bd194493aThomas Graf
70644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *link_attrs2str(int attrs, char *buf, size_t len)
70744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
70844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __flags2str(attrs, buf, len, link_attrs,
70944d362409d5469aed47d19e7908d19bd194493aThomas Graf			   ARRAY_SIZE(link_attrs));
71044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
71144d362409d5469aed47d19e7908d19bd194493aThomas Graf
71244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
71344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing
71444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
71544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
71644d362409d5469aed47d19e7908d19bd194493aThomas Graf
71744d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_link *rtnl_link_alloc(void)
71844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
71944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (struct rtnl_link *) nl_object_alloc(&link_obj_ops);
72044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
72144d362409d5469aed47d19e7908d19bd194493aThomas Graf
72244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_put(struct rtnl_link *link)
72344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
72444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_put((struct nl_object *) link);
72544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
72644d362409d5469aed47d19e7908d19bd194493aThomas Graf
72744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
72844d362409d5469aed47d19e7908d19bd194493aThomas Graf
72944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
73044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management
73144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
73244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
73344d362409d5469aed47d19e7908d19bd194493aThomas Graf
73444d362409d5469aed47d19e7908d19bd194493aThomas Graf
73544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
73644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate link cache and fill in all configured links.
73744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg handle		Netlink handle.
73844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
73944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new link cache, initializes it properly and updates it
74044d362409d5469aed47d19e7908d19bd194493aThomas Graf * to include all links currently configured in the kernel.
74144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
74244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Free the memory after usage.
74344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated cache or NULL if an error occured.
74444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
74544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cache *rtnl_link_alloc_cache(struct nl_handle *handle)
74644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
74744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache * cache;
74844d362409d5469aed47d19e7908d19bd194493aThomas Graf
74944d362409d5469aed47d19e7908d19bd194493aThomas Graf	cache = nl_cache_alloc(&rtnl_link_ops);
75044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cache == NULL)
75144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
75244d362409d5469aed47d19e7908d19bd194493aThomas Graf
75344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (handle && nl_cache_refill(handle, cache) < 0) {
75444d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_cache_free(cache);
75544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
75644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
75744d362409d5469aed47d19e7908d19bd194493aThomas Graf
75844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return cache;
75944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
76044d362409d5469aed47d19e7908d19bd194493aThomas Graf
76144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
76244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Look up link by interface index in the provided cache
76344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache		link cache
76444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ifindex		link interface index
76544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
76644d362409d5469aed47d19e7908d19bd194493aThomas Graf * The caller owns a reference on the returned object and
76744d362409d5469aed47d19e7908d19bd194493aThomas Graf * must give the object back via rtnl_link_put().
76844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
76944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return pointer to link inside the cache or NULL if no match was found.
77044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
77144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex)
77244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
77344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link;
77444d362409d5469aed47d19e7908d19bd194493aThomas Graf
77544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cache->c_ops != &rtnl_link_ops)
77644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
77744d362409d5469aed47d19e7908d19bd194493aThomas Graf
77844d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_for_each_entry(link, &cache->c_items, ce_list) {
77944d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (link->l_index == ifindex) {
78044d362409d5469aed47d19e7908d19bd194493aThomas Graf			nl_object_get((struct nl_object *) link);
78144d362409d5469aed47d19e7908d19bd194493aThomas Graf			return link;
78244d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
78344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
78444d362409d5469aed47d19e7908d19bd194493aThomas Graf
78544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
78644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
78744d362409d5469aed47d19e7908d19bd194493aThomas Graf
78844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
78944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Look up link by link name in the provided cache
79044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache		link cache
79144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name		link name
79244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
79344d362409d5469aed47d19e7908d19bd194493aThomas Graf * The caller owns a reference on the returned object and
79444d362409d5469aed47d19e7908d19bd194493aThomas Graf * must give the object back via rtnl_link_put().
79544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
79644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return pointer to link inside the cache or NULL if no match was found.
79744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
79844d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache,
79944d362409d5469aed47d19e7908d19bd194493aThomas Graf					 const char *name)
80044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
80144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link;
80244d362409d5469aed47d19e7908d19bd194493aThomas Graf
80344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (cache->c_ops != &rtnl_link_ops)
80444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
80544d362409d5469aed47d19e7908d19bd194493aThomas Graf
80644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_list_for_each_entry(link, &cache->c_items, ce_list) {
80744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!strcmp(name, link->l_name)) {
80844d362409d5469aed47d19e7908d19bd194493aThomas Graf			nl_object_get((struct nl_object *) link);
80944d362409d5469aed47d19e7908d19bd194493aThomas Graf			return link;
81044d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
81144d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
81244d362409d5469aed47d19e7908d19bd194493aThomas Graf
81344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
81444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
81544d362409d5469aed47d19e7908d19bd194493aThomas Graf
81644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
81744d362409d5469aed47d19e7908d19bd194493aThomas Graf
81844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
81944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Link Modifications
82044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
82144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
82244d362409d5469aed47d19e7908d19bd194493aThomas Graf
82344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
82444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink change request message to change link attributes
82544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg old		link to be changed
82644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl		template with requested changes
82744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
82844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
82944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a change of link attributes.
83044d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant
83144d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must be sent out via nl_send_auto_complete() or
83244d362409d5469aed47d19e7908d19bd194493aThomas Graf * supplemented as needed.
83344d362409d5469aed47d19e7908d19bd194493aThomas Graf * \a old must point to a link currently configured in the kernel
83444d362409d5469aed47d19e7908d19bd194493aThomas Graf * and \a tmpl must contain the attributes to be changed set via
83544d362409d5469aed47d19e7908d19bd194493aThomas Graf * \c rtnl_link_set_* functions.
83644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
83744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return New netlink message
83844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Not all attributes can be changed, see
83944d362409d5469aed47d19e7908d19bd194493aThomas Graf *       \ref link_changeable "Changeable Attributes" for more details.
84044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
84144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old,
84244d362409d5469aed47d19e7908d19bd194493aThomas Graf					       struct rtnl_link *tmpl,
84344d362409d5469aed47d19e7908d19bd194493aThomas Graf					       int flags)
84444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
84544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
84644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct ifinfomsg ifi = {
84744d362409d5469aed47d19e7908d19bd194493aThomas Graf		.ifi_family = old->l_family,
84844d362409d5469aed47d19e7908d19bd194493aThomas Graf		.ifi_index = old->l_index,
84944d362409d5469aed47d19e7908d19bd194493aThomas Graf	};
85044d362409d5469aed47d19e7908d19bd194493aThomas Graf
85144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_FLAGS) {
85244d362409d5469aed47d19e7908d19bd194493aThomas Graf		ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
85344d362409d5469aed47d19e7908d19bd194493aThomas Graf		ifi.ifi_flags |= tmpl->l_flags;
85444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
85544d362409d5469aed47d19e7908d19bd194493aThomas Graf
85644d362409d5469aed47d19e7908d19bd194493aThomas Graf	msg = nlmsg_alloc_simple(RTM_SETLINK, flags);
85744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!msg)
85844d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto nla_put_failure;
85944d362409d5469aed47d19e7908d19bd194493aThomas Graf
86044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
86144d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto nla_put_failure;
86244d362409d5469aed47d19e7908d19bd194493aThomas Graf
86344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_ADDR)
86444d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_ADDR(msg, IFLA_ADDRESS, tmpl->l_addr);
86544d362409d5469aed47d19e7908d19bd194493aThomas Graf
86644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_BRD)
86744d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_ADDR(msg, IFLA_BROADCAST, tmpl->l_bcast);
86844d362409d5469aed47d19e7908d19bd194493aThomas Graf
86944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_MTU)
87044d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_U32(msg, IFLA_MTU, tmpl->l_mtu);
87144d362409d5469aed47d19e7908d19bd194493aThomas Graf
87244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_TXQLEN)
87344d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_U32(msg, IFLA_TXQLEN, tmpl->l_txqlen);
87444d362409d5469aed47d19e7908d19bd194493aThomas Graf
87544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_WEIGHT)
87644d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_U32(msg, IFLA_WEIGHT, tmpl->l_weight);
87744d362409d5469aed47d19e7908d19bd194493aThomas Graf
87844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & LINK_ATTR_IFNAME)
87944d362409d5469aed47d19e7908d19bd194493aThomas Graf		NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name);
88044d362409d5469aed47d19e7908d19bd194493aThomas Graf
88144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return msg;
88244d362409d5469aed47d19e7908d19bd194493aThomas Graf
88344d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure:
88444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
88544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
88644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
88744d362409d5469aed47d19e7908d19bd194493aThomas Graf
88844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
88944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Change link attributes
89044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg handle		netlink handle
89144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg old		link to be changed
89244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl		template with requested changes
89344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
89444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
89544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message by calling rtnl_link_build_change_request(),
89644d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be
89744d362409d5469aed47d19e7908d19bd194493aThomas Graf * received, i.e. blocks until the request has been processed.
89844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
89944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
90044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Not all attributes can be changed, see
90144d362409d5469aed47d19e7908d19bd194493aThomas Graf *       \ref link_changeable "Changeable Attributes" for more details.
90244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
90344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_change(struct nl_handle *handle, struct rtnl_link *old,
90444d362409d5469aed47d19e7908d19bd194493aThomas Graf		     struct rtnl_link *tmpl, int flags)
90544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
90644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
90744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
90844d362409d5469aed47d19e7908d19bd194493aThomas Graf
90944d362409d5469aed47d19e7908d19bd194493aThomas Graf	msg = rtnl_link_build_change_request(old, tmpl, flags);
91044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!msg)
91144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return nl_errno(ENOMEM);
91244d362409d5469aed47d19e7908d19bd194493aThomas Graf
91344d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = nl_send_auto_complete(handle, msg);
91444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
91544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return err;
91644d362409d5469aed47d19e7908d19bd194493aThomas Graf
91744d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
91844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_wait_for_ack(handle);
91944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
92044d362409d5469aed47d19e7908d19bd194493aThomas Graf
92144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
92244d362409d5469aed47d19e7908d19bd194493aThomas Graf
92344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
92444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Name <-> Index Translations
92544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
92644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
92744d362409d5469aed47d19e7908d19bd194493aThomas Graf
92844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
92944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Translate an interface index to the corresponding link name
93044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache		link cache
93144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ifindex		link interface index
93244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg dst		destination buffer
93344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg len		length of destination buffer
93444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
93544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Translates the specified interface index to the corresponding
93644d362409d5469aed47d19e7908d19bd194493aThomas Graf * link name and stores the name in the destination buffer.
93744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
93844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return link name or NULL if no match was found.
93944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
94044d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst,
94144d362409d5469aed47d19e7908d19bd194493aThomas Graf			size_t len)
94244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
94344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link = rtnl_link_get(cache, ifindex);
94444d362409d5469aed47d19e7908d19bd194493aThomas Graf
94544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link) {
94644d362409d5469aed47d19e7908d19bd194493aThomas Graf		strncpy(dst, link->l_name, len - 1);
94744d362409d5469aed47d19e7908d19bd194493aThomas Graf		rtnl_link_put(link);
94844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return dst;
94944d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
95044d362409d5469aed47d19e7908d19bd194493aThomas Graf
95144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
95244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
95344d362409d5469aed47d19e7908d19bd194493aThomas Graf
95444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
95544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Translate a link name to the corresponding interface index
95644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache		link cache
95744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name		link name
95844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
95944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return interface index or RTNL_LINK_NOT_FOUND if no match was found.
96044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
96144d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_name2i(struct nl_cache *cache, const char *name)
96244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
96344d362409d5469aed47d19e7908d19bd194493aThomas Graf	int ifindex = RTNL_LINK_NOT_FOUND;
96444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_link *link;
96544d362409d5469aed47d19e7908d19bd194493aThomas Graf
96644d362409d5469aed47d19e7908d19bd194493aThomas Graf	link = rtnl_link_get_by_name(cache, name);
96744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link) {
96844d362409d5469aed47d19e7908d19bd194493aThomas Graf		ifindex = link->l_index;
96944d362409d5469aed47d19e7908d19bd194493aThomas Graf		rtnl_link_put(link);
97044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
97144d362409d5469aed47d19e7908d19bd194493aThomas Graf
97244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ifindex;
97344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
97444d362409d5469aed47d19e7908d19bd194493aThomas Graf
97544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
97644d362409d5469aed47d19e7908d19bd194493aThomas Graf
97744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
97844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Link Flags Translations
97944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
98044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
98144d362409d5469aed47d19e7908d19bd194493aThomas Graf
98244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl link_flags[] = {
98344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_LOOPBACK, loopback)
98444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_BROADCAST, broadcast)
98544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_POINTOPOINT, pointopoint)
98644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_MULTICAST, multicast)
98744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_NOARP, noarp)
98844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_ALLMULTI, allmulti)
98944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_PROMISC, promisc)
99044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_MASTER, master)
99144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_SLAVE, slave)
99244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_DEBUG, debug)
99344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_DYNAMIC, dynamic)
99444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_AUTOMEDIA, automedia)
99544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_PORTSEL, portsel)
99644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_NOTRAILERS, notrailers)
99744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_UP, up)
99844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_RUNNING, running)
99944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_LOWER_UP, lowerup)
100044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(IFF_DORMANT, dormant)
100144d362409d5469aed47d19e7908d19bd194493aThomas Graf};
100244d362409d5469aed47d19e7908d19bd194493aThomas Graf
100344d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * rtnl_link_flags2str(int flags, char *buf, size_t len)
100444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
100544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __flags2str(flags, buf, len, link_flags,
100644d362409d5469aed47d19e7908d19bd194493aThomas Graf			   ARRAY_SIZE(link_flags));
100744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
100844d362409d5469aed47d19e7908d19bd194493aThomas Graf
100944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_str2flags(const char *name)
101044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
101144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
101244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
101344d362409d5469aed47d19e7908d19bd194493aThomas Graf
101444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
101544d362409d5469aed47d19e7908d19bd194493aThomas Graf
101644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
101744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Link Statistics Translations
101844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
101944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
102044d362409d5469aed47d19e7908d19bd194493aThomas Graf
102144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct trans_tbl link_stats[] = {
102244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_PACKETS, rx_packets)
102344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_PACKETS, tx_packets)
102444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_BYTES, rx_bytes)
102544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_BYTES, tx_bytes)
102644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_ERRORS, rx_errors)
102744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_ERRORS, tx_errors)
102844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
102944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
103044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
103144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
103244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
103344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
103444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
103544d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
103644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
103744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
103844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
103944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
104044d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
104144d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
104244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
104344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
104444d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RTNL_LINK_MULTICAST, multicast)
104544d362409d5469aed47d19e7908d19bd194493aThomas Graf};
104644d362409d5469aed47d19e7908d19bd194493aThomas Graf
104744d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_link_stat2str(int st, char *buf, size_t len)
104844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
104944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
105044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
105144d362409d5469aed47d19e7908d19bd194493aThomas Graf
105244d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_str2stat(const char *name)
105344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
105444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
105544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
105644d362409d5469aed47d19e7908d19bd194493aThomas Graf
105744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
105844d362409d5469aed47d19e7908d19bd194493aThomas Graf
105944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
106044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes
106144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
106244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
106344d362409d5469aed47d19e7908d19bd194493aThomas Graf
106444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_qdisc(struct rtnl_link *link, const char *qdisc)
106544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
106644d362409d5469aed47d19e7908d19bd194493aThomas Graf	strncpy(link->l_qdisc, qdisc, sizeof(link->l_qdisc) - 1);
106744d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_QDISC;
106844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
106944d362409d5469aed47d19e7908d19bd194493aThomas Graf
107044d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_link_get_qdisc(struct rtnl_link *link)
107144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
107244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_QDISC)
107344d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_qdisc;
107444d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
107544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
107644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
107744d362409d5469aed47d19e7908d19bd194493aThomas Graf
107844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_name(struct rtnl_link *link, const char *name)
107944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
108044d362409d5469aed47d19e7908d19bd194493aThomas Graf	strncpy(link->l_name, name, sizeof(link->l_name) - 1);
108144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_IFNAME;
108244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
108344d362409d5469aed47d19e7908d19bd194493aThomas Graf
108444d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_link_get_name(struct rtnl_link *link)
108544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
108644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_IFNAME)
108744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_name;
108844d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
108944d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
109044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
109144d362409d5469aed47d19e7908d19bd194493aThomas Graf
109244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
109344d362409d5469aed47d19e7908d19bd194493aThomas Graf				 struct nl_addr *new, int flag)
109444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
109544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*pos)
109644d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_put(*pos);
109744d362409d5469aed47d19e7908d19bd194493aThomas Graf
109844d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_get(new);
109944d362409d5469aed47d19e7908d19bd194493aThomas Graf	*pos = new;
110044d362409d5469aed47d19e7908d19bd194493aThomas Graf
110144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= flag;
110244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
110344d362409d5469aed47d19e7908d19bd194493aThomas Graf
110444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
110544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
110644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
110744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
110844d362409d5469aed47d19e7908d19bd194493aThomas Graf
110944d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
111044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
111144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_ADDR)
111244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_addr;
111344d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
111444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
111544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
111644d362409d5469aed47d19e7908d19bd194493aThomas Graf
111744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *brd)
111844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
111944d362409d5469aed47d19e7908d19bd194493aThomas Graf	__assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
112044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
112144d362409d5469aed47d19e7908d19bd194493aThomas Graf
112244d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
112344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
112444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_BRD)
112544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_bcast;
112644d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
112744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
112844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
112944d362409d5469aed47d19e7908d19bd194493aThomas Graf
113044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
113144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
113244d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_flag_mask |= flags;
113344d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_flags |= flags;
113444d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_FLAGS;
113544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
113644d362409d5469aed47d19e7908d19bd194493aThomas Graf
113744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
113844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
113944d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_flag_mask |= flags;
114044d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_flags &= ~flags;
114144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_FLAGS;
114244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
114344d362409d5469aed47d19e7908d19bd194493aThomas Graf
114444d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_link_get_flags(struct rtnl_link *link)
114544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
114644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return link->l_flags;
114744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
114844d362409d5469aed47d19e7908d19bd194493aThomas Graf
114944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_family(struct rtnl_link *link, int family)
115044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
115144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_family = family;
115244d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_FAMILY;
115344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
115444d362409d5469aed47d19e7908d19bd194493aThomas Graf
115544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_get_family(struct rtnl_link *link)
115644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
115744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->l_family & LINK_ATTR_FAMILY)
115844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_family;
115944d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
116044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return AF_UNSPEC;
116144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
116244d362409d5469aed47d19e7908d19bd194493aThomas Graf
116344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype)
116444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
116544d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_arptype = arptype;
116644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
116744d362409d5469aed47d19e7908d19bd194493aThomas Graf
116844d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_link_get_arptype(struct rtnl_link *link)
116944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
117044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return link->l_arptype;
117144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
117244d362409d5469aed47d19e7908d19bd194493aThomas Graf
117344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
117444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
117544d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_index = ifindex;
117644d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_IFINDEX;
117744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
117844d362409d5469aed47d19e7908d19bd194493aThomas Graf
117944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_get_ifindex(struct rtnl_link *link)
118044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
118144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_IFINDEX)
118244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_index;
118344d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
118444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return RTNL_LINK_NOT_FOUND;
118544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
118644d362409d5469aed47d19e7908d19bd194493aThomas Graf
118744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
118844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
118944d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_mtu = mtu;
119044d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_MTU;
119144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
119244d362409d5469aed47d19e7908d19bd194493aThomas Graf
119344d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_link_get_mtu(struct rtnl_link *link)
119444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
119544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MTU)
119644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_mtu;
119744d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
119844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 0;
119944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
120044d362409d5469aed47d19e7908d19bd194493aThomas Graf
120144d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
120244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
120344d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_txqlen = txqlen;
120444d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_TXQLEN;
120544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
120644d362409d5469aed47d19e7908d19bd194493aThomas Graf
120744d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
120844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
120944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_TXQLEN)
121044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_txqlen;
121144d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
121244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return UINT_MAX;
121344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
121444d362409d5469aed47d19e7908d19bd194493aThomas Graf
121544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
121644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
121744d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_weight = weight;
121844d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_WEIGHT;
121944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
122044d362409d5469aed47d19e7908d19bd194493aThomas Graf
122144d362409d5469aed47d19e7908d19bd194493aThomas Grafunsigned int rtnl_link_get_weight(struct rtnl_link *link)
122244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
122344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_WEIGHT)
122444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_weight;
122544d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
122644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return UINT_MAX;
122744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
122844d362409d5469aed47d19e7908d19bd194493aThomas Graf
122944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_link(struct rtnl_link *link, int ifindex)
123044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
123144d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_link = ifindex;
123244d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_LINK;
123344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
123444d362409d5469aed47d19e7908d19bd194493aThomas Graf
123544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_get_link(struct rtnl_link *link)
123644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
123744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_LINK)
123844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_link;
123944d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
124044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return RTNL_LINK_NOT_FOUND;
124144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
124244d362409d5469aed47d19e7908d19bd194493aThomas Graf
124344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_link_set_master(struct rtnl_link *link, int ifindex)
124444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
124544d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->l_master = ifindex;
124644d362409d5469aed47d19e7908d19bd194493aThomas Graf	link->ce_mask |= LINK_ATTR_MASTER;
124744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
124844d362409d5469aed47d19e7908d19bd194493aThomas Graf
124944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_link_get_master(struct rtnl_link *link)
125044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
125144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (link->ce_mask & LINK_ATTR_MASTER)
125244d362409d5469aed47d19e7908d19bd194493aThomas Graf		return link->l_master;
125344d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
125444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return RTNL_LINK_NOT_FOUND;
125544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
125644d362409d5469aed47d19e7908d19bd194493aThomas Graf
125744d362409d5469aed47d19e7908d19bd194493aThomas Grafuint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
125844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
125944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (id < 0 || id > RTNL_LINK_STATS_MAX)
126044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 0;
126144d362409d5469aed47d19e7908d19bd194493aThomas Graf
126244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return link->l_stats[id];
126344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
126444d362409d5469aed47d19e7908d19bd194493aThomas Graf
126544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
126644d362409d5469aed47d19e7908d19bd194493aThomas Graf
126744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops link_obj_ops = {
126844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_name		= "route/link",
126944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_size		= sizeof(struct rtnl_link),
127044d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_free_data		= link_free_data,
127144d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_clone		= link_clone,
127244d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_dump[NL_DUMP_BRIEF]	= link_dump_brief,
127344d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_dump[NL_DUMP_FULL]	= link_dump_full,
127444d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_dump[NL_DUMP_STATS]	= link_dump_stats,
127544d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_dump[NL_DUMP_XML]	= link_dump_xml,
127644d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_dump[NL_DUMP_ENV]	= link_dump_env,
127744d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_compare		= link_compare,
127844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_attrs2str		= link_attrs2str,
127944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_id_attrs		= LINK_ATTR_IFINDEX,
128044d362409d5469aed47d19e7908d19bd194493aThomas Graf};
128144d362409d5469aed47d19e7908d19bd194493aThomas Graf
128244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_af_group link_groups[] = {
128344d362409d5469aed47d19e7908d19bd194493aThomas Graf	{ AF_UNSPEC,	RTNLGRP_LINK },
128444d362409d5469aed47d19e7908d19bd194493aThomas Graf	{ END_OF_GROUP_LIST },
128544d362409d5469aed47d19e7908d19bd194493aThomas Graf};
128644d362409d5469aed47d19e7908d19bd194493aThomas Graf
128744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_link_ops = {
128844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_name		= "route/link",
128944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_hdrsize		= sizeof(struct ifinfomsg),
129044d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msgtypes		= {
129144d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_NEWLINK, NL_ACT_NEW, "new" },
129244d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_DELLINK, NL_ACT_DEL, "del" },
129344d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_GETLINK, NL_ACT_GET, "get" },
129444d362409d5469aed47d19e7908d19bd194493aThomas Graf					END_OF_MSGTYPES_LIST,
129544d362409d5469aed47d19e7908d19bd194493aThomas Graf				  },
129644d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_protocol		= NETLINK_ROUTE,
129744d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_groups		= link_groups,
129844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_request_update	= link_request_update,
129944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msg_parser		= link_msg_parser,
130044d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_obj_ops		= &link_obj_ops,
130144d362409d5469aed47d19e7908d19bd194493aThomas Graf};
130244d362409d5469aed47d19e7908d19bd194493aThomas Graf
130344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init link_init(void)
130444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
130544d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_register(&rtnl_link_ops);
130644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
130744d362409d5469aed47d19e7908d19bd194493aThomas Graf
130844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit link_exit(void)
130944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
131044d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_unregister(&rtnl_link_ops);
131144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
131244d362409d5469aed47d19e7908d19bd194493aThomas Graf
131344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
1314