12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583 |
- /*
- * lib/route/link.c Links (Interfaces)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
- */
- /**
- * @ingroup rtnl
- * @defgroup link Links (Interfaces)
- * @brief
- *
- * @par Link Identification
- * A link can be identified by either its interface index or by its
- * name. The kernel favours the interface index but falls back to the
- * interface name if the interface index is lesser-than 0 for kernels
- * >= 2.6.11. Therefore you can request changes without mapping a
- * interface name to the corresponding index first.
- *
- * @par Changeable Attributes
- * @anchor link_changeable
- * - Link layer address
- * - Link layer broadcast address
- * - device mapping (ifmap) (>= 2.6.9)
- * - MTU (>= 2.6.9)
- * - Transmission queue length (>= 2.6.9)
- * - Weight (>= 2.6.9)
- * - Link name (only via access through interface index) (>= 2.6.9)
- * - Flags (>= 2.6.9)
- * - IFF_DEBUG
- * - IFF_NOTRAILERS
- * - IFF_NOARP
- * - IFF_DYNAMIC
- * - IFF_MULTICAST
- * - IFF_PORTSEL
- * - IFF_AUTOMEDIA
- * - IFF_UP
- * - IFF_PROMISC
- * - IFF_ALLMULTI
- *
- * @par Link Flags (linux/if.h)
- * @anchor link_flags
- * @code
- * IFF_UP Status of link (up|down)
- * IFF_BROADCAST Indicates this link allows broadcasting
- * IFF_MULTICAST Indicates this link allows multicasting
- * IFF_ALLMULTI Indicates this link is doing multicast routing
- * IFF_DEBUG Tell the driver to do debugging (currently unused)
- * IFF_LOOPBACK This is the loopback link
- * IFF_POINTOPOINT Point-to-point link
- * IFF_NOARP Link is unable to perform ARP
- * IFF_PROMISC Status of promiscious mode flag
- * IFF_MASTER Used by teql
- * IFF_SLAVE Used by teql
- * IFF_PORTSEL Indicates this link allows port selection
- * IFF_AUTOMEDIA Indicates this link selects port automatically
- * IFF_DYNAMIC Indicates the address of this link is dynamic
- * IFF_RUNNING Link is running and carrier is ok.
- * IFF_NOTRAILERS Unused, BSD compat.
- * @endcode
- *
- * @par Notes on IFF_PROMISC and IFF_ALLMULTI flags
- * Although you can query the status of IFF_PROMISC and IFF_ALLMULTI
- * they do not represent the actual state in the kernel but rather
- * whether the flag has been enabled/disabled by userspace. The link
- * may be in promiscious mode even if IFF_PROMISC is not set in a link
- * dump request response because promiscity might be needed by the driver
- * for a period of time.
- *
- * @note The unit of the transmission queue length depends on the
- * link type, a common unit is \a packets.
- *
- * @par 1) Retrieving information about available links
- * @code
- * // The first step is to retrieve a list of all available interfaces within
- * // the kernel and put them into a cache.
- * struct nl_cache *cache = rtnl_link_alloc_cache(nl_handle);
- *
- * // In a second step, a specific link may be looked up by either interface
- * // index or interface name.
- * struct rtnl_link *link = rtnl_link_get_by_name(cache, "lo");
- *
- * // rtnl_link_get_by_name() is the short version for translating the
- * // interface name to an interface index first like this:
- * int ifindex = rtnl_link_name2i(cache, "lo");
- * struct rtnl_link *link = rtnl_link_get(cache, ifindex);
- *
- * // After successful usage, the object must be given back to the cache
- * rtnl_link_put(link);
- * @endcode
- *
- * @par 2) Changing link attributes
- * @code
- * // In order to change any attributes of an existing link, we must allocate
- * // a new link to hold the change requests:
- * struct rtnl_link *request = rtnl_link_alloc();
- *
- * // Now we can go on and specify the attributes we want to change:
- * rtnl_link_set_weight(request, 300);
- * rtnl_link_set_mtu(request, 1360);
- *
- * // We can also shut an interface down administratively
- * rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
- *
- * // Actually, we should know which link to change, so let's look it up
- * struct rtnl_link *old = rtnl_link_get(cache, "eth0");
- *
- * // Two ways exist to commit this change request, the first one is to
- * // build the required netlink message and send it out in one single
- * // step:
- * rtnl_link_change(nl_handle, old, request);
- *
- * // An alternative way is to build the netlink message and send it
- * // out yourself using nl_send_auto_complete()
- * struct nl_msg *msg = rtnl_link_build_change_request(old, request);
- * nl_send_auto_complete(nl_handle, nlmsg_hdr(msg));
- * nlmsg_free(msg);
- *
- * // Don't forget to give back the link object ;->
- * rtnl_link_put(old);
- * @endcode
- *
- * @par 3) Link Type Specific Attributes
- * @code
- * // Some link types offer additional parameters and statistics specific
- * // to their type. F.e. a VLAN link can be configured like this:
- * //
- * // Allocate a new link and set the info type to "vlan". This is required
- * // to prepare the link to hold vlan specific attributes.
- * struct rtnl_link *request = rtnl_link_alloc();
- * rtnl_link_set_info_type(request, "vlan");
- *
- * // Now vlan specific attributes can be set:
- * rtnl_link_vlan_set_id(request, 10);
- * rtnl_link_vlan_set_ingress_map(request, 2, 8);
- *
- * // Of course the attributes can also be read, check the info type
- * // to make sure you are using the right access functions:
- * char *type = rtnl_link_get_info_type(link);
- * if (!strcmp(type, "vlan"))
- * int id = rtnl_link_vlan_get_id(link);
- * @endcode
- * @{
- */
- #include <netlink-local.h>
- #include <netlink/netlink.h>
- #include <netlink/attr.h>
- #include <netlink/utils.h>
- #include <netlink/object.h>
- #include <netlink/route/rtnl.h>
- #include <netlink/route/link.h>
- #include <netlink/route/link/info-api.h>
- /** @cond SKIP */
- #define LINK_ATTR_MTU 0x0001
- #define LINK_ATTR_LINK 0x0002
- #define LINK_ATTR_TXQLEN 0x0004
- #define LINK_ATTR_WEIGHT 0x0008
- #define LINK_ATTR_MASTER 0x0010
- #define LINK_ATTR_QDISC 0x0020
- #define LINK_ATTR_MAP 0x0040
- #define LINK_ATTR_ADDR 0x0080
- #define LINK_ATTR_BRD 0x0100
- #define LINK_ATTR_FLAGS 0x0200
- #define LINK_ATTR_IFNAME 0x0400
- #define LINK_ATTR_IFINDEX 0x0800
- #define LINK_ATTR_FAMILY 0x1000
- #define LINK_ATTR_ARPTYPE 0x2000
- #define LINK_ATTR_STATS 0x4000
- #define LINK_ATTR_CHANGE 0x8000
- #define LINK_ATTR_OPERSTATE 0x10000
- #define LINK_ATTR_LINKMODE 0x20000
- #define LINK_ATTR_LINKINFO 0x40000
- static struct nl_cache_ops rtnl_link_ops;
- static struct nl_object_ops link_obj_ops;
- /** @endcond */
- static void release_link_info(struct rtnl_link *link)
- {
- struct rtnl_link_info_ops *io = link->l_info_ops;
- if (io != NULL) {
- io->io_refcnt--;
- io->io_free(link);
- link->l_info_ops = NULL;
- }
- }
- static void link_free_data(struct nl_object *c)
- {
- struct rtnl_link *link = nl_object_priv(c);
- if (link) {
- struct rtnl_link_info_ops *io;
- if ((io = link->l_info_ops) != NULL)
- release_link_info(link);
- nl_addr_put(link->l_addr);
- nl_addr_put(link->l_bcast);
- }
- }
- static int link_clone(struct nl_object *_dst, struct nl_object *_src)
- {
- struct rtnl_link *dst = nl_object_priv(_dst);
- struct rtnl_link *src = nl_object_priv(_src);
- int err;
- if (src->l_addr)
- if (!(dst->l_addr = nl_addr_clone(src->l_addr)))
- goto errout;
- if (src->l_bcast)
- if (!(dst->l_bcast = nl_addr_clone(src->l_bcast)))
- goto errout;
- if (src->l_info_ops && src->l_info_ops->io_clone) {
- err = src->l_info_ops->io_clone(dst, src);
- if (err < 0)
- goto errout;
- }
- return 0;
- errout:
- return nl_get_errno();
- }
- static struct nla_policy link_policy[IFLA_MAX+1] = {
- [IFLA_IFNAME] = { .type = NLA_STRING,
- .maxlen = IFNAMSIZ },
- [IFLA_MTU] = { .type = NLA_U32 },
- [IFLA_TXQLEN] = { .type = NLA_U32 },
- [IFLA_LINK] = { .type = NLA_U32 },
- [IFLA_WEIGHT] = { .type = NLA_U32 },
- [IFLA_MASTER] = { .type = NLA_U32 },
- [IFLA_OPERSTATE]= { .type = NLA_U8 },
- [IFLA_LINKMODE] = { .type = NLA_U8 },
- [IFLA_LINKINFO] = { .type = NLA_NESTED },
- [IFLA_QDISC] = { .type = NLA_STRING,
- .maxlen = IFQDISCSIZ },
- [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) },
- [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) },
- };
- static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = {
- [IFLA_INFO_KIND] = { .type = NLA_STRING },
- [IFLA_INFO_DATA] = { .type = NLA_NESTED },
- [IFLA_INFO_XSTATS] = { .type = NLA_NESTED },
- };
- static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
- struct nlmsghdr *n, struct nl_parser_param *pp)
- {
- struct rtnl_link *link;
- struct ifinfomsg *ifi;
- struct nlattr *tb[IFLA_MAX+1];
- int err;
- link = rtnl_link_alloc();
- if (link == NULL) {
- err = nl_errno(ENOMEM);
- goto errout;
- }
-
- link->ce_msgtype = n->nlmsg_type;
- err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy);
- if (err < 0)
- goto errout;
- if (tb[IFLA_IFNAME] == NULL) {
- err = nl_error(EINVAL, "Missing link name TLV");
- goto errout;
- }
- nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
- ifi = nlmsg_data(n);
- link->l_family = ifi->ifi_family;
- link->l_arptype = ifi->ifi_type;
- link->l_index = ifi->ifi_index;
- link->l_flags = ifi->ifi_flags;
- link->l_change = ifi->ifi_change;
- link->ce_mask = (LINK_ATTR_IFNAME | LINK_ATTR_FAMILY |
- LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
- LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
- if (tb[IFLA_STATS]) {
- struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]);
-
- link->l_stats[RTNL_LINK_RX_PACKETS] = st->rx_packets;
- link->l_stats[RTNL_LINK_RX_BYTES] = st->rx_bytes;
- link->l_stats[RTNL_LINK_RX_ERRORS] = st->rx_errors;
- link->l_stats[RTNL_LINK_RX_DROPPED] = st->rx_dropped;
- link->l_stats[RTNL_LINK_RX_COMPRESSED] = st->rx_compressed;
- link->l_stats[RTNL_LINK_RX_FIFO_ERR] = st->rx_fifo_errors;
- link->l_stats[RTNL_LINK_TX_PACKETS] = st->tx_packets;
- link->l_stats[RTNL_LINK_TX_BYTES] = st->tx_bytes;
- link->l_stats[RTNL_LINK_TX_ERRORS] = st->tx_errors;
- link->l_stats[RTNL_LINK_TX_DROPPED] = st->tx_dropped;
- link->l_stats[RTNL_LINK_TX_COMPRESSED] = st->tx_compressed;
- link->l_stats[RTNL_LINK_TX_FIFO_ERR] = st->tx_fifo_errors;
- link->l_stats[RTNL_LINK_RX_LEN_ERR] = st->rx_length_errors;
- link->l_stats[RTNL_LINK_RX_OVER_ERR] = st->rx_over_errors;
- link->l_stats[RTNL_LINK_RX_CRC_ERR] = st->rx_crc_errors;
- link->l_stats[RTNL_LINK_RX_FRAME_ERR] = st->rx_frame_errors;
- link->l_stats[RTNL_LINK_RX_MISSED_ERR] = st->rx_missed_errors;
- link->l_stats[RTNL_LINK_TX_ABORT_ERR] = st->tx_aborted_errors;
- link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors;
- link->l_stats[RTNL_LINK_TX_HBEAT_ERR] = st->tx_heartbeat_errors;
- link->l_stats[RTNL_LINK_TX_WIN_ERR] = st->tx_window_errors;
- link->l_stats[RTNL_LINK_MULTICAST] = st->multicast;
- link->ce_mask |= LINK_ATTR_STATS;
- }
- if (tb[IFLA_TXQLEN]) {
- link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]);
- link->ce_mask |= LINK_ATTR_TXQLEN;
- }
- if (tb[IFLA_MTU]) {
- link->l_mtu = nla_get_u32(tb[IFLA_MTU]);
- link->ce_mask |= LINK_ATTR_MTU;
- }
- if (tb[IFLA_ADDRESS]) {
- link->l_addr = nla_get_addr(tb[IFLA_ADDRESS], AF_UNSPEC);
- if (link->l_addr == NULL)
- goto errout;
- nl_addr_set_family(link->l_addr,
- nl_addr_guess_family(link->l_addr));
- link->ce_mask |= LINK_ATTR_ADDR;
- }
- if (tb[IFLA_BROADCAST]) {
- link->l_bcast = nla_get_addr(tb[IFLA_BROADCAST], AF_UNSPEC);
- if (link->l_bcast == NULL)
- goto errout;
- nl_addr_set_family(link->l_bcast,
- nl_addr_guess_family(link->l_bcast));
- link->ce_mask |= LINK_ATTR_BRD;
- }
- if (tb[IFLA_LINK]) {
- link->l_link = nla_get_u32(tb[IFLA_LINK]);
- link->ce_mask |= LINK_ATTR_LINK;
- }
- if (tb[IFLA_WEIGHT]) {
- link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]);
- link->ce_mask |= LINK_ATTR_WEIGHT;
- }
- if (tb[IFLA_QDISC]) {
- nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
- link->ce_mask |= LINK_ATTR_QDISC;
- }
- if (tb[IFLA_MAP]) {
- nla_memcpy(&link->l_map, tb[IFLA_MAP],
- sizeof(struct rtnl_link_ifmap));
- link->ce_mask |= LINK_ATTR_MAP;
- }
- if (tb[IFLA_MASTER]) {
- link->l_master = nla_get_u32(tb[IFLA_MASTER]);
- link->ce_mask |= LINK_ATTR_MASTER;
- }
- if (tb[IFLA_OPERSTATE]) {
- link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]);
- link->ce_mask |= LINK_ATTR_OPERSTATE;
- }
- if (tb[IFLA_LINKMODE]) {
- link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]);
- link->ce_mask |= LINK_ATTR_LINKMODE;
- }
- if (tb[IFLA_LINKINFO]) {
- struct nlattr *li[IFLA_INFO_MAX+1];
- err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
- link_info_policy);
- if (err < 0)
- goto errout;
- if (li[IFLA_INFO_KIND] &&
- (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
- struct rtnl_link_info_ops *ops;
- char *kind;
- kind = nla_get_string(li[IFLA_INFO_KIND]);
- ops = rtnl_link_info_ops_lookup(kind);
- if (ops != NULL) {
- ops->io_refcnt++;
- link->l_info_ops = ops;
- err = ops->io_parse(link, li[IFLA_INFO_DATA],
- li[IFLA_INFO_XSTATS]);
- if (err < 0)
- goto errout;
- } else {
- /* XXX: Warn about unparsed info? */
- }
- }
- }
- err = pp->pp_cb((struct nl_object *) link, pp);
- if (err < 0)
- goto errout;
- err = P_ACCEPT;
- errout:
- rtnl_link_put(link);
- return err;
- }
- static int link_request_update(struct nl_cache *c, struct nl_handle *h)
- {
- return nl_rtgen_request(h, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
- }
- static int link_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
- {
- char buf[128];
- struct nl_cache *cache = dp_cache(obj);
- struct rtnl_link *link = (struct rtnl_link *) obj;
- int line = 1;
- dp_dump(p, "%s %s ", link->l_name,
- nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
- if (link->l_addr && !nl_addr_iszero(link->l_addr))
- dp_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf)));
- if (link->ce_mask & LINK_ATTR_MASTER) {
- struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
- dp_dump(p, "master %s ", master ? master->l_name : "inv");
- if (master)
- rtnl_link_put(master);
- }
- rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
- if (buf[0])
- dp_dump(p, "<%s> ", buf);
- if (link->ce_mask & LINK_ATTR_LINK) {
- struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
- dp_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE");
- if (ll)
- rtnl_link_put(ll);
- }
- if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_BRIEF])
- line = link->l_info_ops->io_dump[NL_DUMP_BRIEF](link, p, line);
- dp_dump(p, "\n");
- return line;
- }
- static int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
- {
- struct rtnl_link *link = (struct rtnl_link *) obj;
- char buf[64];
- int line;
- line = link_dump_brief(obj, p);
- dp_new_line(p, line++);
- dp_dump(p, " mtu %u ", link->l_mtu);
- dp_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight);
- if (link->ce_mask & LINK_ATTR_QDISC)
- dp_dump(p, "qdisc %s ", link->l_qdisc);
- if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
- dp_dump(p, "irq %u ", link->l_map.lm_irq);
- if (link->ce_mask & LINK_ATTR_IFINDEX)
- dp_dump(p, "index %u ", link->l_index);
- dp_dump(p, "\n");
- dp_new_line(p, line++);
- dp_dump(p, " ");
- if (link->ce_mask & LINK_ATTR_BRD)
- dp_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf,
- sizeof(buf)));
- if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
- link->l_operstate != IF_OPER_UNKNOWN) {
- rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf));
- dp_dump(p, "state %s ", buf);
- }
- dp_dump(p, "mode %s\n",
- rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf)));
- if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_FULL])
- line = link->l_info_ops->io_dump[NL_DUMP_FULL](link, p, line);
- return line;
- }
- static int link_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
- {
- struct rtnl_link *link = (struct rtnl_link *) obj;
- char *unit, fmt[64];
- float res;
- int line;
-
- line = link_dump_full(obj, p);
- dp_dump_line(p, line++, " Stats: bytes packets errors "
- " dropped fifo-err compressed\n");
- res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit);
- strcpy(fmt, " RX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
- fmt[9] = *unit == 'B' ? '9' : '7';
-
- dp_dump_line(p, line++, fmt,
- res, unit,
- link->l_stats[RTNL_LINK_RX_PACKETS],
- link->l_stats[RTNL_LINK_RX_ERRORS],
- link->l_stats[RTNL_LINK_RX_DROPPED],
- link->l_stats[RTNL_LINK_RX_FIFO_ERR],
- link->l_stats[RTNL_LINK_RX_COMPRESSED]);
- res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit);
- strcpy(fmt, " TX %X.2f %s %10llu %10llu %10llu %10llu %10llu\n");
- fmt[9] = *unit == 'B' ? '9' : '7';
-
- dp_dump_line(p, line++, fmt,
- res, unit,
- link->l_stats[RTNL_LINK_TX_PACKETS],
- link->l_stats[RTNL_LINK_TX_ERRORS],
- link->l_stats[RTNL_LINK_TX_DROPPED],
- link->l_stats[RTNL_LINK_TX_FIFO_ERR],
- link->l_stats[RTNL_LINK_TX_COMPRESSED]);
- dp_dump_line(p, line++, " Errors: length over crc "
- " frame missed multicast\n");
- dp_dump_line(p, line++, " RX %10" PRIu64 " %10" PRIu64 " %10"
- PRIu64 " %10" PRIu64 " %10" PRIu64 " %10"
- PRIu64 "\n",
- link->l_stats[RTNL_LINK_RX_LEN_ERR],
- link->l_stats[RTNL_LINK_RX_OVER_ERR],
- link->l_stats[RTNL_LINK_RX_CRC_ERR],
- link->l_stats[RTNL_LINK_RX_FRAME_ERR],
- link->l_stats[RTNL_LINK_RX_MISSED_ERR],
- link->l_stats[RTNL_LINK_MULTICAST]);
- dp_dump_line(p, line++, " Errors: aborted carrier heartbeat "
- " window collision\n");
-
- dp_dump_line(p, line++, " TX %10" PRIu64 " %10" PRIu64 " %10"
- PRIu64 " %10" PRIu64 " %10" PRIu64 "\n",
- link->l_stats[RTNL_LINK_TX_ABORT_ERR],
- link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
- link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
- link->l_stats[RTNL_LINK_TX_WIN_ERR],
- link->l_stats[RTNL_LINK_TX_COLLISIONS]);
- if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_STATS])
- line = link->l_info_ops->io_dump[NL_DUMP_STATS](link, p, line);
- return line;
- }
- static int link_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
- {
- struct rtnl_link *link = (struct rtnl_link *) obj;
- struct nl_cache *cache = dp_cache(obj);
- char buf[128];
- int i, line = 0;
- dp_dump_line(p, line++, "<link name=\"%s\" index=\"%u\">\n",
- link->l_name, link->l_index);
- dp_dump_line(p, line++, " <family>%s</family>\n",
- nl_af2str(link->l_family, buf, sizeof(buf)));
- dp_dump_line(p, line++, " <arptype>%s</arptype>\n",
- nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
- dp_dump_line(p, line++, " <address>%s</address>\n",
- nl_addr2str(link->l_addr, buf, sizeof(buf)));
- dp_dump_line(p, line++, " <mtu>%u</mtu>\n", link->l_mtu);
- dp_dump_line(p, line++, " <txqlen>%u</txqlen>\n", link->l_txqlen);
- dp_dump_line(p, line++, " <weight>%u</weight>\n", link->l_weight);
- rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
- if (buf[0])
- dp_dump_line(p, line++, " <flags>%s</flags>\n", buf);
- if (link->ce_mask & LINK_ATTR_QDISC)
- dp_dump_line(p, line++, " <qdisc>%s</qdisc>\n", link->l_qdisc);
- if (link->ce_mask & LINK_ATTR_LINK) {
- struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
- dp_dump_line(p, line++, " <link>%s</link>\n",
- ll ? ll->l_name : "none");
- if (ll)
- rtnl_link_put(ll);
- }
- if (link->ce_mask & LINK_ATTR_MASTER) {
- struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
- dp_dump_line(p, line++, " <master>%s</master>\n",
- master ? master->l_name : "none");
- if (master)
- rtnl_link_put(master);
- }
- if (link->ce_mask & LINK_ATTR_BRD)
- dp_dump_line(p, line++, " <broadcast>%s</broadcast>\n",
- nl_addr2str(link->l_bcast, buf, sizeof(buf)));
- if (link->ce_mask & LINK_ATTR_STATS) {
- dp_dump_line(p, line++, " <stats>\n");
- for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
- rtnl_link_stat2str(i, buf, sizeof(buf));
- dp_dump_line(p, line++,
- " <%s>%" PRIu64 "</%s>\n",
- buf, link->l_stats[i], buf);
- }
- dp_dump_line(p, line++, " </stats>\n");
- }
- if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_XML]) {
- dp_dump_line(p, line++, " <info>\n");
- line = link->l_info_ops->io_dump[NL_DUMP_XML](link, p, line);
- dp_dump_line(p, line++, " </info>\n");
- }
- dp_dump_line(p, line++, "</link>\n");
- #if 0
- uint32_t l_change; /**< Change mask */
- struct rtnl_lifmap l_map; /**< Interface device mapping */
- #endif
- return line;
- }
- static int link_dump_env(struct nl_object *obj, struct nl_dump_params *p)
- {
- struct rtnl_link *link = (struct rtnl_link *) obj;
- struct nl_cache *cache = dp_cache(obj);
- char buf[128];
- int i, line = 0;
- dp_dump_line(p, line++, "LINK_NAME=%s\n", link->l_name);
- dp_dump_line(p, line++, "LINK_IFINDEX=%u\n", link->l_index);
- dp_dump_line(p, line++, "LINK_FAMILY=%s\n",
- nl_af2str(link->l_family, buf, sizeof(buf)));
- dp_dump_line(p, line++, "LINK_TYPE=%s\n",
- nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
- if (link->ce_mask & LINK_ATTR_ADDR)
- dp_dump_line(p, line++, "LINK_ADDRESS=%s\n",
- nl_addr2str(link->l_addr, buf, sizeof(buf)));
- dp_dump_line(p, line++, "LINK_MTU=%u\n", link->l_mtu);
- dp_dump_line(p, line++, "LINK_TXQUEUELEN=%u\n", link->l_txqlen);
- dp_dump_line(p, line++, "LINK_WEIGHT=%u\n", link->l_weight);
- rtnl_link_flags2str(link->l_flags & ~IFF_RUNNING, buf, sizeof(buf));
- if (buf[0])
- dp_dump_line(p, line++, "LINK_FLAGS=%s\n", buf);
- if (link->ce_mask & LINK_ATTR_QDISC)
- dp_dump_line(p, line++, "LINK_QDISC=%s\n", link->l_qdisc);
- if (link->ce_mask & LINK_ATTR_LINK) {
- struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
- dp_dump_line(p, line++, "LINK_LINK_IFINDEX=%d\n", link->l_link);
- if (ll) {
- dp_dump_line(p, line++, "LINK_LINK_IFNAME=%s\n",
- ll->l_name);
- rtnl_link_put(ll);
- }
- }
- if (link->ce_mask & LINK_ATTR_MASTER) {
- struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
- dp_dump_line(p, line++, "LINK_MASTER=%s\n",
- master ? master->l_name : "none");
- if (master)
- rtnl_link_put(master);
- }
- if (link->ce_mask & LINK_ATTR_BRD)
- dp_dump_line(p, line++, "LINK_BROADCAST=%s\n",
- nl_addr2str(link->l_bcast, buf, sizeof(buf)));
- if (link->ce_mask & LINK_ATTR_STATS) {
- for (i = 0; i <= RTNL_LINK_STATS_MAX; i++) {
- char *c = buf;
- sprintf(buf, "LINK_");
- rtnl_link_stat2str(i, buf + 5, sizeof(buf) - 5);
- while (*c) {
- *c = toupper(*c);
- c++;
- }
- dp_dump_line(p, line++,
- "%s=%" PRIu64 "\n", buf, link->l_stats[i]);
- }
- }
- if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_ENV])
- line = link->l_info_ops->io_dump[NL_DUMP_ENV](link, p, line);
- return line;
- }
- #if 0
- static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb)
- {
- struct rtnl_link *l = (struct rtnl_link *) a;
- struct nl_cache *c = dp_cache(a);
- int nevents = 0;
- if (l->l_change == ~0U) {
- if (l->ce_msgtype == RTM_NEWLINK)
- cb->le_register(l);
- else
- cb->le_unregister(l);
- return 1;
- }
- if (l->l_change & IFF_SLAVE) {
- if (l->l_flags & IFF_SLAVE) {
- struct rtnl_link *m = rtnl_link_get(c, l->l_master);
- cb->le_new_bonding(l, m);
- if (m)
- rtnl_link_put(m);
- } else
- cb->le_cancel_bonding(l);
- }
- #if 0
- if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
- dp_dump_line(p, line++, "link %s changed state to %s.\n",
- l->l_name, l->l_flags & IFF_UP ? "up" : "down");
- if (l->l_change & IFF_PROMISC) {
- dp_new_line(p, line++);
- dp_dump(p, "link %s %s promiscuous mode.\n",
- l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left");
- }
- if (line == 0)
- dp_dump_line(p, line++, "link %s sent unknown event.\n",
- l->l_name);
- #endif
- return nevents;
- }
- #endif
- static int link_compare(struct nl_object *_a, struct nl_object *_b,
- uint32_t attrs, int flags)
- {
- struct rtnl_link *a = (struct rtnl_link *) _a;
- struct rtnl_link *b = (struct rtnl_link *) _b;
- int diff = 0;
- #define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
- diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
- diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
- diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
- diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
- diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
- diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
- diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
- diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
- diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
- diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
- diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
- diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
- diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
- if (flags & LOOSE_FLAG_COMPARISON)
- diff |= LINK_DIFF(FLAGS,
- (a->l_flags ^ b->l_flags) & b->l_flag_mask);
- else
- diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
- #undef LINK_DIFF
- return diff;
- }
- static struct trans_tbl link_attrs[] = {
- __ADD(LINK_ATTR_MTU, mtu)
- __ADD(LINK_ATTR_LINK, link)
- __ADD(LINK_ATTR_TXQLEN, txqlen)
- __ADD(LINK_ATTR_WEIGHT, weight)
- __ADD(LINK_ATTR_MASTER, master)
- __ADD(LINK_ATTR_QDISC, qdisc)
- __ADD(LINK_ATTR_MAP, map)
- __ADD(LINK_ATTR_ADDR, address)
- __ADD(LINK_ATTR_BRD, broadcast)
- __ADD(LINK_ATTR_FLAGS, flags)
- __ADD(LINK_ATTR_IFNAME, name)
- __ADD(LINK_ATTR_IFINDEX, ifindex)
- __ADD(LINK_ATTR_FAMILY, family)
- __ADD(LINK_ATTR_ARPTYPE, arptype)
- __ADD(LINK_ATTR_STATS, stats)
- __ADD(LINK_ATTR_CHANGE, change)
- __ADD(LINK_ATTR_OPERSTATE, operstate)
- __ADD(LINK_ATTR_LINKMODE, linkmode)
- };
- static char *link_attrs2str(int attrs, char *buf, size_t len)
- {
- return __flags2str(attrs, buf, len, link_attrs,
- ARRAY_SIZE(link_attrs));
- }
- /**
- * @name Allocation/Freeing
- * @{
- */
- struct rtnl_link *rtnl_link_alloc(void)
- {
- return (struct rtnl_link *) nl_object_alloc(&link_obj_ops);
- }
- void rtnl_link_put(struct rtnl_link *link)
- {
- nl_object_put((struct nl_object *) link);
- }
- /** @} */
- /**
- * @name Cache Management
- * @{
- */
- /**
- * Allocate link cache and fill in all configured links.
- * @arg handle Netlink handle.
- *
- * Allocates a new link cache, initializes it properly and updates it
- * to include all links currently configured in the kernel.
- *
- * @note Free the memory after usage.
- * @return Newly allocated cache or NULL if an error occured.
- */
- struct nl_cache *rtnl_link_alloc_cache(struct nl_handle *handle)
- {
- struct nl_cache * cache;
-
- cache = nl_cache_alloc(&rtnl_link_ops);
- if (cache == NULL)
- return NULL;
-
- if (handle && nl_cache_refill(handle, cache) < 0) {
- nl_cache_free(cache);
- return NULL;
- }
- return cache;
- }
- /**
- * Look up link by interface index in the provided cache
- * @arg cache link cache
- * @arg ifindex link interface index
- *
- * The caller owns a reference on the returned object and
- * must give the object back via rtnl_link_put().
- *
- * @return pointer to link inside the cache or NULL if no match was found.
- */
- struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex)
- {
- struct rtnl_link *link;
- if (cache->c_ops != &rtnl_link_ops)
- return NULL;
- nl_list_for_each_entry(link, &cache->c_items, ce_list) {
- if (link->l_index == ifindex) {
- nl_object_get((struct nl_object *) link);
- return link;
- }
- }
- return NULL;
- }
- /**
- * Look up link by link name in the provided cache
- * @arg cache link cache
- * @arg name link name
- *
- * The caller owns a reference on the returned object and
- * must give the object back via rtnl_link_put().
- *
- * @return pointer to link inside the cache or NULL if no match was found.
- */
- struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache,
- const char *name)
- {
- struct rtnl_link *link;
- if (cache->c_ops != &rtnl_link_ops)
- return NULL;
- nl_list_for_each_entry(link, &cache->c_items, ce_list) {
- if (!strcmp(name, link->l_name)) {
- nl_object_get((struct nl_object *) link);
- return link;
- }
- }
- return NULL;
- }
- /** @} */
- /**
- * @name Link Modifications
- * @{
- */
- /**
- * Builds a netlink change request message to change link attributes
- * @arg old link to be changed
- * @arg tmpl template with requested changes
- * @arg flags additional netlink message flags
- *
- * Builds a new netlink message requesting a change of link attributes.
- * The netlink message header isn't fully equipped with all relevant
- * fields and must be sent out via nl_send_auto_complete() or
- * supplemented as needed.
- * \a old must point to a link currently configured in the kernel
- * and \a tmpl must contain the attributes to be changed set via
- * \c rtnl_link_set_* functions.
- *
- * @return New netlink message
- * @note Not all attributes can be changed, see
- * \ref link_changeable "Changeable Attributes" for more details.
- */
- struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old,
- struct rtnl_link *tmpl,
- int flags)
- {
- struct nl_msg *msg;
- struct ifinfomsg ifi = {
- .ifi_family = old->l_family,
- .ifi_index = old->l_index,
- };
- if (tmpl->ce_mask & LINK_ATTR_FLAGS) {
- ifi.ifi_flags = old->l_flags & ~tmpl->l_flag_mask;
- ifi.ifi_flags |= tmpl->l_flags;
- }
- msg = nlmsg_alloc_simple(RTM_SETLINK, flags);
- if (!msg)
- goto nla_put_failure;
- if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
- goto nla_put_failure;
- if (tmpl->ce_mask & LINK_ATTR_ADDR)
- NLA_PUT_ADDR(msg, IFLA_ADDRESS, tmpl->l_addr);
- if (tmpl->ce_mask & LINK_ATTR_BRD)
- NLA_PUT_ADDR(msg, IFLA_BROADCAST, tmpl->l_bcast);
- if (tmpl->ce_mask & LINK_ATTR_MTU)
- NLA_PUT_U32(msg, IFLA_MTU, tmpl->l_mtu);
- if (tmpl->ce_mask & LINK_ATTR_TXQLEN)
- NLA_PUT_U32(msg, IFLA_TXQLEN, tmpl->l_txqlen);
- if (tmpl->ce_mask & LINK_ATTR_WEIGHT)
- NLA_PUT_U32(msg, IFLA_WEIGHT, tmpl->l_weight);
- if (tmpl->ce_mask & LINK_ATTR_IFNAME)
- NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name);
- if (tmpl->ce_mask & LINK_ATTR_OPERSTATE)
- NLA_PUT_U8(msg, IFLA_OPERSTATE, tmpl->l_operstate);
- if (tmpl->ce_mask & LINK_ATTR_LINKMODE)
- NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode);
- if ((tmpl->ce_mask & LINK_ATTR_LINKINFO) && tmpl->l_info_ops &&
- tmpl->l_info_ops->io_put_attrs) {
- struct nlattr *info;
- if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
- goto nla_put_failure;
- NLA_PUT_STRING(msg, IFLA_INFO_KIND, tmpl->l_info_ops->io_name);
- if (tmpl->l_info_ops->io_put_attrs(msg, tmpl) < 0)
- goto nla_put_failure;
- nla_nest_end(msg, info);
- }
- return msg;
- nla_put_failure:
- nlmsg_free(msg);
- return NULL;
- }
- /**
- * Change link attributes
- * @arg handle netlink handle
- * @arg old link to be changed
- * @arg tmpl template with requested changes
- * @arg flags additional netlink message flags
- *
- * Builds a new netlink message by calling rtnl_link_build_change_request(),
- * sends the request to the kernel and waits for the next ACK to be
- * received, i.e. blocks until the request has been processed.
- *
- * @return 0 on success or a negative error code
- * @note Not all attributes can be changed, see
- * \ref link_changeable "Changeable Attributes" for more details.
- */
- int rtnl_link_change(struct nl_handle *handle, struct rtnl_link *old,
- struct rtnl_link *tmpl, int flags)
- {
- int err;
- struct nl_msg *msg;
-
- msg = rtnl_link_build_change_request(old, tmpl, flags);
- if (!msg)
- return nl_errno(ENOMEM);
-
- err = nl_send_auto_complete(handle, msg);
- nlmsg_free(msg);
- if (err < 0)
- return err;
- return nl_wait_for_ack(handle);
- }
- /** @} */
- /**
- * @name Name <-> Index Translations
- * @{
- */
- /**
- * Translate an interface index to the corresponding link name
- * @arg cache link cache
- * @arg ifindex link interface index
- * @arg dst destination buffer
- * @arg len length of destination buffer
- *
- * Translates the specified interface index to the corresponding
- * link name and stores the name in the destination buffer.
- *
- * @return link name or NULL if no match was found.
- */
- char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst,
- size_t len)
- {
- struct rtnl_link *link = rtnl_link_get(cache, ifindex);
- if (link) {
- strncpy(dst, link->l_name, len - 1);
- rtnl_link_put(link);
- return dst;
- }
- return NULL;
- }
- /**
- * Translate a link name to the corresponding interface index
- * @arg cache link cache
- * @arg name link name
- *
- * @return interface index or RTNL_LINK_NOT_FOUND if no match was found.
- */
- int rtnl_link_name2i(struct nl_cache *cache, const char *name)
- {
- int ifindex = RTNL_LINK_NOT_FOUND;
- struct rtnl_link *link;
-
- link = rtnl_link_get_by_name(cache, name);
- if (link) {
- ifindex = link->l_index;
- rtnl_link_put(link);
- }
- return ifindex;
- }
- /** @} */
- /**
- * @name Link Flags Translations
- * @{
- */
- static struct trans_tbl link_flags[] = {
- __ADD(IFF_LOOPBACK, loopback)
- __ADD(IFF_BROADCAST, broadcast)
- __ADD(IFF_POINTOPOINT, pointopoint)
- __ADD(IFF_MULTICAST, multicast)
- __ADD(IFF_NOARP, noarp)
- __ADD(IFF_ALLMULTI, allmulti)
- __ADD(IFF_PROMISC, promisc)
- __ADD(IFF_MASTER, master)
- __ADD(IFF_SLAVE, slave)
- __ADD(IFF_DEBUG, debug)
- __ADD(IFF_DYNAMIC, dynamic)
- __ADD(IFF_AUTOMEDIA, automedia)
- __ADD(IFF_PORTSEL, portsel)
- __ADD(IFF_NOTRAILERS, notrailers)
- __ADD(IFF_UP, up)
- __ADD(IFF_RUNNING, running)
- __ADD(IFF_LOWER_UP, lowerup)
- __ADD(IFF_DORMANT, dormant)
- __ADD(IFF_ECHO, echo)
- };
- char * rtnl_link_flags2str(int flags, char *buf, size_t len)
- {
- return __flags2str(flags, buf, len, link_flags,
- ARRAY_SIZE(link_flags));
- }
- int rtnl_link_str2flags(const char *name)
- {
- return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
- }
- /** @} */
- /**
- * @name Link Statistics Translations
- * @{
- */
- static struct trans_tbl link_stats[] = {
- __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
- __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
- __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
- __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
- __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
- __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
- __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
- __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
- __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
- __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
- __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
- __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
- __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
- __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
- __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
- __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
- __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
- __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
- __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
- __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
- __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
- __ADD(RTNL_LINK_TX_COLLISIONS, tx_collision)
- __ADD(RTNL_LINK_MULTICAST, multicast)
- };
- char *rtnl_link_stat2str(int st, char *buf, size_t len)
- {
- return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
- }
- int rtnl_link_str2stat(const char *name)
- {
- return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
- }
- /** @} */
- /**
- * @name Link Operstate Translations
- * @{
- */
- static struct trans_tbl link_operstates[] = {
- __ADD(IF_OPER_UNKNOWN, unknown)
- __ADD(IF_OPER_NOTPRESENT, notpresent)
- __ADD(IF_OPER_DOWN, down)
- __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
- __ADD(IF_OPER_TESTING, testing)
- __ADD(IF_OPER_DORMANT, dormant)
- __ADD(IF_OPER_UP, up)
- };
- char *rtnl_link_operstate2str(int st, char *buf, size_t len)
- {
- return __type2str(st, buf, len, link_operstates,
- ARRAY_SIZE(link_operstates));
- }
- int rtnl_link_str2operstate(const char *name)
- {
- return __str2type(name, link_operstates,
- ARRAY_SIZE(link_operstates));
- }
- /** @} */
- /**
- * @name Link Mode Translations
- * @{
- */
- static struct trans_tbl link_modes[] = {
- __ADD(IF_LINK_MODE_DEFAULT, default)
- __ADD(IF_LINK_MODE_DORMANT, dormant)
- };
- char *rtnl_link_mode2str(int st, char *buf, size_t len)
- {
- return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
- }
- int rtnl_link_str2mode(const char *name)
- {
- return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
- }
- /** @} */
- /**
- * @name Attributes
- * @{
- */
- void rtnl_link_set_qdisc(struct rtnl_link *link, const char *qdisc)
- {
- strncpy(link->l_qdisc, qdisc, sizeof(link->l_qdisc) - 1);
- link->ce_mask |= LINK_ATTR_QDISC;
- }
- char *rtnl_link_get_qdisc(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_QDISC)
- return link->l_qdisc;
- else
- return NULL;
- }
- void rtnl_link_set_name(struct rtnl_link *link, const char *name)
- {
- strncpy(link->l_name, name, sizeof(link->l_name) - 1);
- link->ce_mask |= LINK_ATTR_IFNAME;
- }
- char *rtnl_link_get_name(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_IFNAME)
- return link->l_name;
- else
- return NULL;
- }
- static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
- struct nl_addr *new, int flag)
- {
- if (*pos)
- nl_addr_put(*pos);
- nl_addr_get(new);
- *pos = new;
- link->ce_mask |= flag;
- }
- void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
- {
- __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
- }
- struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_ADDR)
- return link->l_addr;
- else
- return NULL;
- }
- void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *brd)
- {
- __assign_addr(link, &link->l_bcast, brd, LINK_ATTR_BRD);
- }
- struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_BRD)
- return link->l_bcast;
- else
- return NULL;
- }
- void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
- {
- link->l_flag_mask |= flags;
- link->l_flags |= flags;
- link->ce_mask |= LINK_ATTR_FLAGS;
- }
- void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
- {
- link->l_flag_mask |= flags;
- link->l_flags &= ~flags;
- link->ce_mask |= LINK_ATTR_FLAGS;
- }
- unsigned int rtnl_link_get_flags(struct rtnl_link *link)
- {
- return link->l_flags;
- }
- void rtnl_link_set_family(struct rtnl_link *link, int family)
- {
- link->l_family = family;
- link->ce_mask |= LINK_ATTR_FAMILY;
- }
- int rtnl_link_get_family(struct rtnl_link *link)
- {
- if (link->l_family & LINK_ATTR_FAMILY)
- return link->l_family;
- else
- return AF_UNSPEC;
- }
- void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype)
- {
- link->l_arptype = arptype;
- }
- unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
- {
- return link->l_arptype;
- }
- void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
- {
- link->l_index = ifindex;
- link->ce_mask |= LINK_ATTR_IFINDEX;
- }
- int rtnl_link_get_ifindex(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_IFINDEX)
- return link->l_index;
- else
- return RTNL_LINK_NOT_FOUND;
- }
- void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
- {
- link->l_mtu = mtu;
- link->ce_mask |= LINK_ATTR_MTU;
- }
- unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_MTU)
- return link->l_mtu;
- else
- return 0;
- }
- void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
- {
- link->l_txqlen = txqlen;
- link->ce_mask |= LINK_ATTR_TXQLEN;
- }
- unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_TXQLEN)
- return link->l_txqlen;
- else
- return UINT_MAX;
- }
- void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
- {
- link->l_weight = weight;
- link->ce_mask |= LINK_ATTR_WEIGHT;
- }
- unsigned int rtnl_link_get_weight(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_WEIGHT)
- return link->l_weight;
- else
- return UINT_MAX;
- }
- void rtnl_link_set_link(struct rtnl_link *link, int ifindex)
- {
- link->l_link = ifindex;
- link->ce_mask |= LINK_ATTR_LINK;
- }
- int rtnl_link_get_link(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_LINK)
- return link->l_link;
- else
- return RTNL_LINK_NOT_FOUND;
- }
- void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
- {
- link->l_master = ifindex;
- link->ce_mask |= LINK_ATTR_MASTER;
- }
- int rtnl_link_get_master(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_MASTER)
- return link->l_master;
- else
- return RTNL_LINK_NOT_FOUND;
- }
- void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t operstate)
- {
- link->l_operstate = operstate;
- link->ce_mask |= LINK_ATTR_OPERSTATE;
- }
- uint8_t rtnl_link_get_operstate(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_OPERSTATE)
- return link->l_operstate;
- else
- return IF_OPER_UNKNOWN;
- }
- void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t linkmode)
- {
- link->l_linkmode = linkmode;
- link->ce_mask |= LINK_ATTR_LINKMODE;
- }
- uint8_t rtnl_link_get_linkmode(struct rtnl_link *link)
- {
- if (link->ce_mask & LINK_ATTR_LINKMODE)
- return link->l_linkmode;
- else
- return IF_LINK_MODE_DEFAULT;
- }
- uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
- {
- if (id < 0 || id > RTNL_LINK_STATS_MAX)
- return 0;
- return link->l_stats[id];
- }
- /**
- * Specify the info type of a link
- * @arg link link object
- * @arg type info type
- *
- * Looks up the info type and prepares the link to store info type
- * specific attributes. If an info type has been assigned already
- * it will be released with all changes lost.
- *
- * @return 0 on success or a negative errror code.
- */
- int rtnl_link_set_info_type(struct rtnl_link *link, const char *type)
- {
- struct rtnl_link_info_ops *io;
- int err;
- if ((io = rtnl_link_info_ops_lookup(type)) == NULL)
- return nl_error(ENOENT, "No such link info type exists");
- if (link->l_info_ops)
- release_link_info(link);
- if ((err = io->io_alloc(link)) < 0)
- return err;
- link->l_info_ops = io;
- return 0;
- }
- /**
- * Return info type of a link
- * @arg link link object
- *
- * @note The returned pointer is only valid as long as the link exists
- * @return Info type name or NULL if unknown.
- */
- char *rtnl_link_get_info_type(struct rtnl_link *link)
- {
- if (link->l_info_ops)
- return link->l_info_ops->io_name;
- else
- return NULL;
- }
- /** @} */
- static struct nl_object_ops link_obj_ops = {
- .oo_name = "route/link",
- .oo_size = sizeof(struct rtnl_link),
- .oo_free_data = link_free_data,
- .oo_clone = link_clone,
- .oo_dump[NL_DUMP_BRIEF] = link_dump_brief,
- .oo_dump[NL_DUMP_FULL] = link_dump_full,
- .oo_dump[NL_DUMP_STATS] = link_dump_stats,
- .oo_dump[NL_DUMP_XML] = link_dump_xml,
- .oo_dump[NL_DUMP_ENV] = link_dump_env,
- .oo_compare = link_compare,
- .oo_attrs2str = link_attrs2str,
- .oo_id_attrs = LINK_ATTR_IFINDEX,
- };
- static struct nl_af_group link_groups[] = {
- { AF_UNSPEC, RTNLGRP_LINK },
- { END_OF_GROUP_LIST },
- };
- static struct nl_cache_ops rtnl_link_ops = {
- .co_name = "route/link",
- .co_hdrsize = sizeof(struct ifinfomsg),
- .co_msgtypes = {
- { RTM_NEWLINK, NL_ACT_NEW, "new" },
- { RTM_DELLINK, NL_ACT_DEL, "del" },
- { RTM_GETLINK, NL_ACT_GET, "get" },
- END_OF_MSGTYPES_LIST,
- },
- .co_protocol = NETLINK_ROUTE,
- .co_groups = link_groups,
- .co_request_update = link_request_update,
- .co_msg_parser = link_msg_parser,
- .co_obj_ops = &link_obj_ops,
- };
- static void __init link_init(void)
- {
- nl_cache_mngt_register(&rtnl_link_ops);
- }
- static void __exit link_exit(void)
- {
- nl_cache_mngt_unregister(&rtnl_link_ops);
- }
- /** @} */
|