* [PATCH 10/10 net-next] net: Enable ipv4 per interface statistics
From: igorm @ 2011-12-16 15:26 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Added argument of type net_device* to macros IP_*_STATS and ICMP_*_STATS
In most places that was trivial - just added net_device* from
which we've read net*.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
net/bridge/br_netfilter.c | 6 ++--
net/dccp/ipv4.c | 9 ++++---
net/ipv4/datagram.c | 2 +-
net/ipv4/icmp.c | 29 ++++++++++++++-----------
net/ipv4/inet_connection_sock.c | 8 +++++-
net/ipv4/ip_forward.c | 8 ++++--
net/ipv4/ip_fragment.c | 43 +++++++++++++++++++++-----------------
net/ipv4/ip_input.c | 33 +++++++++++++++--------------
net/ipv4/ip_output.c | 43 +++++++++++++++++++++-----------------
net/ipv4/ipmr.c | 6 +++-
net/ipv4/ping.c | 8 +++---
net/ipv4/raw.c | 4 +-
net/ipv4/route.c | 2 +-
net/ipv4/tcp_ipv4.c | 9 ++++---
net/ipv4/udp.c | 7 +++--
net/l2tp/l2tp_ip.c | 6 ++--
net/sctp/input.c | 4 +-
net/sctp/output.c | 2 +-
18 files changed, 127 insertions(+), 102 deletions(-)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 834dfab..a821217 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -255,13 +255,13 @@ static int br_parse_ip_options(struct sk_buff *skb)
len = ntohs(iph->tot_len);
if (skb->len < len) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
} else if (len < (iph->ihl*4))
goto inhdr_error;
if (pskb_trim_rcsum(skb, len)) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INDISCARDS);
goto drop;
}
@@ -286,7 +286,7 @@ static int br_parse_ip_options(struct sk_buff *skb)
return 0;
inhdr_error:
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INHDRERRORS);
drop:
return -1;
}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 1c67fe8..ca8a024 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -219,11 +219,12 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
struct sock *sk;
__u64 seq;
int err;
- struct net *net = dev_net(skb->dev);
+ struct net_device *dev = skb->dev;
+ struct net *net = dev_net(dev);
if (skb->len < offset + sizeof(*dh) ||
skb->len < offset + __dccp_basic_hdr_len(dh)) {
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
return;
}
@@ -231,7 +232,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
iph->daddr, dh->dccph_dport,
iph->saddr, dh->dccph_sport, inet_iif(skb));
if (sk == NULL) {
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
return;
}
@@ -488,7 +489,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) {
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
return NULL;
}
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 424fafb..ca1d0ba 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
if (err == -ENETUNREACH)
- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(sock_net(sk), NULL, IPSTATS_MIB_OUTNOROUTES);
goto out;
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index ab188ae..8a064db 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -264,10 +264,10 @@ out:
/*
* Maintain the counters used in the SNMP statistics for outgoing ICMP
*/
-void icmp_out_count(struct net *net, unsigned char type)
+void icmp_out_count(struct net_device *dev, unsigned char type)
{
- ICMPMSGOUT_INC_STATS(net, type);
- ICMP_INC_STATS(net, ICMP_MIB_OUTMSGS);
+ ICMPMSGOUT_INC_STATS(dev_net(dev), dev, type);
+ ICMP_INC_STATS(dev_net(dev), dev, ICMP_MIB_OUTMSGS);
}
/*
@@ -296,13 +296,14 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
{
struct sock *sk;
struct sk_buff *skb;
+ struct net_device *dev = (*rt)->dst.dev;
- sk = icmp_sk(dev_net((*rt)->dst.dev));
+ sk = icmp_sk(dev_net(dev));
if (ip_append_data(sk, fl4, icmp_glue_bits, icmp_param,
icmp_param->data_len+icmp_param->head_len,
icmp_param->head_len,
ipc, rt, MSG_DONTWAIT) < 0) {
- ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_OUTERRORS);
+ ICMP_INC_STATS_BH(sock_net(sk), dev, ICMP_MIB_OUTERRORS);
ip_flush_pending_frames(sk);
} else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
struct icmphdr *icmph = icmp_hdr(skb);
@@ -643,8 +644,9 @@ static void icmp_unreach(struct sk_buff *skb)
const struct net_protocol *ipprot;
u32 info = 0;
struct net *net;
+ struct net_device *dev = skb_dst(skb)->dev;
- net = dev_net(skb_dst(skb)->dev);
+ net = dev_net(dev);
/*
* Incomplete header ?
@@ -747,7 +749,7 @@ static void icmp_unreach(struct sk_buff *skb)
out:
return;
out_err:
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
goto out;
}
@@ -796,7 +798,7 @@ static void icmp_redirect(struct sk_buff *skb)
out:
return;
out_err:
- ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(dev_net(skb->dev), skb->dev, ICMP_MIB_INERRORS);
goto out;
}
@@ -867,7 +869,7 @@ static void icmp_timestamp(struct sk_buff *skb)
out:
return;
out_err:
- ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), skb_dst(skb)->dev, ICMP_MIB_INERRORS);
goto out;
}
@@ -963,7 +965,8 @@ int icmp_rcv(struct sk_buff *skb)
{
struct icmphdr *icmph;
struct rtable *rt = skb_rtable(skb);
- struct net *net = dev_net(rt->dst.dev);
+ struct net_device *dev = rt->dst.dev;
+ struct net *net = dev_net(dev);
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
struct sec_path *sp = skb_sec_path(skb);
@@ -985,7 +988,7 @@ int icmp_rcv(struct sk_buff *skb)
skb_set_network_header(skb, nh);
}
- ICMP_INC_STATS_BH(net, ICMP_MIB_INMSGS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INMSGS);
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
@@ -1003,7 +1006,7 @@ int icmp_rcv(struct sk_buff *skb)
icmph = icmp_hdr(skb);
- ICMPMSGIN_INC_STATS_BH(net, icmph->type);
+ ICMPMSGIN_INC_STATS_BH(net, dev, icmph->type);
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
@@ -1044,7 +1047,7 @@ drop:
kfree_skb(skb);
return 0;
error:
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
goto drop;
}
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 2e4e244..f527d70 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -372,9 +372,11 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
return &rt->dst;
route_err:
+ IP_INC_STATS_BH(net, rt->dst.dev, IPSTATS_MIB_OUTNOROUTES);
ip_rt_put(rt);
+ return NULL;
no_route:
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
return NULL;
}
EXPORT_SYMBOL_GPL(inet_csk_route_req);
@@ -405,9 +407,11 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
return &rt->dst;
route_err:
+ IP_INC_STATS_BH(net, rt->dst.dev, IPSTATS_MIB_OUTNOROUTES);
ip_rt_put(rt);
+ return NULL;
no_route:
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
return NULL;
}
EXPORT_SYMBOL_GPL(inet_csk_route_child_sock);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 29a07b6..f8ab57e 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -43,7 +43,8 @@ static int ip_forward_finish(struct sk_buff *skb)
{
struct ip_options * opt = &(IPCB(skb)->opt);
- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
+ IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), skb_dst(skb)->dev,
+ IPSTATS_MIB_OUTFORWDATAGRAMS);
if (unlikely(opt->optlen))
ip_forward_options(skb);
@@ -89,7 +90,7 @@ int ip_forward(struct sk_buff *skb)
if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
(ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
- IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
+ IP_INC_STATS(dev_net(rt->dst.dev), rt->dst.dev, IPSTATS_MIB_FRAGFAILS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(dst_mtu(&rt->dst)));
goto drop;
@@ -124,7 +125,8 @@ sr_failed:
too_many_hops:
/* Tell the sender its packet died... */
- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_INHDRERRORS);
+ IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), skb_dst(skb)->dev,
+ IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
kfree_skb(skb);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index fdaabf2..9aa00e1 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -209,13 +209,14 @@ static void ipq_kill(struct ipq *ipq)
/* Memory limiting on fragments. Evictor trashes the oldest
* fragment queue until we are back under the threshold.
*/
-static void ip_evictor(struct net *net)
+static void ip_evictor(struct net_device *dev)
{
int evicted;
+ struct net *net = dev_net(dev);
evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags);
if (evicted)
- IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted);
+ IP_ADD_STATS_BH(net, dev, IPSTATS_MIB_REASMFAILS, evicted);
}
/*
@@ -225,6 +226,7 @@ static void ip_expire(unsigned long arg)
{
struct ipq *qp;
struct net *net;
+ struct net_device *dev;
qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
net = container_of(qp->q.net, struct net, ipv4.frags);
@@ -235,19 +237,18 @@ static void ip_expire(unsigned long arg)
goto out;
ipq_kill(qp);
+
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(net, qp->iif);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMTIMEOUT);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMFAILS);
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT);
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
-
- if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
+ if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments && dev) {
struct sk_buff *head = qp->q.fragments;
const struct iphdr *iph;
int err;
- rcu_read_lock();
- head->dev = dev_get_by_index_rcu(net, qp->iif);
- if (!head->dev)
- goto out_rcu_unlock;
+ head->dev = dev;
/* skb dst is stale, drop it, and perform route lookup again */
skb_dst_drop(head);
@@ -269,9 +270,9 @@ static void ip_expire(unsigned long arg)
/* Send an ICMP "Fragment Reassembly Timeout" message. */
icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
-out_rcu_unlock:
- rcu_read_unlock();
}
+out_rcu_unlock:
+ rcu_read_unlock();
out:
spin_unlock(&qp->q.lock);
ipq_put(qp);
@@ -325,7 +326,10 @@ static inline int ip_frag_too_far(struct ipq *qp)
struct net *net;
net = container_of(qp->q.net, struct net, ipv4.frags);
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
+ rcu_read_lock();
+ IP_INC_STATS_BH(net, dev_get_by_index_rcu(net, qp->iif),
+ IPSTATS_MIB_REASMFAILS);
+ rcu_read_unlock();
}
return rc;
@@ -631,7 +635,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
iph->frag_off = 0;
iph->tot_len = htons(len);
iph->tos |= ecn;
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMOKS);
qp->q.fragments = NULL;
qp->q.fragments_tail = NULL;
return 0;
@@ -646,7 +650,7 @@ out_oversize:
printk(KERN_INFO "Oversized IP packet from %pI4.\n",
&qp->saddr);
out_fail:
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMFAILS);
return err;
}
@@ -655,13 +659,14 @@ int ip_defrag(struct sk_buff *skb, u32 user)
{
struct ipq *qp;
struct net *net;
+ struct net_device *dev = skb->dev ? skb->dev : skb_dst(skb)->dev;
- net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
+ net = dev_net(dev);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMREQDS);
/* Start by cleaning up the memory. */
if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
- ip_evictor(net);
+ ip_evictor(dev);
/* Lookup (or create) queue header */
if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
@@ -676,7 +681,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
return ret;
}
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_REASMFAILS);
kfree_skb(skb);
return -ENOMEM;
}
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 073a9b0..53f5ba0 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -187,8 +187,9 @@ int ip_call_ra_chain(struct sk_buff *skb)
static int ip_local_deliver_finish(struct sk_buff *skb)
{
- struct net *net = dev_net(skb->dev);
-
+ struct net_device *dev = skb->dev;
+ struct net *net = dev_net(dev);
+
__skb_pull(skb, ip_hdrlen(skb));
/* Point into the IP datagram, just past the header. */
@@ -228,16 +229,16 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
protocol = -ret;
goto resubmit;
}
- IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_INDELIVERS);
} else {
if (!raw) {
if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_INUNKNOWNPROTOS);
icmp_send(skb, ICMP_DEST_UNREACH,
ICMP_PROT_UNREACH, 0);
}
} else
- IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
+ IP_INC_STATS_BH(net, dev, IPSTATS_MIB_INDELIVERS);
kfree_skb(skb);
}
}
@@ -279,7 +280,7 @@ static inline int ip_rcv_options(struct sk_buff *skb)
--ANK (980813)
*/
if (skb_cow(skb, skb_headroom(skb))) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INDISCARDS);
goto drop;
}
@@ -288,7 +289,7 @@ static inline int ip_rcv_options(struct sk_buff *skb)
opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
if (ip_options_compile(dev_net(dev), opt, skb)) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INHDRERRORS);
goto drop;
}
@@ -328,10 +329,10 @@ static int ip_rcv_finish(struct sk_buff *skb)
iph->tos, skb->dev);
if (unlikely(err)) {
if (err == -EHOSTUNREACH)
- IP_INC_STATS_BH(dev_net(skb->dev),
+ IP_INC_STATS_BH(dev_net(skb->dev), skb->dev,
IPSTATS_MIB_INADDRERRORS);
else if (err == -ENETUNREACH)
- IP_INC_STATS_BH(dev_net(skb->dev),
+ IP_INC_STATS_BH(dev_net(skb->dev), skb->dev,
IPSTATS_MIB_INNOROUTES);
else if (err == -EXDEV)
NET_INC_STATS_BH(dev_net(skb->dev),
@@ -356,10 +357,10 @@ static int ip_rcv_finish(struct sk_buff *skb)
rt = skb_rtable(skb);
if (rt->rt_type == RTN_MULTICAST) {
- IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INMCAST,
+ IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), rt->dst.dev, IPSTATS_MIB_INMCAST,
skb->len);
} else if (rt->rt_type == RTN_BROADCAST)
- IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INBCAST,
+ IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), rt->dst.dev, IPSTATS_MIB_INBCAST,
skb->len);
return dst_input(skb);
@@ -384,10 +385,10 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
goto drop;
- IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
+ IP_UPD_PO_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_IN, skb->len);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INDISCARDS);
goto out;
}
@@ -420,7 +421,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
len = ntohs(iph->tot_len);
if (skb->len < len) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
} else if (len < (iph->ihl*4))
goto inhdr_error;
@@ -430,7 +431,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
* Note this now means skb->len holds ntohs(iph->tot_len).
*/
if (pskb_trim_rcsum(skb, len)) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INDISCARDS);
goto drop;
}
@@ -444,7 +445,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
ip_rcv_finish);
inhdr_error:
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+ IP_INC_STATS_BH(dev_net(dev), dev, IPSTATS_MIB_INHDRERRORS);
drop:
kfree_skb(skb);
out:
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index ff302bd..994bbb5 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -186,9 +186,9 @@ static inline int ip_finish_output2(struct sk_buff *skb)
struct neighbour *neigh;
if (rt->rt_type == RTN_MULTICAST) {
- IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
+ IP_UPD_PO_STATS(dev_net(dev), dev, IPSTATS_MIB_OUTMCAST, skb->len);
} else if (rt->rt_type == RTN_BROADCAST)
- IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len);
+ IP_UPD_PO_STATS(dev_net(dev), dev, IPSTATS_MIB_OUTBCAST, skb->len);
/* Be paranoid, rather than too clever. */
if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
@@ -253,7 +253,7 @@ int ip_mc_output(struct sk_buff *skb)
/*
* If the indicated interface is up and running, send the packet.
*/
- IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+ IP_UPD_PO_STATS(dev_net(dev), dev, IPSTATS_MIB_OUT, skb->len);
skb->dev = dev;
skb->protocol = htons(ETH_P_IP);
@@ -309,7 +309,7 @@ int ip_output(struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
- IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+ IP_UPD_PO_STATS(dev_net(dev), dev, IPSTATS_MIB_OUT, skb->len);
skb->dev = dev;
skb->protocol = htons(ETH_P_IP);
@@ -375,7 +375,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if);
if (IS_ERR(rt))
- goto no_route;
+ goto no_route_no_dev;
sk_setup_caps(sk, &rt->dst);
}
skb_dst_set_noref(skb, &rt->dst);
@@ -414,11 +414,16 @@ packet_routed:
rcu_read_unlock();
return res;
-no_route:
+out_err:
rcu_read_unlock();
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
return -EHOSTUNREACH;
+no_route_no_dev:
+ IP_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_OUTNOROUTES);
+ goto out_err;
+no_route:
+ IP_INC_STATS(sock_net(sk), rt->dst.dev, IPSTATS_MIB_OUTNOROUTES);
+ goto out_err;
}
EXPORT_SYMBOL(ip_queue_xmit);
@@ -478,7 +483,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
iph = ip_hdr(skb);
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGFAILS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(ip_skb_dst_mtu(skb)));
kfree_skb(skb);
@@ -570,7 +575,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
err = output(skb);
if (!err)
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGCREATES);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGCREATES);
if (err || !frag)
break;
@@ -580,7 +585,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
}
if (err == 0) {
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGOKS);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGOKS);
return 0;
}
@@ -589,7 +594,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
kfree_skb(frag);
frag = skb;
}
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGFAILS);
return err;
slow_path_clean:
@@ -708,15 +713,15 @@ slow_path:
if (err)
goto fail;
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGCREATES);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGCREATES);
}
kfree_skb(skb);
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGOKS);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGOKS);
return err;
fail:
kfree_skb(skb);
- IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+ IP_INC_STATS(dev_net(dev), dev, IPSTATS_MIB_FRAGFAILS);
return err;
}
EXPORT_SYMBOL(ip_fragment);
@@ -1049,7 +1054,7 @@ alloc_new_skb:
error:
cork->length -= length;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
+ IP_INC_STATS(sock_net(sk), rt->dst.dev, IPSTATS_MIB_OUTDISCARDS);
return err;
}
@@ -1270,7 +1275,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
error:
cork->length -= size;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
+ IP_INC_STATS(sock_net(sk), rt->dst.dev, IPSTATS_MIB_OUTDISCARDS);
return err;
}
@@ -1295,7 +1300,6 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
struct sk_buff *skb, *tmp_skb;
struct sk_buff **tail_skb;
struct inet_sock *inet = inet_sk(sk);
- struct net *net = sock_net(sk);
struct ip_options *opt = NULL;
struct rtable *rt = (struct rtable *)cork->dst;
struct iphdr *iph;
@@ -1368,7 +1372,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
skb_dst_set(skb, &rt->dst);
if (iph->protocol == IPPROTO_ICMP)
- icmp_out_count(net, ((struct icmphdr *)
+ icmp_out_count(rt->dst.dev, ((struct icmphdr *)
skb_transport_header(skb))->type);
ip_cork_release(cork);
@@ -1379,6 +1383,7 @@ out:
int ip_send_skb(struct sk_buff *skb)
{
struct net *net = sock_net(skb->sk);
+ struct net_device *dev = skb_dst(skb)->dev;
int err;
err = ip_local_out(skb);
@@ -1386,7 +1391,7 @@ int ip_send_skb(struct sk_buff *skb)
if (err > 0)
err = net_xmit_errno(err);
if (err)
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
+ IP_INC_STATS(net, dev, IPSTATS_MIB_OUTDISCARDS);
}
return err;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 8e54490..0aaa704 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1575,7 +1575,8 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
{
struct ip_options *opt = &(IPCB(skb)->opt);
- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
+ IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev),
+ skb_dst(skb)->dev, IPSTATS_MIB_OUTFORWDATAGRAMS);
if (unlikely(opt->optlen))
ip_forward_options(skb);
@@ -1637,7 +1638,8 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
* to blackhole.
*/
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+ IP_INC_STATS_BH(dev_net(dev), dev,
+ IPSTATS_MIB_FRAGFAILS);
ip_rt_put(rt);
goto out_free;
}
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 43d4c3b..10504e8 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -567,7 +567,7 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
err = PTR_ERR(rt);
rt = NULL;
if (err == -ENETUNREACH)
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
goto out;
}
@@ -602,13 +602,13 @@ back_from_confirm:
release_sock(sk);
out:
- ip_rt_put(rt);
if (free)
kfree(ipc.opt);
if (!err) {
- icmp_out_count(sock_net(sk), user_icmph.type);
- return len;
+ icmp_out_count(rt->dst.dev, user_icmph.type);
+ err = len;
}
+ ip_rt_put(rt);
return err;
do_confirm:
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 3ccda5a..7c579c3 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -387,7 +387,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
}
if (iph->protocol == IPPROTO_ICMP)
- icmp_out_count(net, ((struct icmphdr *)
+ icmp_out_count(rt->dst.dev, ((struct icmphdr *)
skb_transport_header(skb))->type);
err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
@@ -402,7 +402,7 @@ out:
error_free:
kfree_skb(skb);
error:
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
+ IP_INC_STATS(net, rt->dst.dev, IPSTATS_MIB_OUTDISCARDS);
if (err == -ENOBUFS && !inet->recverr)
err = 0;
return err;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f30112f..e9b1124 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1545,7 +1545,7 @@ static int ip_error(struct sk_buff *skb)
case ENETUNREACH:
code = ICMP_NET_UNREACH;
IP_INC_STATS_BH(dev_net(rt->dst.dev),
- IPSTATS_MIB_INNOROUTES);
+ rt->dst.dev, IPSTATS_MIB_INNOROUTES);
break;
case EACCES:
code = ICMP_PKT_FILTERED;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1eb4ad5..8b99f21 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -183,7 +183,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
if (err == -ENETUNREACH)
- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(sock_net(sk), NULL, IPSTATS_MIB_OUTNOROUTES);
return err;
}
@@ -359,17 +359,18 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
__u32 seq;
__u32 remaining;
int err;
- struct net *net = dev_net(icmp_skb->dev);
+ struct net_device *dev = icmp_skb->dev;
+ struct net *net = dev_net(dev);
if (icmp_skb->len < (iph->ihl << 2) + 8) {
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
return;
}
sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest,
iph->saddr, th->source, inet_iif(icmp_skb));
if (!sk) {
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
return;
}
if (sk->sk_state == TCP_TIME_WAIT) {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5d075b5..b4af9c0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -587,12 +587,13 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
struct sock *sk;
int harderr;
int err;
- struct net *net = dev_net(skb->dev);
+ struct net_device *dev = skb->dev;
+ struct net *net = dev_net(dev);
sk = __udp4_lib_lookup(net, iph->daddr, uh->dest,
iph->saddr, uh->source, skb->dev->ifindex, udptable);
if (sk == NULL) {
- ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(net, dev, ICMP_MIB_INERRORS);
return; /* No socket for error */
}
@@ -937,7 +938,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
err = PTR_ERR(rt);
rt = NULL;
if (err == -ENETUNREACH)
- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
goto out;
}
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index d21e7eb..1620860 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -330,7 +330,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
if (IS_ERR(rt)) {
rc = PTR_ERR(rt);
if (rc == -ENETUNREACH)
- IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(&init_net, NULL, IPSTATS_MIB_OUTNOROUTES);
goto out;
}
@@ -406,7 +406,7 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb)
return 0;
drop:
- IP_INC_STATS(&init_net, IPSTATS_MIB_INDISCARDS);
+ IP_INC_STATS(&init_net, skb->dev, IPSTATS_MIB_INDISCARDS);
kfree_skb(skb);
return -1;
}
@@ -532,7 +532,7 @@ out:
no_route:
rcu_read_unlock();
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
rc = -EHOSTUNREACH;
goto out;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 80f71af..f86f811 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -576,7 +576,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
int err;
if (skb->len < ihlen + 8) {
- ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(&init_net, skb->dev, ICMP_MIB_INERRORS);
return;
}
@@ -590,7 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
skb->network_header = saveip;
skb->transport_header = savesctp;
if (!sk) {
- ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(&init_net, skb->dev, ICMP_MIB_INERRORS);
return;
}
/* Warning: The sock lock is held. Remember to call
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 08b3cea..7fb40d0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -569,7 +569,7 @@ out:
return err;
no_route:
kfree_skb(nskb);
- IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
+ IP_INC_STATS_BH(&init_net, NULL, IPSTATS_MIB_OUTNOROUTES);
/* FIXME: Returning the 'err' will effect all the associations
* associated with a socket, although only one of the paths of the
--
1.7.5.4
^ permalink raw reply related
* [PATCH 09/10 net-next] net:ipv4:proc: Introduce proc files for ipv4 per interface stats
From: igorm @ 2011-12-16 15:26 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
In ip_proc_init_net dev_snmp proc directory is created.
Functions snmp_(un)register_dev are for creating/deleting proc files
that have same names as interfaces for which they are created.
Per device proc files for ipv4 interfaces have the same form as
per device proc files for ipv6 interfaces.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
net/ipv4/proc.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 3569d8e..c6202d9 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -128,6 +128,14 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
SNMP_MIB_SENTINEL
};
+static const struct snmp_mib snmp4_icmp_list[] = {
+ SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS),
+ SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS),
+ SNMP_MIB_ITEM("OutMsgs", ICMP_MIB_OUTMSGS),
+ SNMP_MIB_ITEM("OutErrors", ICMP_MIB_OUTERRORS),
+ SNMP_MIB_SENTINEL
+};
+
static const struct {
const char *name;
int index;
@@ -459,6 +467,113 @@ static const struct file_operations netstat_seq_fops = {
.release = single_release_net,
};
+static void snmp_seq_show_item(struct seq_file *seq, void __percpu **pcpumib,
+ atomic_long_t *smib,
+ const struct snmp_mib *itemlist,
+ char *prefix)
+{
+ char name[32];
+ int i;
+ unsigned long val;
+
+ for (i = 0; itemlist[i].name; i++) {
+ val = pcpumib ?
+ snmp_fold_field64(pcpumib, itemlist[i].entry,
+ offsetof(struct ipstats_mib, syncp)) :
+ atomic_long_read(smib + itemlist[i].entry);
+ snprintf(name, sizeof(name), "%s%s",
+ prefix, itemlist[i].name);
+ seq_printf(seq, "%-32s\t%lu\n", name, val);
+ }
+}
+
+static void snmp_seq_show_icmpmsg(struct seq_file *seq, atomic_long_t *smib)
+{
+ char name[32];
+ int i;
+ unsigned long val;
+ for (i = 0; i < ICMPMSG_MIB_MAX; i++) {
+ val = atomic_long_read(smib + i);
+ if (val) {
+ snprintf(name, sizeof(name), "Icmp%sType%u",
+ i & 0x100 ? "Out" : "In", i & 0xff);
+ seq_printf(seq, "%-32s\t%lu\n", name, val);
+ }
+ }
+}
+
+static int snmp_dev_seq_show(struct seq_file *seq, void *v)
+{
+ struct in_device *idev = (struct in_device *)seq->private;
+
+ seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
+ seq_printf(seq, "%-32s\t%u\n", "Forwarding",
+ IN_DEV_FORWARD(idev));
+ seq_printf(seq, "%-32s\t%u\n", "McForwarding",
+ IN_DEV_MFORWARD(idev));
+ seq_printf(seq, "%-32s\t%u\n", "DefaultTTL",
+ sysctl_ip_default_ttl);
+
+ BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0);
+
+ snmp_seq_show_item(seq, (void __percpu **)idev->stats.ip, NULL,
+ snmp4_ipstats_list, "Ip");
+ snmp_seq_show_item(seq, (void __percpu **)idev->stats.ip, NULL,
+ snmp4_ipextstats_list, "Ip");
+ snmp_seq_show_item(seq, NULL, idev->stats.icmpdev->mibs,
+ snmp4_icmp_list, "Icmp");
+ snmp_seq_show_icmpmsg(seq, idev->stats.icmpmsgdev->mibs);
+ return 0;
+}
+
+static int snmp_dev_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, snmp_dev_seq_show, PDE(inode)->data);
+}
+
+static const struct file_operations snmp_dev_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = snmp_dev_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+int snmp_register_dev(struct in_device *idev)
+{
+ struct proc_dir_entry *p;
+ struct net *net;
+
+ if (!idev || !idev->dev)
+ return -EINVAL;
+
+ net = dev_net(idev->dev);
+ if (!net->mib.proc_net_devsnmp)
+ return -ENOENT;
+
+ p = proc_create_data(idev->dev->name, S_IRUGO,
+ net->mib.proc_net_devsnmp,
+ &snmp_dev_seq_fops, idev);
+ if (!p)
+ return -ENOMEM;
+
+ idev->stats.proc_dir_entry = p;
+ return 0;
+}
+
+int snmp_unregister_dev(struct in_device *idev)
+{
+ struct net *net = dev_net(idev->dev);
+ if (!net->mib.proc_net_devsnmp)
+ return -ENOENT;
+ if (!idev->stats.proc_dir_entry)
+ return -EINVAL;
+ remove_proc_entry(idev->stats.proc_dir_entry->name,
+ net->mib.proc_net_devsnmp);
+ idev->stats.proc_dir_entry = NULL;
+ return 0;
+}
+
static __net_init int ip_proc_init_net(struct net *net)
{
if (!proc_net_fops_create(net, "sockstat", S_IRUGO, &sockstat_seq_fops))
@@ -467,9 +582,14 @@ static __net_init int ip_proc_init_net(struct net *net)
goto out_netstat;
if (!proc_net_fops_create(net, "snmp", S_IRUGO, &snmp_seq_fops))
goto out_snmp;
+ net->mib.proc_net_devsnmp = proc_mkdir("dev_snmp", net->proc_net);
+ if (!net->mib.proc_net_devsnmp)
+ goto out_dev_snmp;
return 0;
+out_dev_snmp:
+ proc_net_remove(net, "snmp");
out_snmp:
proc_net_remove(net, "netstat");
out_netstat:
@@ -483,6 +603,7 @@ static __net_exit void ip_proc_exit_net(struct net *net)
proc_net_remove(net, "snmp");
proc_net_remove(net, "netstat");
proc_net_remove(net, "sockstat");
+ proc_net_remove(net, "dev_snmp");
}
static __net_initdata struct pernet_operations ip_proc_ops = {
--
1.7.5.4
^ permalink raw reply related
* [PATCH 07/10 net-next] net:ipv4:devinet: Add support for alloc/free of per device stats and (un)register of per device proc files
From: igorm @ 2011-12-16 15:26 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Added function snmp_alloc_dev and snmp_free_dev for
allocing/freeing per device statistics.
snmp_alloc_dev is only called when in_device is created. If it failes,
in_device can't be created.
snmp_free_dev is only called when in_device is destroyed.
Added calls for snmp_(un)register_dev functions.
snmp_unregister_dev is called when in_device is destroyed and when it changes name.
snmp_register_dev is called when in_device is created. If it failes in_device
can be created. snmp_register_dev is also called when in_device change name.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
net/ipv4/devinet.c | 75 +++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 65f01dc..c18564f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -211,6 +211,38 @@ static inline void inet_free_ifa(struct in_ifaddr *ifa)
call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
}
+static int snmp_alloc_dev(struct in_device *idev)
+{
+ if (snmp_mib_init((void __percpu **)idev->stats.ip,
+ sizeof(struct ipstats_mib),
+ __alignof__(struct ipstats_mib)) < 0)
+ goto err_ip;
+ idev->stats.icmpdev = kzalloc(sizeof(struct icmp_mib_dev),
+ GFP_KERNEL);
+ if (!idev->stats.icmpdev)
+ goto err_icmp;
+ idev->stats.icmpmsgdev = kzalloc(sizeof(struct icmpmsg_mib_dev),
+ GFP_KERNEL);
+ if (!idev->stats.icmpmsgdev)
+ goto err_icmpmsg;
+
+ return 0;
+
+err_icmpmsg:
+ kfree(idev->stats.icmpdev);
+err_icmp:
+ snmp_mib_free((void __percpu **)idev->stats.ip);
+err_ip:
+ return -ENOMEM;
+}
+
+static void snmp_free_dev(struct in_device *idev)
+{
+ kfree(idev->stats.icmpmsgdev);
+ kfree(idev->stats.icmpdev);
+ snmp_mib_free((void __percpu **)idev->stats.ip);
+}
+
void in_dev_finish_destroy(struct in_device *idev)
{
struct net_device *dev = idev->dev;
@@ -224,8 +256,10 @@ void in_dev_finish_destroy(struct in_device *idev)
dev_put(dev);
if (!idev->dead)
pr_err("Freeing alive in_device %p\n", idev);
- else
+ else {
+ snmp_free_dev(idev);
kfree(idev);
+ }
}
EXPORT_SYMBOL(in_dev_finish_destroy);
@@ -249,6 +283,22 @@ static struct in_device *inetdev_init(struct net_device *dev)
dev_disable_lro(dev);
/* Reference in_dev->dev */
dev_hold(dev);
+
+ if (snmp_alloc_dev(in_dev) < 0) {
+ printk(KERN_CRIT
+ "%s(): cannot allocate memory for statistics; dev=%s.\n",
+ __func__, dev->name);
+ neigh_parms_release(&arp_tbl, in_dev->arp_parms);
+ dev_put(dev);
+ kfree(in_dev);
+ return NULL;
+ }
+
+ if (snmp_register_dev(in_dev) < 0)
+ printk(KERN_WARNING
+ "%s(): cannot create /proc/net/dev_snmp/%s\n",
+ __func__, dev->name);
+
/* Account for reference dev->ip_ptr (below) */
in_dev_hold(in_dev);
@@ -292,6 +342,7 @@ static void inetdev_destroy(struct in_device *in_dev)
}
RCU_INIT_POINTER(dev->ip_ptr, NULL);
+ snmp_unregister_dev(in_dev);
devinet_sysctl_unregister(in_dev);
neigh_parms_release(&arp_tbl, in_dev->arp_parms);
@@ -1222,14 +1273,20 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
case NETDEV_UNREGISTER:
inetdev_destroy(in_dev);
break;
- case NETDEV_CHANGENAME:
- /* Do not notify about label change, this event is
- * not interesting to applications using netlink.
- */
- inetdev_changename(dev, in_dev);
-
- devinet_sysctl_unregister(in_dev);
- devinet_sysctl_register(in_dev);
+ case NETDEV_CHANGENAME: {
+ int err;
+ /* Do not notify about label change, this event is
+ * not interesting to applications using netlink.
+ */
+ inetdev_changename(dev, in_dev);
+
+ snmp_unregister_dev(in_dev);
+ devinet_sysctl_unregister(in_dev);
+ devinet_sysctl_register(in_dev);
+ err = snmp_register_dev(in_dev);
+ if (err)
+ return notifier_from_errno(err);
+ }
break;
}
out:
--
1.7.5.4
^ permalink raw reply related
* [PATCH 08/10 net-next] net:ipv4:af_inet: Init proc fs before ip_init
From: igorm @ 2011-12-16 15:26 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Moved ipv4_proc_init() before ip_init().
Did that, so the proc fs for ipv4 would be initialised
before we initialise devinet. If I didn't do that,
per device proc files couldn't be created
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
net/ipv4/af_inet.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f7b5670..7384a20 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1695,6 +1695,11 @@ static int __init inet_init(void)
for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
inet_register_protosw(q);
+
+ /*
+ * Init proc fs
+ */
+ ipv4_proc_init();
/*
* Set the ARP module up
@@ -1742,8 +1747,6 @@ static int __init inet_init(void)
if (init_ipv4_mibs())
printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n");
- ipv4_proc_init();
-
ipfrag_init();
dev_add_pack(&ip_packet_type);
--
1.7.5.4
^ permalink raw reply related
* [PATCH 05/10 net-next] include:net:ip: Tuned up IP_*_STATS macros for per device statistics and added functions for (un)registering per device proc entries
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Changed IP_*_STATS so now they call _DEV* macros.
They call _DEV* macros under rcu_read_lock,
so we could get in_device* from net_device* with function
__in_dev_get_rcu_safely. This function is safe if dev==NULL.
Included <linux/inetdevice.h> so we could call __in_dev_get_rcu_safely.
Added prototypes for snmp_(un)register_dev.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/net/ip.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index 775009f..9895b1f 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -26,6 +26,7 @@
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
#include <net/inet_sock.h>
#include <net/snmp.h>
@@ -184,12 +185,54 @@ struct ipv4_config {
};
extern struct ipv4_config ipv4_config;
-#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
-#define IP_INC_STATS_BH(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field)
-#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
-#define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val)
-#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
-#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val)
+#define IP_INC_STATS(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINC(net, ip, 64, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field); \
+ rcu_read_unlock(); \
+ })
+
+#define IP_INC_STATS_BH(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINC(net, ip, 64_BH, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field); \
+ rcu_read_unlock(); \
+ })
+
+#define IP_ADD_STATS(net, dev, field, val) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVADD(net, ip, 64, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field, val); \
+ rcu_read_unlock(); \
+ })
+
+#define IP_ADD_STATS_BH(net, dev, field, val) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVADD(net, ip, 64_BH, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field, val); \
+ rcu_read_unlock(); \
+ })
+
+#define IP_UPD_PO_STATS(net, dev, field, val) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVUPD(net, ip, 64, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field, val); \
+ rcu_read_unlock(); \
+ })
+
+#define IP_UPD_PO_STATS_BH(net, dev, field, val) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVUPD(net, ip, 64_BH, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field, val); \
+ rcu_read_unlock(); \
+ })
+
#define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
#define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
#define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
@@ -470,6 +513,11 @@ extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
#ifdef CONFIG_PROC_FS
extern int ip_misc_proc_init(void);
+extern int snmp_register_dev(struct in_device *idev);
+extern int snmp_unregister_dev(struct in_device *idev);
+#else
+extern int snmp_register_dev(struct in_device *idev) { return 0;}
+extern int snmp_unregister_dev(struct in_device *idev) { return 0;}
#endif
#endif /* _IP_H */
--
1.7.5.4
^ permalink raw reply related
* [PATCH 06/10 net-next] include:net:icmp: Tuned up ICMP_*_STATS macros for per device statistics and changed prototype for icmp_out_count
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Changed ICMP_*_STATS so now they call _DEV* macros.
They call _DEV* macros under rcu_read_lock,
so we could get in_device from net_device with function
__in_dev_get_rcu_safely. This function is safe if dev==NULL.
Changed prototype for icmp_out_count so we can have per device statistics.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/net/icmp.h | 37 ++++++++++++++++++++++++++++++++-----
1 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 75d6156..aa71b9a 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -29,10 +29,37 @@ struct icmp_err {
};
extern const struct icmp_err icmp_err_convert[];
-#define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field)
-#define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field)
-#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256)
-#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field)
+#define ICMP_INC_STATS(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINCATOMIC(net, icmp, , struct in_device, \
+ __in_dev_get_rcu_safely(dev), field); \
+ rcu_read_unlock(); \
+ })
+
+#define ICMP_INC_STATS_BH(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINCATOMIC(net, icmp, _BH, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field); \
+ rcu_read_unlock(); \
+ })
+
+#define ICMPMSGOUT_INC_STATS(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINC_ATOMIC_ATOMIC(net, icmpmsg, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field +256); \
+ rcu_read_unlock(); \
+ })
+
+#define ICMPMSGIN_INC_STATS_BH(net, dev, field) \
+ ({ \
+ rcu_read_lock(); \
+ _DEVINC_ATOMIC_ATOMIC(net, icmpmsg, struct in_device, \
+ __in_dev_get_rcu_safely(dev), field); \
+ rcu_read_unlock(); \
+ })
struct dst_entry;
struct net_proto_family;
@@ -43,6 +70,6 @@ extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
extern int icmp_rcv(struct sk_buff *skb);
extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int icmp_init(void);
-extern void icmp_out_count(struct net *net, unsigned char type);
+extern void icmp_out_count(struct net_device *dev, unsigned char type);
#endif /* _ICMP_H */
--
1.7.5.4
^ permalink raw reply related
* [PATCH 02/10 net-next] include: net: snmp: Create icmp per device counters and add macros for per device stats
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Added per device counters for ipv4 icmp statistics.
Moved _DEV* macros here, from include/net/ipv6.h.
Also, made them more generic, by adding new argument - type.
Because of that, they can be used for in_device stats accounting
in the same way as for inet6_dev.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/net/snmp.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 2f65e16..65f4052 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -61,14 +61,24 @@ struct ipstats_mib {
/* ICMP */
#define ICMP_MIB_MAX __ICMP_MIB_MAX
+/* per network ns counters */
struct icmp_mib {
unsigned long mibs[ICMP_MIB_MAX];
};
+/*per device counters, (shared on all cpus) */
+struct icmp_mib_dev {
+ atomic_long_t mibs[ICMP_MIB_MAX];
+};
#define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX
+/* per network ns counters */
struct icmpmsg_mib {
atomic_long_t mibs[ICMPMSG_MIB_MAX];
};
+/* per device counters, (shared on all cpus) */
+struct icmpmsg_mib_dev {
+ atomic_long_t mibs[ICMPMSG_MIB_MAX];
+};
/* ICMP6 (IPv6-ICMP) */
#define ICMP6_MIB_MAX __ICMP6_MIB_MAX
@@ -214,4 +224,49 @@ struct linux_xfrm_mib {
#define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend) SNMP_UPD_PO_STATS_BH(mib, basefield, addend)
#endif
+/* Macros for enabling per device statistics */
+
+#define _DEVINC(net, statname, modifier, type, idev, field) \
+({ \
+ __typeof__(type) *_idev = (idev); \
+ if (likely(_idev)) \
+ SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
+ SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field)); \
+})
+
+/* per device counters are atomic_long_t */
+#define _DEVINCATOMIC(net, statname, modifier, type, idev, field) \
+({ \
+ __typeof__(type) *_idev = (idev); \
+ if (likely(_idev)) \
+ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
+ SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field)); \
+})
+
+/* per device and per net counters are atomic_long_t */
+
+#define _DEVINC_ATOMIC_ATOMIC(net, statname, type, idev, field) \
+({ \
+ __typeof__(type) *_idev = (idev); \
+ if (likely(_idev)) \
+ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
+ SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field)); \
+})
+
+#define _DEVADD(net, statname, modifier, type, idev, field, val) \
+({ \
+ __typeof__(type) *_idev = (idev); \
+ if (likely(_idev)) \
+ SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
+ SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val)); \
+})
+
+#define _DEVUPD(net, statname, modifier, type, idev, field, val) \
+({ \
+ __typeof__(type) *_idev = (idev); \
+ if (likely(_idev)) \
+ SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+ SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val)); \
+})
+
#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH 04/10 net-next] include:net:ipv6: Moved _DEV* macros
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Moved _DEV* macros to /include/net/snmp.h so they
could be reused for ipv4 per device statistics.
Changed calling of _DEV* macros because they now have +1 argument - type.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/net/ipv6.h | 64 +++++++++-------------------------------------------
1 files changed, 11 insertions(+), 53 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index e4170a2..fe65b9b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -115,73 +115,31 @@ struct frag_hdr {
extern int sysctl_mld_max_msf;
extern struct ctl_path net_ipv6_ctl_path[];
-#define _DEVINC(net, statname, modifier, idev, field) \
-({ \
- struct inet6_dev *_idev = (idev); \
- if (likely(_idev != NULL)) \
- SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
- SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
-})
-
-/* per device counters are atomic_long_t */
-#define _DEVINCATOMIC(net, statname, modifier, idev, field) \
-({ \
- struct inet6_dev *_idev = (idev); \
- if (likely(_idev != NULL)) \
- SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
- SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
-})
-
-/* per device and per net counters are atomic_long_t */
-#define _DEVINC_ATOMIC_ATOMIC(net, statname, idev, field) \
-({ \
- struct inet6_dev *_idev = (idev); \
- if (likely(_idev != NULL)) \
- SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
- SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\
-})
-
-#define _DEVADD(net, statname, modifier, idev, field, val) \
-({ \
- struct inet6_dev *_idev = (idev); \
- if (likely(_idev != NULL)) \
- SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
- SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
-})
-
-#define _DEVUPD(net, statname, modifier, idev, field, val) \
-({ \
- struct inet6_dev *_idev = (idev); \
- if (likely(_idev != NULL)) \
- SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
- SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
-})
-
/* MIBs */
#define IP6_INC_STATS(net, idev,field) \
- _DEVINC(net, ipv6, 64, idev, field)
+ _DEVINC(net, ipv6, 64, struct inet6_dev, idev, field)
#define IP6_INC_STATS_BH(net, idev,field) \
- _DEVINC(net, ipv6, 64_BH, idev, field)
+ _DEVINC(net, ipv6, 64_BH, struct inet6_dev, idev, field)
#define IP6_ADD_STATS(net, idev,field,val) \
- _DEVADD(net, ipv6, 64, idev, field, val)
+ _DEVADD(net, ipv6, 64, struct inet6_dev, idev, field, val)
#define IP6_ADD_STATS_BH(net, idev,field,val) \
- _DEVADD(net, ipv6, 64_BH, idev, field, val)
+ _DEVADD(net, ipv6, 64_BH, struct inet6_dev, idev, field, val)
#define IP6_UPD_PO_STATS(net, idev,field,val) \
- _DEVUPD(net, ipv6, 64, idev, field, val)
+ _DEVUPD(net, ipv6, 64, struct inet6_dev, idev, field, val)
#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \
- _DEVUPD(net, ipv6, 64_BH, idev, field, val)
+ _DEVUPD(net, ipv6, 64_BH, struct inet6_dev, idev, field, val)
#define ICMP6_INC_STATS(net, idev, field) \
- _DEVINCATOMIC(net, icmpv6, , idev, field)
+ _DEVINCATOMIC(net, icmpv6, , struct inet6_dev, idev, field)
#define ICMP6_INC_STATS_BH(net, idev, field) \
- _DEVINCATOMIC(net, icmpv6, _BH, idev, field)
+ _DEVINCATOMIC(net, icmpv6, _BH, struct inet6_dev, idev, field)
#define ICMP6MSGOUT_INC_STATS(net, idev, field) \
- _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, struct inet6_dev, idev, field +256)
#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \
- _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, struct inet6_dev, idev, field +256)
#define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \
- _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, struct inet6_dev, idev, field)
struct ip6_ra_chain {
struct ip6_ra_chain *next;
--
1.7.5.4
^ permalink raw reply related
* [PATCH 00/10 net-next] Introduce per interface ipv4 statistics
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
From: Igor Maravic <igorm@etf.rs>
Hi all,
in this patch series I introduced per interface statistics for ipv4.
I referenced how it was done for ipv6 per interface statistics.
BR
Igor
Igor Maravic (10):
include: net: netns: mib: Add proc_dir_entry for ipv4 per interface
stats
include: net: snmp: Create icmp per device counters and add macros
for per device stats
include:linux:inetdevice: Add struct ipv4_devstat and func
__in_dev_get_rcu_safely
include:net:ipv6: Moved _DEV* macros
include:net:ip: Tuned up IP_*_STATS macros for per device statistics
and added functions for (un)registering per device proc entries
include:net:icmp: Tuned up ICMP_*_STATS macros for per device
statistics and changed prototype for icmp_out_count
net:ipv4:devinet: Add support for alloc/free of per device stats and
(un)register of per device proc files
net:ipv4:af_inet: Init proc fs before ip_init
net:ipv4:proc: Introduce proc files for ipv4 per interface stats
net: Enable ipv4 per interface statistics
include/linux/inetdevice.h | 16 +++++
include/net/icmp.h | 37 ++++++++++--
include/net/ip.h | 60 +++++++++++++++++--
include/net/ipv6.h | 64 ++++-----------------
include/net/netns/mib.h | 1 +
include/net/snmp.h | 55 ++++++++++++++++++
net/bridge/br_netfilter.c | 6 +-
net/dccp/ipv4.c | 9 ++-
net/ipv4/af_inet.c | 7 ++-
net/ipv4/datagram.c | 2 +-
net/ipv4/devinet.c | 75 +++++++++++++++++++++---
net/ipv4/icmp.c | 29 +++++----
net/ipv4/inet_connection_sock.c | 8 ++-
net/ipv4/ip_forward.c | 8 ++-
net/ipv4/ip_fragment.c | 43 ++++++++------
net/ipv4/ip_input.c | 33 ++++++-----
net/ipv4/ip_output.c | 43 ++++++++------
net/ipv4/ipmr.c | 6 +-
net/ipv4/ping.c | 8 +-
net/ipv4/proc.c | 121 +++++++++++++++++++++++++++++++++++++++
net/ipv4/raw.c | 4 +-
net/ipv4/route.c | 2 +-
net/ipv4/tcp_ipv4.c | 9 ++-
net/ipv4/udp.c | 7 +-
net/l2tp/l2tp_ip.c | 6 +-
net/sctp/input.c | 4 +-
net/sctp/output.c | 2 +-
27 files changed, 488 insertions(+), 177 deletions(-)
--
1.7.5.4
^ permalink raw reply
* [PATCH 03/10 net-next] include:linux:inetdevice: Add struct ipv4_devstat and func __in_dev_get_rcu_safely
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Added struct ipv4_devstat for holding per device ipv4 stats.
Added function __in_dev_get_rcu_safely.
Did that so I would have cleaner code in IP_*_STATS and ICMP_*_STATS macros.
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/linux/inetdevice.h | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 5f81466..a4bffa7 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -49,6 +49,13 @@ struct ipv4_devconf {
DECLARE_BITMAP(state, IPV4_DEVCONF_MAX);
};
+struct ipv4_devstat {
+ struct proc_dir_entry *proc_dir_entry;
+ DEFINE_SNMP_STAT(struct ipstats_mib, ip);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmp_mib_dev, icmpdev);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib_dev, icmpmsgdev);
+};
+
struct in_device {
struct net_device *dev;
atomic_t refcnt;
@@ -69,6 +76,7 @@ struct in_device {
struct neigh_parms *arp_parms;
struct ipv4_devconf cnf;
+ struct ipv4_devstat stats;
struct rcu_head rcu_head;
};
@@ -209,6 +217,14 @@ static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev)
return rcu_dereference(dev->ip_ptr);
}
+static inline struct in_device *__in_dev_get_rcu_safely(const struct net_device *dev)
+{
+ if (likely(dev))
+ return rcu_dereference(dev->ip_ptr);
+ else
+ return NULL;
+}
+
static inline struct in_device *in_dev_get(const struct net_device *dev)
{
struct in_device *in_dev;
--
1.7.5.4
^ permalink raw reply related
* [PATCH 01/10 net-next] include: net: netns: mib: Add proc_dir_entry for ipv4 per interface stats
From: igorm @ 2011-12-16 15:25 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
In-Reply-To: <1324049163-11207-1-git-send-email-igorm@etf.rs>
From: Igor Maravic <igorm@etf.rs>
Introduces proc_dir_entry in which we will hold ipv4 per interface proc files
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
include/net/netns/mib.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h
index d542a4b..eaac2d1 100644
--- a/include/net/netns/mib.h
+++ b/include/net/netns/mib.h
@@ -4,6 +4,7 @@
#include <net/snmp.h>
struct netns_mib {
+ struct proc_dir_entry *proc_net_devsnmp;
DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
DEFINE_SNMP_STAT(struct ipstats_mib, ip_statistics);
DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
--
1.7.5.4
^ permalink raw reply related
* Re: linux-3.0.x regression with ipv4 routes having mtu
From: Timo Teräs @ 2011-12-16 14:30 UTC (permalink / raw)
To: Steffen Klassert; +Cc: David Miller, netdev
In-Reply-To: <20111216122147.GJ6348@secunet.com>
On 12/16/2011 02:21 PM, Steffen Klassert wrote:
> On Thu, Dec 15, 2011 at 02:49:57PM +0100, Steffen Klassert wrote:
>> On Wed, Dec 14, 2011 at 12:50:10PM -0500, David Miller wrote:
>>> From: Timo Teräs <timo.teras@iki.fi>
>>> Date: Wed, 14 Dec 2011 17:54:16 +0200
>>>
>>>> So something is does not get updated here. This used to work though.
>>>> The current production boxes where I know this work is 2.6.38.8.
>>>
>>> We store the PMTU externally in inetpeer entries, Eric Dumazet
>>> fixed recently but that fix hasn't been submitted to -stable
>>> yet.
>>>
>>
>> I think we still have at least two problems with pmtu handling.
>> One is that "ip route flush cache" flushes the routing cache
>> but not the cached metrics on the inetpeer.
>
> "ip route flush cache" does not even flush the routing cache,
> it just markes the routing cache as invalid by changing the
> rt_genid which make the old routes invisible. And since we don't
> have rt_check_expire() anymore, we have to wait until we have
> collected gc_thresh (1024) useless routes before rt_garbage_collect()
> starts to remove some of them (btw. is this intentional).
>
> I think we need a trigger in rt_cache_invalidate() that expires
> all cached pmtu values similar to the routing cache entries.
> For a moment I thought we could just reset the __rt_peer_genid
> value back to zero to mark all cached pmtu values as expired,
> but that's apparently not save to do. So I came to no conclusion
> how to fix this today. Any ideas?
Oh, right. This problem is secondary. As long as the mtu value is
reflected properly, I'll be happy :)
>> Another problem might be that we ignore the user configured
>> fib_metrics in rt_init_metrics() if we have a cached metric
>> on the inetpeer.
>>
>
> I think this could be fixed with something like the patch
> below. With this it should be possible to overwrite cached
> values from userspace. It has not much testing, so it's
> just for review at the monent.
>
> ---------
> Subject: [PATCH] route: Initialize with the fib_metrics in the non default case
>[snip]
Thanks! After a very quick test spin, it would appear to fix the bug.
Will continue testing.
^ permalink raw reply
* Re: [PATCH v9 1/9] Basic kernel memory functionality for the Memory Controller
From: Michal Hocko @ 2011-12-16 13:30 UTC (permalink / raw)
To: Glauber Costa
Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
paul-inf54ven1CmVyaH7bEyXVA, lizf-BthXqXjhjHXQFUHtdCDX3A,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, gthelen-hpIqsD4AKlfQT0dZR+AlfA,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
kirill-oKw7cIdHH8eLwutG50LtGA, avagin-bzQdu9zFT3WakBO8gow8eQ,
devel-GEFAQzZX7r8dnm+yROfE0A, eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
cgroups-u79uwXL29TY76Z2rM5mHXA, Johannes Weiner
In-Reply-To: <4EEB417B.8000508-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
On Fri 16-12-11 17:02:51, Glauber Costa wrote:
> On 12/16/2011 04:32 PM, Michal Hocko wrote:
[...]
> >So why do we need kmem accounting when tcp (the only user at the moment)
> >doesn't use it?
>
> Well, a bit historical. I needed a basic placeholder for it, since
> it tcp is officially kmem. As the time passed, I took most of the
> stuff out of this patch to leave just the basics I would need for
> tcp.
> Turns out I ended up focusing on the rest, and some of the stuff was
> left here.
>
> At one point I merged tcp data into kmem, but then reverted this
> behavior. the kmem counter stayed.
>
> I agree deferring the whole behavior would be better.
>
> >>In summary, we still never do non-independent accounting. When we
> >>start doing it for the other caches, We will have to add a test at
> >>charge time as well.
> >
> >So we shouldn't do it as a part of this patchset because the further
> >usage is not clear and I think there will be some real issues with
> >user+kmem accounting (e.g. a proper memcg-oom implementation).
> >Can you just drop this patch?
>
> Yes, but the whole set is in the net tree already.
Isn't it only in some for-next branch? Can that one be updated?
> (All other patches are tcp-related but this) Would you mind if I'd
> send a follow up patch removing the kmem files, and leaving just the
> registration functions and basic documentation? (And sorry for that as
> well in advance)
Yes a followup patch would work as well.
--
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9
Czech Republic
--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v9 1/9] Basic kernel memory functionality for the Memory Controller
From: Glauber Costa @ 2011-12-16 13:02 UTC (permalink / raw)
To: Michal Hocko
Cc: davem, linux-kernel, paul, lizf, kamezawa.hiroyu, ebiederm,
gthelen, netdev, linux-mm, kirill, avagin, devel, eric.dumazet,
cgroups, Johannes Weiner
In-Reply-To: <20111216123233.GF3122@tiehlicka.suse.cz>
On 12/16/2011 04:32 PM, Michal Hocko wrote:
> On Thu 15-12-11 16:29:18, Glauber Costa wrote:
>> On 12/14/2011 09:04 PM, Michal Hocko wrote:
>>> [Now with the current patch version, I hope]
>>> On Mon 12-12-11 11:47:01, Glauber Costa wrote:
> [...]
>>>> @@ -3848,10 +3862,17 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
>>>> u64 val;
>>>>
>>>> if (!mem_cgroup_is_root(memcg)) {
>>>> + val = 0;
>>>> +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
>>>> + if (!memcg->kmem_independent_accounting)
>>>> + val = res_counter_read_u64(&memcg->kmem, RES_USAGE);
>>>> +#endif
>>>> if (!swap)
>>>> - return res_counter_read_u64(&memcg->res, RES_USAGE);
>>>> + val += res_counter_read_u64(&memcg->res, RES_USAGE);
>>>> else
>>>> - return res_counter_read_u64(&memcg->memsw, RES_USAGE);
>>>> + val += res_counter_read_u64(&memcg->memsw, RES_USAGE);
>>>> +
>>>> + return val;
>>>> }
>>>
>>> So you report kmem+user but we do not consider kmem during charge so one
>>> can easily end up with usage_in_bytes over limit but no reclaim is going
>>> on. Not good, I would say.
>
> I find this a problem and one of the reason I do not like !independent
> accounting.
>
>>>
>>> OK, so to sum it up. The biggest problem I see is the (non)independent
>>> accounting. We simply cannot mix user+kernel limits otherwise we would
>>> see issues (like kernel resource hog would force memcg-oom and innocent
>>> members would die because their rss is much bigger).
>>> It is also not clear to me what should happen when we hit the kmem
>>> limit. I guess it will be kmem cache dependent.
>>
>> So right now, tcp is completely independent, since it is not
>> accounted to kmem.
>
> So why do we need kmem accounting when tcp (the only user at the moment)
> doesn't use it?
Well, a bit historical. I needed a basic placeholder for it, since it
tcp is officially kmem. As the time passed, I took most of the stuff out
of this patch to leave just the basics I would need for tcp.
Turns out I ended up focusing on the rest, and some of the stuff was
left here.
At one point I merged tcp data into kmem, but then reverted this
behavior. the kmem counter stayed.
I agree deferring the whole behavior would be better.
>> In summary, we still never do non-independent accounting. When we
>> start doing it for the other caches, We will have to add a test at
>> charge time as well.
>
> So we shouldn't do it as a part of this patchset because the further
> usage is not clear and I think there will be some real issues with
> user+kmem accounting (e.g. a proper memcg-oom implementation).
> Can you just drop this patch?
Yes, but the whole set is in the net tree already. (All other patches
are tcp-related but this) Would you mind if I'd send a follow up patch
removing the kmem files, and leaving just the registration functions and
basic documentation? (And sorry for that as well in advance)
>> We still need to keep it separate though, in case the independent
>> flag is turned on/off
>
> I don't mind to have kmem.tcp.* knobs.
>
^ permalink raw reply
* Re: [PATCH v2] sctp: fix incorrect overflow check on autoclose
From: Vlad Yasevich @ 2011-12-16 13:00 UTC (permalink / raw)
To: Xi Wang
Cc: netdev, linux-sctp, Andrew Morton, Andrei Pelinescu-Onciul,
David S. Miller
In-Reply-To: <0BF79838-C86F-4C3F-8D51-4223D579764C@gmail.com>
On 12/15/2011 05:13 PM, Xi Wang wrote:
> On Dec 15, 2011, at 4:07 PM, Vlad Yasevich wrote:
>> I think it would be better to keep this value in seconds and get rid
>> of division in the setsockopt code. We could then have a min and max
>> values where max value could be something like 2 days. I really don't
>> see an autoclose value that is bigger then that being very useful. In
>> fact, most of the time these values are very small as one wants to close
>> out idle associations.
>
> Now I start to think exposing a new sysctl option might be a little
> overkill since autoclose is often small.
>
> How about this?
>
> 1) Simply store autoclose in seconds in setsockopt.
>
> 2) Avoid overflow in associola.c.
>
> asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
> (sp->autoclose > MAX_SCHEDULE_TIMEOUT / HZ)
> ? MAX_SCHEDULE_TIMEOUT
> : (unsigned long)sp->autoclose * HZ;
>
> Or we could use INT_MAX instead of MAX_SCHEDULE_TIMEOUT if you want to
> keep that value consistent across 32/64 bits.
This would work as well. I do like the max configurable though as it
might be a nice feature, but the above code is exactly what I was
thinking about too.
-vlad
>
> - xi
>
^ permalink raw reply
* Re: [PATCH v9 1/9] Basic kernel memory functionality for the Memory Controller
From: Michal Hocko @ 2011-12-16 12:32 UTC (permalink / raw)
To: Glauber Costa
Cc: davem, linux-kernel, paul, lizf, kamezawa.hiroyu, ebiederm,
gthelen, netdev, linux-mm, kirill, avagin, devel, eric.dumazet,
cgroups, Johannes Weiner
In-Reply-To: <4EE9E81E.2090700@parallels.com>
On Thu 15-12-11 16:29:18, Glauber Costa wrote:
> On 12/14/2011 09:04 PM, Michal Hocko wrote:
> >[Now with the current patch version, I hope]
> >On Mon 12-12-11 11:47:01, Glauber Costa wrote:
[...]
> >>@@ -3848,10 +3862,17 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
> >> u64 val;
> >>
> >> if (!mem_cgroup_is_root(memcg)) {
> >>+ val = 0;
> >>+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
> >>+ if (!memcg->kmem_independent_accounting)
> >>+ val = res_counter_read_u64(&memcg->kmem, RES_USAGE);
> >>+#endif
> >> if (!swap)
> >>- return res_counter_read_u64(&memcg->res, RES_USAGE);
> >>+ val += res_counter_read_u64(&memcg->res, RES_USAGE);
> >> else
> >>- return res_counter_read_u64(&memcg->memsw, RES_USAGE);
> >>+ val += res_counter_read_u64(&memcg->memsw, RES_USAGE);
> >>+
> >>+ return val;
> >> }
> >
> >So you report kmem+user but we do not consider kmem during charge so one
> >can easily end up with usage_in_bytes over limit but no reclaim is going
> >on. Not good, I would say.
I find this a problem and one of the reason I do not like !independent
accounting.
> >
> >OK, so to sum it up. The biggest problem I see is the (non)independent
> >accounting. We simply cannot mix user+kernel limits otherwise we would
> >see issues (like kernel resource hog would force memcg-oom and innocent
> >members would die because their rss is much bigger).
> >It is also not clear to me what should happen when we hit the kmem
> >limit. I guess it will be kmem cache dependent.
>
> So right now, tcp is completely independent, since it is not
> accounted to kmem.
So why do we need kmem accounting when tcp (the only user at the moment)
doesn't use it?
> In summary, we still never do non-independent accounting. When we
> start doing it for the other caches, We will have to add a test at
> charge time as well.
So we shouldn't do it as a part of this patchset because the further
usage is not clear and I think there will be some real issues with
user+kmem accounting (e.g. a proper memcg-oom implementation).
Can you just drop this patch?
> We still need to keep it separate though, in case the independent
> flag is turned on/off
I don't mind to have kmem.tcp.* knobs.
--
Michal Hocko
SUSE Labs
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9
Czech Republic
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: linux-3.0.x regression with ipv4 routes having mtu
From: Steffen Klassert @ 2011-12-16 12:21 UTC (permalink / raw)
To: David Miller; +Cc: timo.teras, netdev
In-Reply-To: <20111215134957.GI6348@secunet.com>
On Thu, Dec 15, 2011 at 02:49:57PM +0100, Steffen Klassert wrote:
> On Wed, Dec 14, 2011 at 12:50:10PM -0500, David Miller wrote:
> > From: Timo Teräs <timo.teras@iki.fi>
> > Date: Wed, 14 Dec 2011 17:54:16 +0200
> >
> > > So something is does not get updated here. This used to work though.
> > > The current production boxes where I know this work is 2.6.38.8.
> >
> > We store the PMTU externally in inetpeer entries, Eric Dumazet
> > fixed recently but that fix hasn't been submitted to -stable
> > yet.
> >
>
> I think we still have at least two problems with pmtu handling.
> One is that "ip route flush cache" flushes the routing cache
> but not the cached metrics on the inetpeer.
"ip route flush cache" does not even flush the routing cache,
it just markes the routing cache as invalid by changing the
rt_genid which make the old routes invisible. And since we don't
have rt_check_expire() anymore, we have to wait until we have
collected gc_thresh (1024) useless routes before rt_garbage_collect()
starts to remove some of them (btw. is this intentional).
I think we need a trigger in rt_cache_invalidate() that expires
all cached pmtu values similar to the routing cache entries.
For a moment I thought we could just reset the __rt_peer_genid
value back to zero to mark all cached pmtu values as expired,
but that's apparently not save to do. So I came to no conclusion
how to fix this today. Any ideas?
>
> Another problem might be that we ignore the user configured
> fib_metrics in rt_init_metrics() if we have a cached metric
> on the inetpeer.
>
I think this could be fixed with something like the patch
below. With this it should be possible to overwrite cached
values from userspace. It has not much testing, so it's
just for review at the monent.
---------
Subject: [PATCH] route: Initialize with the fib_metrics in the non default case
We initialize the routing metrics with the cached values in
rt_init_metrics(). So if we have the metrics cached on the
inetpeer, we ignore the user configured fib_metrics. So
initialize the routing metrics with the fib_metrics if they
are different from dst_default_metrics.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/route.c | 28 ++++++++++++++++++++--------
1 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f30112f..26a6249 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1841,6 +1841,22 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
return mtu;
}
+static void __rt_init_metrics(struct rtable *rt, struct fib_info *fi,
+ struct inet_peer *peer)
+{
+ if (peer && fi->fib_metrics == (u32 *) dst_default_metrics) {
+ dst_init_metrics(&rt->dst, peer->metrics, false);
+ return;
+ }
+
+ if (fi->fib_metrics != (u32 *) dst_default_metrics) {
+ rt->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+ }
+
+ dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+}
+
static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
struct fib_info *fi)
{
@@ -1859,7 +1875,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
if (inet_metrics_new(peer))
memcpy(peer->metrics, fi->fib_metrics,
sizeof(u32) * RTAX_MAX);
- dst_init_metrics(&rt->dst, peer->metrics, false);
+
+ __rt_init_metrics(rt, fi, peer);
check_peer_pmtu(&rt->dst, peer);
if (peer->redirect_genid != redirect_genid)
@@ -1869,13 +1886,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
rt->rt_gateway = peer->redirect_learned.a4;
rt->rt_flags |= RTCF_REDIRECTED;
}
- } else {
- if (fi->fib_metrics != (u32 *) dst_default_metrics) {
- rt->fi = fi;
- atomic_inc(&fi->fib_clntref);
- }
- dst_init_metrics(&rt->dst, fi->fib_metrics, true);
- }
+ } else
+ __rt_init_metrics(rt, fi, NULL);
}
static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *fl4,
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH net-next] net: ipv6: proc: Fix error handling
From: Eric Dumazet @ 2011-12-16 12:21 UTC (permalink / raw)
To: igorm; +Cc: netdev, davem
In-Reply-To: <1324037139-3626-1-git-send-email-igorm@etf.rs>
Le vendredi 16 décembre 2011 à 13:05 +0100, igorm@etf.rs a écrit :
> From: Igor Maravic <igorm@etf.rs>
>
> Fix error handling in case making of dir dev_snmp6 failes
>
> Signed-off-by: Igor Maravic <igorm@etf.rs>
> ---
> net/ipv6/proc.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
> index fdeb6d0..6df9035 100644
> --- a/net/ipv6/proc.c
> +++ b/net/ipv6/proc.c
> @@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net)
> goto proc_dev_snmp6_fail;
> return 0;
>
> +proc_dev_snmp6_fail:
> + proc_net_remove(net, "snmp6");
> proc_snmp6_fail:
> proc_net_remove(net, "sockstat6");
> -proc_dev_snmp6_fail:
> - proc_net_remove(net, "dev_snmp6");
> return -ENOMEM;
> }
>
Good catch, thanks !
(Should probably be applied on net tree, not net-next)
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* [PATCH net-next] net: ipv6: proc: Fix error handling
From: igorm @ 2011-12-16 12:05 UTC (permalink / raw)
To: netdev; +Cc: davem, Igor Maravic
From: Igor Maravic <igorm@etf.rs>
Fix error handling in case making of dir dev_snmp6 failes
Signed-off-by: Igor Maravic <igorm@etf.rs>
---
net/ipv6/proc.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index fdeb6d0..6df9035 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net)
goto proc_dev_snmp6_fail;
return 0;
+proc_dev_snmp6_fail:
+ proc_net_remove(net, "snmp6");
proc_snmp6_fail:
proc_net_remove(net, "sockstat6");
-proc_dev_snmp6_fail:
- proc_net_remove(net, "dev_snmp6");
return -ENOMEM;
}
--
1.7.5.4
^ permalink raw reply related
* Re: nonlocal_bind and IPv6
From: Francois Romieu @ 2011-12-16 11:10 UTC (permalink / raw)
To: Vincent Bernat; +Cc: David Miller, zenczykowski, netdev, yoshfuji
In-Reply-To: <e21a2d9682b5d83fefe3f09a07316033@luffy.cx>
Vincent Bernat <bernat@luffy.cx> :
> On Fri, 16 Dec 2011 02:06:00 -0500 (EST), David Miller wrote:
> >>04:58, Maciej Żenczykowski <zenczykowski@gmail.com> disait :
[...]
> >>>why not simply use the IP_TRANSPARENT or IP_FREEBIND socket
> >>>options?
> >>
> >>Because this requires modifying each affected software. This
> >>can be difficult if you don't have the source code available.
> >
> >But it means that it would work on every single kernel verion out
> >there.
[...]
> Moreover, I am just adding the IPv6 version of this setting. The
> IPv4 version already exists.
For IPv6 this is adding a system-scope function which will have to be
maintained and available for ages. It will compete with the existing,
per-application answer. The "fix you application / design" argument
is thus stronger than with IPv4.
--
Ueimor
^ permalink raw reply
* [PATCH 2/2] net: fix compilation with !CONFIG_NET
From: Glauber Costa @ 2011-12-16 10:52 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
netdev-u79uwXL29TY76Z2rM5mHXA,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
cgroups-u79uwXL29TY76Z2rM5mHXA, Glauber Costa, Stephen Rothwell
In-Reply-To: <1324032720-13752-1-git-send-email-glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
Reported-by: Randy Dunlap <rdunlap-/UHa2rfvQTnk1uMJSBkQmQ@public.gmane.org>
Signed-off-by: Glauber Costa <glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
CC: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
CC: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
---
include/net/sock.h | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 6fe0dae..3144c79 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -66,8 +66,20 @@
struct cgroup;
struct cgroup_subsys;
+#ifdef CONFIG_NET
int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss);
void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss);
+#else
+static inline
+int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+ return 0;
+}
+static inline
+void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+}
+#endif
/*
* This structure really needs to be cleaned up.
* Most of it is for TCP, and not used by any of
--
1.7.6.4
--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/2] net: fix sleeping while atomic problem in sock mem_cgroup.
From: Glauber Costa @ 2011-12-16 10:51 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
netdev-u79uwXL29TY76Z2rM5mHXA,
eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
cgroups-u79uwXL29TY76Z2rM5mHXA, Glauber Costa, Stephen Rothwell,
Randy Dunlap
We can't scan the proto_list to initialize sock cgroups, as it
holds a rwlock, and we also want to keep the code generic enough to
avoid calling the initialization functions of protocols directly,
Convert proto_list_lock into a mutex, so we can sleep and do the
necessary allocations. This lock is seldom taken, so there shouldn't
be any performance penalties associated with that
Signed-off-by: Glauber Costa <glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
CC: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
CC: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
CC: Randy Dunlap <rdunlap-/UHa2rfvQTnk1uMJSBkQmQ@public.gmane.org>
---
net/core/sock.c | 28 ++++++++++++++--------------
1 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/net/core/sock.c b/net/core/sock.c
index 5a6a906..0c67fac 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -136,7 +136,7 @@
#include <net/tcp.h>
#endif
-static DEFINE_RWLOCK(proto_list_lock);
+static DEFINE_MUTEX(proto_list_mutex);
static LIST_HEAD(proto_list);
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
@@ -145,7 +145,7 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
struct proto *proto;
int ret = 0;
- read_lock(&proto_list_lock);
+ mutex_lock(&proto_list_mutex);
list_for_each_entry(proto, &proto_list, node) {
if (proto->init_cgroup) {
ret = proto->init_cgroup(cgrp, ss);
@@ -154,13 +154,13 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
}
}
- read_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
return ret;
out:
list_for_each_entry_continue_reverse(proto, &proto_list, node)
if (proto->destroy_cgroup)
proto->destroy_cgroup(cgrp, ss);
- read_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
return ret;
}
@@ -168,11 +168,11 @@ void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss)
{
struct proto *proto;
- read_lock(&proto_list_lock);
+ mutex_lock(&proto_list_mutex);
list_for_each_entry_reverse(proto, &proto_list, node)
if (proto->destroy_cgroup)
proto->destroy_cgroup(cgrp, ss);
- read_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
}
#endif
@@ -2479,10 +2479,10 @@ int proto_register(struct proto *prot, int alloc_slab)
}
}
- write_lock(&proto_list_lock);
+ mutex_lock(&proto_list_mutex);
list_add(&prot->node, &proto_list);
assign_proto_idx(prot);
- write_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
return 0;
out_free_timewait_sock_slab_name:
@@ -2505,10 +2505,10 @@ EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot)
{
- write_lock(&proto_list_lock);
+ mutex_lock(&proto_list_mutex);
release_proto_idx(prot);
list_del(&prot->node);
- write_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
@@ -2531,9 +2531,9 @@ EXPORT_SYMBOL(proto_unregister);
#ifdef CONFIG_PROC_FS
static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(proto_list_lock)
+ __acquires(proto_list_mutex)
{
- read_lock(&proto_list_lock);
+ mutex_lock(&proto_list_mutex);
return seq_list_start_head(&proto_list, *pos);
}
@@ -2543,9 +2543,9 @@ static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
}
static void proto_seq_stop(struct seq_file *seq, void *v)
- __releases(proto_list_lock)
+ __releases(proto_list_mutex)
{
- read_unlock(&proto_list_lock);
+ mutex_unlock(&proto_list_mutex);
}
static char proto_method_implemented(const void *method)
--
1.7.6.4
--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [patch] wimax/i2400m: remove an unused variable
From: Dan Carpenter @ 2011-12-16 10:22 UTC (permalink / raw)
To: Inaky Perez-Gonzalez; +Cc: linux-wimax, wimax, netdev, kernel-janitors
"result" isn't used. We ignore errors here because there is not much we
can do about them.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c
index ac357ac..99ef81b 100644
--- a/drivers/net/wimax/i2400m/usb-tx.c
+++ b/drivers/net/wimax/i2400m/usb-tx.c
@@ -177,7 +177,6 @@ retry:
static
int i2400mu_txd(void *_i2400mu)
{
- int result = 0;
struct i2400mu *i2400mu = _i2400mu;
struct i2400m *i2400m = &i2400mu->i2400m;
struct device *dev = &i2400mu->usb_iface->dev;
@@ -208,16 +207,14 @@ int i2400mu_txd(void *_i2400mu)
/* Yeah, we ignore errors ... not much we can do */
i2400mu_tx(i2400mu, tx_msg, tx_msg_size);
i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */
- if (result < 0)
- break;
}
spin_lock_irqsave(&i2400m->tx_lock, flags);
i2400mu->tx_kthread = NULL;
spin_unlock_irqrestore(&i2400m->tx_lock, flags);
- d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
- return result;
+ d_fnend(4, dev, "(i2400mu %p)\n", i2400mu);
+ return 0;
}
^ permalink raw reply related
* Re: [PATCH v2] net: fix sleeping while atomic problem in sock mem_cgroup.
From: Eric Dumazet @ 2011-12-16 10:10 UTC (permalink / raw)
To: Glauber Costa
Cc: davem, linux-kernel, kamezawa.hiroyu, netdev, cgroups,
Stephen Rothwell, Randy Dunlap
In-Reply-To: <4EEB1807.1000308@parallels.com>
Le vendredi 16 décembre 2011 à 14:05 +0400, Glauber Costa a écrit :
> Well, in this case, I myself think this is a better solution. Do you
> want to push the patch yourself, or should I do it ?
>
Please do it, I'll add my SOB after yours, thanks !
^ permalink raw reply
* Re: [PATCH v2] net: fix sleeping while atomic problem in sock mem_cgroup.
From: Glauber Costa @ 2011-12-16 10:05 UTC (permalink / raw)
To: Eric Dumazet
Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
netdev-u79uwXL29TY76Z2rM5mHXA, cgroups-u79uwXL29TY76Z2rM5mHXA,
Stephen Rothwell, Randy Dunlap
In-Reply-To: <1324029886.2273.9.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On 12/16/2011 02:04 PM, Eric Dumazet wrote:
> Le vendredi 16 décembre 2011 à 13:53 +0400, Glauber Costa a écrit :
>> On 12/16/2011 01:31 PM, Eric Dumazet wrote:
>>> Le vendredi 16 décembre 2011 à 13:09 +0400, Glauber Costa a écrit :
>>>> Since we can't scan the proto_list to initialize sock cgroups, as it
>>>> holds a rwlock, and we also want to keep the code generic enough to
>>>> avoid calling the initialization functions of protocols directly,
>>>> I propose we keep the interested parties in a separate list. This list
>>>> is protected by a mutex so we can sleep and do the necessary allocations.
>>>>
>>>> Also fixes a reference problem found by Randy Dunlap's randconfig.
>>>>
>>>> Signed-off-by: Glauber Costa<glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
>>>> CC: Hiroyouki Kamezawa<kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
>>>> CC: David S. Miller<davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
>>>> CC: Eric Dumazet<eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>>> CC: Stephen Rothwell<sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
>>>> CC: Randy Dunlap<rdunlap-/UHa2rfvQTnk1uMJSBkQmQ@public.gmane.org>
>>>> ---
>>>
>>> Sorry to come late, but why dont we convert proto_list_lock to a mutex ?
>>
>> I didn't suggest this, as I imagined there could be some performance
>> implications to be drawn from it that may not be obvious to me.
>>
>> But if it is okay with you net guys, it is certainly okay with me as well.
>
> This 'lock' is not performance sensitive, its very seldom taken.
>
> If we really wanted to be fast, it would not be a rwlock anymore ;)
>
> "cat /proc/net/protocols" could eventually use RCU locking if we want
> parallelism. (I dont think its needed)
>
Well, in this case, I myself think this is a better solution. Do you
want to push the patch yourself, or should I do it ?
--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox