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