summaryrefslogtreecommitdiffstats
path: root/lib/route/link.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2010-11-11 21:26:11 (GMT)
committerThomas Graf <tgraf@suug.ch>2010-11-11 21:26:11 (GMT)
commit7ff4deeb56300a83a1bee091d3664fd588ac7837 (patch)
treedda1f357ef9b91e9fe1bef82229f1aeb3215579a /lib/route/link.c
parent2847cf081b88678a2bb780c59a2678131d47c11d (diff)
downloadlibnl-7ff4deeb56300a83a1bee091d3664fd588ac7837.zip
libnl-7ff4deeb56300a83a1bee091d3664fd588ac7837.tar.gz
libnl-7ff4deeb56300a83a1bee091d3664fd588ac7837.tar.bz2
Extend rtnl_link_alloc_cache() to support address families
Adds a family argument which allows to request link dumps for a certain address family. This allows to f.e. dump ipv6 specific statistics and data. nl-link-list --family inet6
Diffstat (limited to 'lib/route/link.c')
-rw-r--r--lib/route/link.c89
1 files changed, 82 insertions, 7 deletions
diff --git a/lib/route/link.c b/lib/route/link.c
index 7aed708..d54082a 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -354,7 +354,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct ifinfomsg *ifi;
struct nlattr *tb[IFLA_MAX+1];
struct rtnl_link_af_ops *af_ops = NULL;
- int err;
+ int err, family;
link = rtnl_link_alloc();
if (link == NULL) {
@@ -368,7 +368,7 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
return -NLE_MSG_TOOSHORT;
ifi = nlmsg_data(n);
- link->l_family = ifi->ifi_family;
+ link->l_family = family = ifi->ifi_family;
link->l_arptype = ifi->ifi_type;
link->l_index = ifi->ifi_index;
link->l_flags = ifi->ifi_flags;
@@ -377,7 +377,15 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
- if ((af_ops = rtnl_link_af_ops_lookup(ifi->ifi_family))) {
+ if ((af_ops = rtnl_link_af_ops_lookup(family))) {
+ if (af_ops->ao_alloc) {
+ link->l_af_data[family] = af_ops->ao_alloc(link);
+ if (!link->l_af_data[family]) {
+ err = -NLE_NOMEM;
+ goto errout;
+ }
+ }
+
if (af_ops->ao_protinfo_policy) {
memcpy(&link_policy[IFLA_PROTINFO],
af_ops->ao_protinfo_policy,
@@ -589,7 +597,9 @@ errout:
static int link_request_update(struct nl_cache *cache, struct nl_sock *sk)
{
- return nl_rtgen_request(sk, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
+ int family = cache->c_iarg1;
+
+ return nl_rtgen_request(sk, RTM_GETLINK, family, NLM_F_DUMP);
}
static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p)
@@ -881,6 +891,7 @@ void rtnl_link_put(struct rtnl_link *link)
/**
* Allocate link cache and fill in all configured links.
* @arg sk Netlink socket.
+ * @arg family Link address family or AF_UNSPEC
* @arg result Pointer to store resulting cache.
*
* Allocates a new link cache, initializes it properly and updates it
@@ -888,9 +899,24 @@ void rtnl_link_put(struct rtnl_link *link)
*
* @return 0 on success or a negative error code.
*/
-int rtnl_link_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
+int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
{
- return nl_cache_alloc_and_fill(&rtnl_link_ops, sk, result);
+ struct nl_cache * cache;
+ int err;
+
+ cache = nl_cache_alloc(&rtnl_link_ops);
+ if (!cache)
+ return -NLE_NOMEM;
+
+ cache->c_iarg1 = family;
+
+ if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
+ nl_cache_free(cache);
+ return err;
+ }
+
+ *result = cache;
+ return 0;
}
/**
@@ -1202,6 +1228,36 @@ static struct trans_tbl link_stats[] = {
__ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
__ADD(RTNL_LINK_COLLISIONS, collisions)
__ADD(RTNL_LINK_MULTICAST, multicast)
+ __ADD(RTNL_LINK_INPKTS, InReceives)
+ __ADD(RTNL_LINK_INHDRERRORS, InHdrErrors)
+ __ADD(RTNL_LINK_INTOOBIGERRORS, InTooBigErrors)
+ __ADD(RTNL_LINK_INNOROUTES, InNoRoutes)
+ __ADD(RTNL_LINK_INADDRERRORS, InAddrErrors)
+ __ADD(RTNL_LINK_INUNKNOWNPROTOS, InUnknownProtos)
+ __ADD(RTNL_LINK_INTRUNCATEDPKTS, InTruncatedPkts)
+ __ADD(RTNL_LINK_INDISCARDS, InDiscards)
+ __ADD(RTNL_LINK_INDELIVERS, InDelivers)
+ __ADD(RTNL_LINK_OUTFORWDATAGRAMS, OutForwDatagrams)
+ __ADD(RTNL_LINK_OUTPKTS, OutRequests)
+ __ADD(RTNL_LINK_OUTDISCARDS, OutDiscards)
+ __ADD(RTNL_LINK_OUTNOROUTES, OutNoRoutes)
+ __ADD(RTNL_LINK_REASMTIMEOUT, ReasmTimeout)
+ __ADD(RTNL_LINK_REASMREQDS, ReasmReqds)
+ __ADD(RTNL_LINK_REASMOKS, ReasmOKs)
+ __ADD(RTNL_LINK_REASMFAILS, ReasmFails)
+ __ADD(RTNL_LINK_FRAGOKS, FragOKs)
+ __ADD(RTNL_LINK_FRAGFAILS, FragFails)
+ __ADD(RTNL_LINK_FRAGCREATES, FragCreates)
+ __ADD(RTNL_LINK_INMCASTPKTS, InMcastPkts)
+ __ADD(RTNL_LINK_OUTMCASTPKTS, OutMcastPkts)
+ __ADD(RTNL_LINK_INBCASTPKTS, InBcastPkts)
+ __ADD(RTNL_LINK_OUTBCASTPKTS, OutBcastPkts)
+ __ADD(RTNL_LINK_INOCTETS, InOctets)
+ __ADD(RTNL_LINK_OUTOCTETS, OutOctets)
+ __ADD(RTNL_LINK_INMCASTOCTETS, InMcastOctets)
+ __ADD(RTNL_LINK_OUTMCASTOCTETS, OutMcastOctets)
+ __ADD(RTNL_LINK_INBCASTOCTETS, InBcastOctets)
+ __ADD(RTNL_LINK_OUTBCASTOCTETS, OutBcastOctets)
};
char *rtnl_link_stat2str(int st, char *buf, size_t len)
@@ -1365,7 +1421,7 @@ void rtnl_link_set_family(struct rtnl_link *link, int family)
int rtnl_link_get_family(struct rtnl_link *link)
{
- if (link->l_family & LINK_ATTR_FAMILY)
+ if (link->ce_mask & LINK_ATTR_FAMILY)
return link->l_family;
else
return AF_UNSPEC;
@@ -1540,6 +1596,25 @@ uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
}
/**
+ * Set value of a link statistics counter
+ * @arg link Link object
+ * @arg id Counter ID
+ * @arg value New value
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_link_set_stat(struct rtnl_link *link, const unsigned int id,
+ const uint64_t value)
+{
+ if (id > RTNL_LINK_STATS_MAX)
+ return -NLE_INVAL;
+
+ link->l_stats[id] = value;
+
+ return 0;
+}
+
+/**
* Specify the info type of a link
* @arg link link object
* @arg type info type