From 90bcaf7b4a33bb9b100cc06869f0c033a870d4a0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:25:17 -0800 Subject: [IPV6]: flowlabels are net-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 66716911962..9ff1be1bc2e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -217,7 +217,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (tclass < 0) tclass = 0; - *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; + *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; hdr->payload_len = htons(seg_len); hdr->nexthdr = proto; @@ -1311,7 +1311,7 @@ int ip6_push_pending_frames(struct sock *sk) skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); - *(u32*)hdr = fl->fl6_flowlabel | + *(__be32*)hdr = fl->fl6_flowlabel | htonl(0x60000000 | ((int)np->cork.tclass << 20)); if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) -- cgit v1.2.3 From ae08e1f092210619fe49551aa3ed0dc0003d5880 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:27:11 -0800 Subject: [IPV6]: ip6_output annotations Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- net/ipv6/ip6_output.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 85577a4ffa6..7fc9a3aaa1c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -139,7 +139,7 @@ struct skb_shared_info { /* Warning: this field is not always filled in (UFO)! */ unsigned short gso_segs; unsigned short gso_type; - unsigned int ip6_frag_id; + __be32 ip6_frag_id; struct sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; }; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9ff1be1bc2e..93330685adf 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -267,7 +267,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); skb->nh.ipv6h = hdr; - *(u32*)hdr = htonl(0x60000000); + *(__be32*)hdr = htonl(0x60000000); hdr->payload_len = htons(len); hdr->nexthdr = proto; @@ -571,7 +571,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) struct ipv6hdr *tmp_hdr; struct frag_hdr *fh; unsigned int mtu, hlen, left, len; - u32 frag_id = 0; + __be32 frag_id = 0; int ptr, offset = 0, err=0; u8 *prevhdr, nexthdr = 0; -- cgit v1.2.3 From 82e91ffef60e6eba9848fe149ce1eecd2b5aef12 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 9 Nov 2006 15:19:14 -0800 Subject: [NET]: Turn nfmark into generic mark nfmark is being used in various subsystems and has become the defacto mark field for all kinds of packets. Therefore it makes sense to rename it to `mark' and remove the dependency on CONFIG_NETFILTER. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- net/bridge/netfilter/ebt_mark.c | 8 ++++---- net/bridge/netfilter/ebt_mark_m.c | 4 ++-- net/bridge/netfilter/ebt_ulog.c | 2 +- net/core/skbuff.c | 4 ++-- net/decnet/dn_route.c | 4 ++-- net/ipv4/ip_output.c | 2 +- net/ipv4/ipvs/ip_vs_proto_tcp.c | 2 +- net/ipv4/ipvs/ip_vs_proto_udp.c | 2 +- net/ipv4/netfilter.c | 2 +- net/ipv4/netfilter/ip_queue.c | 2 +- net/ipv4/netfilter/ipt_REJECT.c | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 2 +- net/ipv4/netfilter/iptable_mangle.c | 6 +++--- net/ipv4/route.c | 10 +++++----- net/ipv6/ip6_output.c | 2 +- net/ipv6/netfilter/ip6_queue.c | 2 +- net/ipv6/netfilter/ip6table_mangle.c | 9 ++++----- net/ipv6/route.c | 2 +- net/netfilter/nfnetlink_log.c | 4 ++-- net/netfilter/nfnetlink_queue.c | 8 ++++---- net/netfilter/xt_CONNMARK.c | 10 +++++----- net/netfilter/xt_MARK.c | 12 ++++++------ net/netfilter/xt_mark.c | 2 +- net/sched/Kconfig | 2 +- net/sched/cls_fw.c | 6 +----- net/sched/cls_u32.c | 2 +- net/sched/em_meta.c | 10 +++------- 28 files changed, 59 insertions(+), 68 deletions(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 7fc9a3aaa1c..e3ae544b395 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -216,7 +216,7 @@ enum { * @tail: Tail pointer * @end: End pointer * @destructor: Destruct function - * @nfmark: Can be used for communication between hooks + * @mark: Generic packet mark * @nfct: Associated connection, if any * @ipvs_property: skbuff is owned by ipvs * @nfctinfo: Relationship of this skb to the connection @@ -295,7 +295,6 @@ struct sk_buff { #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif - __u32 nfmark; #endif /* CONFIG_NETFILTER */ #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ @@ -310,6 +309,7 @@ struct sk_buff { __u32 secmark; #endif + __u32 mark; /* These elements must be at the end, see alloc_skb() for details. */ unsigned int truesize; diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index b54306a934e..2458638561c 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, int action = info->target & -16; if (action == MARK_SET_VALUE) - (*pskb)->nfmark = info->mark; + (*pskb)->mark = info->mark; else if (action == MARK_OR_VALUE) - (*pskb)->nfmark |= info->mark; + (*pskb)->mark |= info->mark; else if (action == MARK_AND_VALUE) - (*pskb)->nfmark &= info->mark; + (*pskb)->mark &= info->mark; else - (*pskb)->nfmark ^= info->mark; + (*pskb)->mark ^= info->mark; return info->target | -16; } diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index a6413e4b498..025869ee0b6 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c @@ -19,8 +19,8 @@ static int ebt_filter_mark(const struct sk_buff *skb, struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; if (info->bitmask & EBT_MARK_OR) - return !(!!(skb->nfmark & info->mask) ^ info->invert); - return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert); + return !(!!(skb->mark & info->mask) ^ info->invert); + return !(((skb->mark & info->mask) == info->mark) ^ info->invert); } static int ebt_mark_check(const char *tablename, unsigned int hookmask, diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 9f950db3b76..c1af68b5a29 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -168,7 +168,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, if (ub->qlen == 1) skb_set_timestamp(ub->skb, &pm->stamp); pm->data_len = copy_len; - pm->mark = skb->nfmark; + pm->mark = skb->mark; pm->hook = hooknr; if (uloginfo->prefix != NULL) strcpy(pm->prefix, uloginfo->prefix); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b8b10635804..b3dea1ef953 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -473,8 +473,8 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) #endif C(protocol); n->destructor = NULL; + C(mark); #ifdef CONFIG_NETFILTER - C(nfmark); C(nfct); nf_conntrack_get(skb->nfct); C(nfctinfo); @@ -534,8 +534,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->pkt_type = old->pkt_type; new->tstamp = old->tstamp; new->destructor = NULL; + new->mark = old->mark; #ifdef CONFIG_NETFILTER - new->nfmark = old->nfmark; new->nfct = old->nfct; nf_conntrack_get(old->nfct); new->nfctinfo = old->nfctinfo; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 23489f7232d..3482839af28 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1236,7 +1236,7 @@ static int dn_route_input_slow(struct sk_buff *skb) .saddr = cb->src, .scope = RT_SCOPE_UNIVERSE, #ifdef CONFIG_DECNET_ROUTE_FWMARK - .fwmark = skb->nfmark + .fwmark = skb->mark #endif } }, .iif = skb->dev->ifindex }; @@ -1458,7 +1458,7 @@ int dn_route_input(struct sk_buff *skb) (rt->fl.fld_dst == cb->dst) && (rt->fl.oif == 0) && #ifdef CONFIG_DECNET_ROUTE_FWMARK - (rt->fl.fld_fwmark == skb->nfmark) && + (rt->fl.fld_fwmark == skb->mark) && #endif (rt->fl.iif == cb->iif)) { rt->u.dst.lastuse = jiffies; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fc195a44fc2..23633bf042b 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -386,6 +386,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) dst_release(to->dst); to->dst = dst_clone(from->dst); to->dev = from->dev; + to->mark = from->mark; /* Copy the flags to each fragment. */ IPCB(to)->flags = IPCB(from)->flags; @@ -394,7 +395,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->tc_index = from->tc_index; #endif #ifdef CONFIG_NETFILTER - to->nfmark = from->nfmark; /* Connection association is same as pre-frag packet */ nf_conntrack_put(to->nfct); to->nfct = from->nfct; diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index 6ff05c3a32e..7de385267b3 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -84,7 +84,7 @@ tcp_conn_schedule(struct sk_buff *skb, } if (th->syn && - (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, + (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, skb->nh.iph->daddr, th->dest))) { if (ip_vs_todrop()) { /* diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 691c8b637b2..452cb9c384b 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -89,7 +89,7 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, return 0; } - if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, + if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, skb->nh.iph->daddr, uh->dest))) { if (ip_vs_todrop()) { /* diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index e2005c6810a..bfc8d753a23 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -28,7 +28,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; #ifdef CONFIG_IP_ROUTE_FWMARK - fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark; + fl.nl_u.ip4_u.fwmark = (*pskb)->mark; #endif if (ip_route_output_key(&rt, &fl) != 0) return -1; diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 97556cc2e4e..cd520df4dcf 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -243,7 +243,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->data_len = data_len; pmsg->timestamp_sec = entry->skb->tstamp.off_sec; pmsg->timestamp_usec = entry->skb->tstamp.off_usec; - pmsg->mark = entry->skb->nfmark; + pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 264763adc39..f0319e5ee43 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -76,7 +76,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) /* This packet will not be the same as the other: clear nf fields */ nf_reset(nskb); - nskb->nfmark = 0; + nskb->mark = 0; skb_init_secmark(nskb); tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 2b104ea54f4..dbd34783a64 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -239,7 +239,7 @@ static void ipt_ulog_packet(unsigned int hooknum, pm->data_len = copy_len; pm->timestamp_sec = skb->tstamp.off_sec; pm->timestamp_usec = skb->tstamp.off_usec; - pm->mark = skb->nfmark; + pm->mark = skb->mark; pm->hook = hooknum; if (prefix != NULL) strncpy(pm->prefix, prefix, sizeof(pm->prefix)); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index b91f3582359..62d4ccc259c 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -132,7 +132,7 @@ ipt_local_hook(unsigned int hook, unsigned int ret; u_int8_t tos; __be32 saddr, daddr; - unsigned long nfmark; + u_int32_t mark; /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) @@ -143,7 +143,7 @@ ipt_local_hook(unsigned int hook, } /* Save things which could affect route */ - nfmark = (*pskb)->nfmark; + mark = (*pskb)->mark; saddr = (*pskb)->nh.iph->saddr; daddr = (*pskb)->nh.iph->daddr; tos = (*pskb)->nh.iph->tos; @@ -154,7 +154,7 @@ ipt_local_hook(unsigned int hook, && ((*pskb)->nh.iph->saddr != saddr || (*pskb)->nh.iph->daddr != daddr #ifdef CONFIG_IP_ROUTE_FWMARK - || (*pskb)->nfmark != nfmark + || (*pskb)->mark != mark #endif || (*pskb)->nh.iph->tos != tos)) if (ip_route_me_harder(pskb, RTN_UNSPEC)) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 925ee4dfc32..4de3e38fa1a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1644,7 +1644,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -1790,7 +1790,7 @@ static inline int __mkroute_input(struct sk_buff *skb, rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -1921,7 +1921,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, .tos = tos, .scope = RT_SCOPE_UNIVERSE, #ifdef CONFIG_IP_ROUTE_FWMARK - .fwmark = skb->nfmark + .fwmark = skb->mark #endif } }, .iif = dev->ifindex }; @@ -2035,7 +2035,7 @@ local_input: rth->rt_dst = daddr; rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark= skb->nfmark; + rth->fl.fl4_fwmark= skb->mark; #endif rth->fl.fl4_src = saddr; rth->rt_src = saddr; @@ -2114,7 +2114,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.iif == iif && rth->fl.oif == 0 && #ifdef CONFIG_IP_ROUTE_FWMARK - rth->fl.fl4_fwmark == skb->nfmark && + rth->fl.fl4_fwmark == skb->mark && #endif rth->fl.fl4_tos == tos) { rth->u.dst.lastuse = jiffies; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 93330685adf..1bde3aca346 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -499,12 +499,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) dst_release(to->dst); to->dst = dst_clone(from->dst); to->dev = from->dev; + to->mark = from->mark; #ifdef CONFIG_NET_SCHED to->tc_index = from->tc_index; #endif #ifdef CONFIG_NETFILTER - to->nfmark = from->nfmark; /* Connection association is same as pre-frag packet */ nf_conntrack_put(to->nfct); to->nfct = from->nfct; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9fec832ee08..21908c9a10d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -241,7 +241,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->data_len = data_len; pmsg->timestamp_sec = entry->skb->tstamp.off_sec; pmsg->timestamp_usec = entry->skb->tstamp.off_usec; - pmsg->mark = entry->skb->nfmark; + pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 386ea260e76..6250e86a6dd 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -149,11 +149,10 @@ ip6t_local_hook(unsigned int hook, int (*okfn)(struct sk_buff *)) { - unsigned long nfmark; unsigned int ret; struct in6_addr saddr, daddr; u_int8_t hop_limit; - u_int32_t flowlabel; + u_int32_t flowlabel, mark; #if 0 /* root is playing with raw sockets. */ @@ -165,10 +164,10 @@ ip6t_local_hook(unsigned int hook, } #endif - /* save source/dest address, nfmark, hoplimit, flowlabel, priority, */ + /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); - nfmark = (*pskb)->nfmark; + mark = (*pskb)->mark; hop_limit = (*pskb)->nh.ipv6h->hop_limit; /* flowlabel and prio (includes version, which shouldn't change either */ @@ -179,7 +178,7 @@ ip6t_local_hook(unsigned int hook, if (ret != NF_DROP && ret != NF_STOLEN && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) - || (*pskb)->nfmark != nfmark + || (*pskb)->mark != mark || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e9c1fc5f21b..aaabb1fad1c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -712,7 +712,7 @@ void ip6_route_input(struct sk_buff *skb) .daddr = iph->daddr, .saddr = iph->saddr, #ifdef CONFIG_IPV6_ROUTE_FWMARK - .fwmark = skb->nfmark, + .fwmark = skb->mark, #endif .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, }, diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 856ed0d1997..bd3ffa6f1a6 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -501,8 +501,8 @@ __build_packet_message(struct nfulnl_instance *inst, #endif } - if (skb->nfmark) { - tmp_uint = htonl(skb->nfmark); + if (skb->mark) { + tmp_uint = htonl(skb->mark); NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 4ab7b1416bb..82e4454659b 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -480,8 +480,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, #endif } - if (entskb->nfmark) { - tmp_uint = htonl(entskb->nfmark); + if (entskb->mark) { + tmp_uint = htonl(entskb->mark); NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint); } @@ -834,8 +834,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, } if (nfqa[NFQA_MARK-1]) - entry->skb->nfmark = ntohl(*(__be32 *) - NFA_DATA(nfqa[NFQA_MARK-1])); + entry->skb->mark = ntohl(*(__be32 *) + NFA_DATA(nfqa[NFQA_MARK-1])); issue_verdict(entry, verdict); instance_put(queue); diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index c01524f817f..67ed5315299 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -42,7 +42,7 @@ target(struct sk_buff **pskb, { const struct xt_connmark_target_info *markinfo = targinfo; u_int32_t diff; - u_int32_t nfmark; + u_int32_t mark; u_int32_t newmark; u_int32_t ctinfo; u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); @@ -62,7 +62,7 @@ target(struct sk_buff **pskb, break; case XT_CONNMARK_SAVE: newmark = (*ctmark & ~markinfo->mask) | - ((*pskb)->nfmark & markinfo->mask); + ((*pskb)->mark & markinfo->mask); if (*ctmark != newmark) { *ctmark = newmark; #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) @@ -73,10 +73,10 @@ target(struct sk_buff **pskb, } break; case XT_CONNMARK_RESTORE: - nfmark = (*pskb)->nfmark; - diff = (*ctmark ^ nfmark) & markinfo->mask; + mark = (*pskb)->mark; + diff = (*ctmark ^ mark) & markinfo->mask; if (diff != 0) - (*pskb)->nfmark = nfmark ^ diff; + (*pskb)->mark = mark ^ diff; break; } } diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index c6e860a7114..0b48547e8d6 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c @@ -31,8 +31,8 @@ target_v0(struct sk_buff **pskb, { const struct xt_mark_target_info *markinfo = targinfo; - if((*pskb)->nfmark != markinfo->mark) - (*pskb)->nfmark = markinfo->mark; + if((*pskb)->mark != markinfo->mark) + (*pskb)->mark = markinfo->mark; return XT_CONTINUE; } @@ -54,16 +54,16 @@ target_v1(struct sk_buff **pskb, break; case XT_MARK_AND: - mark = (*pskb)->nfmark & markinfo->mark; + mark = (*pskb)->mark & markinfo->mark; break; case XT_MARK_OR: - mark = (*pskb)->nfmark | markinfo->mark; + mark = (*pskb)->mark | markinfo->mark; break; } - if((*pskb)->nfmark != mark) - (*pskb)->nfmark = mark; + if((*pskb)->mark != mark) + (*pskb)->mark = mark; return XT_CONTINUE; } diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index 934dddfbcd2..dfa1ee6914c 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c @@ -31,7 +31,7 @@ match(const struct sk_buff *skb, { const struct xt_mark_info *info = matchinfo; - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; + return ((skb->mark & info->mask) == info->mark) ^ info->invert; } static int diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8298ea9ffe1..b2437092978 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -320,7 +320,7 @@ config CLS_U32_PERF config CLS_U32_MARK bool "Netfilter marks support" - depends on NET_CLS_U32 && NETFILTER + depends on NET_CLS_U32 ---help--- Say Y here to be able to use netfilter marks as u32 key. diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index e54acc6bccc..f59a2c4aa03 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -101,11 +101,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, struct fw_head *head = (struct fw_head*)tp->root; struct fw_filter *f; int r; -#ifdef CONFIG_NETFILTER - u32 id = skb->nfmark & head->mask; -#else - u32 id = 0; -#endif + u32 id = skb->mark & head->mask; if (head != NULL) { for (f=head->ht[fw_hash(id)]; f; f=f->next) { diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 0a6cfa0005b..8b519480199 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -143,7 +143,7 @@ next_knode: #endif #ifdef CONFIG_CLS_U32_MARK - if ((skb->nfmark & n->mark.mask) != n->mark.val) { + if ((skb->mark & n->mark.mask) != n->mark.val) { n = n->next; goto next_knode; } else { diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 61e3b740ab1..d3ff3503326 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -208,13 +208,9 @@ META_COLLECTOR(int_maclen) * Netfilter **************************************************************************/ -META_COLLECTOR(int_nfmark) +META_COLLECTOR(int_mark) { -#ifdef CONFIG_NETFILTER - dst->value = skb->nfmark; -#else - dst->value = 0; -#endif + dst->value = skb->mark; } /************************************************************************** @@ -490,7 +486,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { [META_ID(PKTLEN)] = META_FUNC(int_pktlen), [META_ID(DATALEN)] = META_FUNC(int_datalen), [META_ID(MACLEN)] = META_FUNC(int_maclen), - [META_ID(NFMARK)] = META_FUNC(int_nfmark), + [META_ID(NFMARK)] = META_FUNC(int_mark), [META_ID(TCINDEX)] = META_FUNC(int_tcindex), [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid), [META_ID(RTIIF)] = META_FUNC(int_rtiif), -- cgit v1.2.3 From a11d206d0f88e092419877c7f706cafb5e1c2e57 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 4 Nov 2006 20:11:37 +0900 Subject: [IPV6]: Per-interface statistics support. For IP MIB (RFC4293). Signed-off-by: YOSHIFUJI Hideaki --- include/net/if_inet6.h | 1 + include/net/ipv6.h | 21 ++++++++++++--- net/ipv6/exthdrs.c | 57 ++++++++++++++++++++++++++-------------- net/ipv6/icmp.c | 3 ++- net/ipv6/ip6_input.c | 40 +++++++++++++++++++--------- net/ipv6/ip6_output.c | 71 +++++++++++++++++++++++++++++--------------------- net/ipv6/mcast.c | 20 +++++++++----- net/ipv6/ndisc.c | 8 +++--- net/ipv6/netfilter.c | 2 +- net/ipv6/proc.c | 7 +++++ net/ipv6/raw.c | 4 +-- net/ipv6/reassembly.c | 65 +++++++++++++++++++++++++++------------------ net/ipv6/route.c | 4 +-- 13 files changed, 195 insertions(+), 108 deletions(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 34489c13c11..3ec7d07346d 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -152,6 +152,7 @@ struct ifacaddr6 struct ipv6_devstat { struct proc_dir_entry *proc_dir_entry; + DEFINE_SNMP_STAT(struct ipstats_mib, ipv6); DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); }; diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0b8c9b990ac..3c266ad99a0 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -113,9 +113,24 @@ extern int sysctl_mld_max_msf; /* MIBs */ DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); -#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field) -#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field) -#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field) +#define IP6_INC_STATS(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS(_idev->stats.ipv6, field); \ + SNMP_INC_STATS(ipv6_statistics, field); \ +}) +#define IP6_INC_STATS_BH(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS_BH(_idev->stats.ipv6, field); \ + SNMP_INC_STATS_BH(ipv6_statistics, field); \ +}) +#define IP6_INC_STATS_USER(idev,field) ({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_INC_STATS_USER(_idev->stats.ipv6, field); \ + SNMP_INC_STATS_USER(ipv6_statistics, field); \ +}) DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); #define ICMP6_INC_STATS(idev, field) ({ \ struct inet6_dev *_idev = (idev); \ diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 88c96b10684..27829cc4ce8 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) #ifdef CONFIG_IPV6_MIP6 __u16 dstbuf; #endif + struct dst_entry *dst; if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) dstbuf = opt->dst1; #endif + dst = dst_clone(skb->dst); if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { + dst_release(dst); skb = *skbp; skb->h.raw += ((skb->h.raw[1]+1)<<3); opt = IP6CB(skb); @@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) return 1; } - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); + dst_release(dst); return -1; } @@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } @@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || skb->pkt_type != PACKET_HOST) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -388,7 +395,8 @@ looped_back: * processed by own */ if (!addr) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -410,7 +418,8 @@ looped_back: switch (hdr->type) { case IPV6_SRCRT_TYPE_0: if (hdr->hdrlen & 0x01) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); return -1; } @@ -419,14 +428,16 @@ looped_back: case IPV6_SRCRT_TYPE_2: /* Silently discard invalid RTH type 2 */ if (hdr->hdrlen != 2 || hdr->segments_left != 1) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; } break; #endif default: - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); return -1; } @@ -439,7 +450,8 @@ looped_back: n = hdr->hdrlen >> 1; if (hdr->segments_left > n) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); return -1; } @@ -449,12 +461,14 @@ looped_back: */ if (skb_cloned(skb)) { struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); - kfree_skb(skb); /* the copy is a forwarded packet */ if (skb2 == NULL) { - IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); return -1; } + kfree_skb(skb); *skbp = skb = skb2; opt = IP6CB(skb2); hdr = (struct ipv6_rt_hdr *) skb2->h.raw; @@ -475,12 +489,14 @@ looped_back: if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, (xfrm_address_t *)&skb->nh.ipv6h->saddr, IPPROTO_ROUTING) < 0) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } if (!ipv6_chk_home_addr(addr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -491,7 +507,8 @@ looped_back: } if (ipv6_addr_is_multicast(addr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } @@ -510,7 +527,8 @@ looped_back: if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->nh.ipv6h->hop_limit <= 1) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); kfree_skb(skb); @@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]); - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); goto drop; } pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); if (pkt_len <= IPV6_MAXPLEN) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); return 0; } if (skb->nh.ipv6h->payload_len) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); return 0; } if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 81bd45b26c9..52cca93ff2f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -177,7 +177,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, */ dst = ip6_route_output(sk, fl); if (dst->error) { - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(dst), + IPSTATS_MIB_OUTNOROUTES); } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { res = 1; } else { diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index ebf54ae90a0..ad0b8abcdf4 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -60,14 +60,22 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt { struct ipv6hdr *hdr; u32 pkt_len; + struct inet6_dev *idev; - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; + if (skb->pkt_type == PACKET_OTHERHOST) { + kfree_skb(skb); + return 0; + } + + rcu_read_lock(); - IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); + idev = __in6_dev_get(skb->dev); + + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); + rcu_read_unlock(); goto out; } @@ -104,7 +112,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); goto drop; } hdr = skb->nh.ipv6h; @@ -112,17 +120,21 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->nexthdr == NEXTHDR_HOP) { if (ipv6_parse_hopopts(&skb) < 0) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); + rcu_read_unlock(); return 0; } } + rcu_read_unlock(); + return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); truncated: - IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); err: - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); drop: + rcu_read_unlock(); kfree_skb(skb); out: return 0; @@ -140,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) unsigned int nhoff; int nexthdr; u8 hash; + struct inet6_dev *idev; /* * Parse extension headers @@ -147,6 +160,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) rcu_read_lock(); resubmit: + idev = ip6_dst_idev(skb->dst); if (!pskb_pull(skb, skb->h.raw - skb->data)) goto discard; nhoff = IP6CB(skb)->nhoff; @@ -185,24 +199,24 @@ resubmit: if (ret > 0) goto resubmit; else if (ret == 0) - IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); } else { if (!raw_sk) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_UNK_NEXTHDR, nhoff, skb->dev); } } else - IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); kfree_skb(skb); } rcu_read_unlock(); return 0; discard: - IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); rcu_read_unlock(); kfree_skb(skb); return 0; @@ -219,7 +233,7 @@ int ip6_mc_input(struct sk_buff *skb) struct ipv6hdr *hdr; int deliver; - IP6_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = skb->nh.ipv6h; deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 1bde3aca346..85f88927049 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb) } else if (dst->neighbour) return dst->neighbour->output(skb); - IP6_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); return -EINVAL; @@ -118,6 +118,7 @@ static int ip6_output2(struct sk_buff *skb) if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; + struct inet6_dev *idev = ip6_dst_idev(skb->dst); if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, @@ -133,13 +134,13 @@ static int ip6_output2(struct sk_buff *skb) ip6_dev_loopback_xmit); if (skb->nh.ipv6h->hop_limit == 0) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return 0; } } - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); @@ -182,12 +183,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (skb_headroom(skb) < head_room) { struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); - kfree_skb(skb); - skb = skb2; - if (skb == NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + if (skb2 == NULL) { + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); return -ENOBUFS; } + kfree_skb(skb); + skb = skb2; if (sk) skb_set_owner_w(skb, sk); } @@ -230,7 +233,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, mtu = dst_mtu(dst); if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTREQUESTS); return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); } @@ -239,7 +243,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } @@ -373,7 +377,7 @@ int ip6_forward(struct sk_buff *skb) goto error; if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } @@ -406,7 +410,7 @@ int ip6_forward(struct sk_buff *skb) skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -ETIMEDOUT; @@ -419,13 +423,13 @@ int ip6_forward(struct sk_buff *skb) if (proxied > 0) return ip6_input(skb); else if (proxied < 0) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } } if (!xfrm6_route_forward(skb)) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } dst = skb->dst; @@ -464,14 +468,14 @@ int ip6_forward(struct sk_buff *skb) /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); - IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS); - IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } if (skb_cow(skb, dst->dev->hard_header_len)) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); goto drop; } @@ -481,11 +485,11 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; - IP6_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); error: - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); drop: kfree_skb(skb); return -EINVAL; @@ -622,7 +626,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) tmp_hdr = kmalloc(hlen, GFP_ATOMIC); if (!tmp_hdr) { - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } @@ -643,7 +647,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb->data_len = first_len - skb_headlen(skb); skb->len = first_len; skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); - + + dst_hold(&rt->u.dst); for (;;) { /* Prepare header of the next frame, @@ -667,7 +672,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) err = output(skb); if(!err) - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES); if (err || !frag) break; @@ -680,7 +685,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) kfree(tmp_hdr); if (err == 0) { - IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS); + dst_release(&rt->u.dst); return 0; } @@ -690,7 +696,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) frag = skb; } - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS); + dst_release(&rt->u.dst); return err; } @@ -723,7 +730,8 @@ slow_path: if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGFAILS); err = -ENOMEM; goto fail; } @@ -784,15 +792,17 @@ slow_path: if (err) goto fail; - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES); } + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGOKS); kfree_skb(skb); - IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); return err; fail: + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); - IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); return err; } @@ -1265,7 +1275,7 @@ alloc_new_skb: return 0; error: inet->cork.length -= length; - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; } @@ -1326,7 +1336,7 @@ int ip6_push_pending_frames(struct sock *sk) skb->priority = sk->sk_priority; skb->dst = dst_clone(&rt->u.dst); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); if (err) { if (err > 0) @@ -1357,7 +1367,8 @@ void ip6_flush_pending_frames(struct sock *sk) struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9055979083b..c006d02be8b 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb) struct inet6_dev *idev = in6_dev_get(skb->dev); int err; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - sizeof(struct ipv6hdr); mldlen = skb->tail - skb->h.raw; @@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb) mld_dev_queue_xmit); if (!err) { ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } else - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); if (likely(idev != NULL)) in6_dev_put(idev); @@ -1763,7 +1763,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_PADN, 0 }; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + rcu_read_lock(); + IP6_INC_STATS(__in6_dev_get(dev), + IPSTATS_MIB_OUTREQUESTS); + rcu_read_unlock(); snd_addr = addr; if (type == ICMPV6_MGM_REDUCTION) { snd_addr = &all_routers; @@ -1777,7 +1780,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); if (skb == NULL) { - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + rcu_read_lock(); + IP6_INC_STATS(__in6_dev_get(dev), + IPSTATS_MIB_OUTDISCARDS); + rcu_read_unlock(); return; } @@ -1816,9 +1822,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) else ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); } else - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); if (likely(idev != NULL)) in6_dev_put(idev); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 89d527ebd7f..1342be8b4cd 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -515,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); @@ -601,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, /* send it! */ skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); @@ -676,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, /* send it! */ skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); @@ -1512,7 +1512,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, buff->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); if (!err) { ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 580b1aba672..646a47456fd 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -31,7 +31,7 @@ int ip6_route_me_harder(struct sk_buff *skb) #endif if (dst->error) { - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); dst_release(dst); return -EINVAL; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index efee7a6301a..4158d386b0a 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -161,6 +161,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) if (idev) { seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); + snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); } else { snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); @@ -281,6 +282,9 @@ int snmp6_alloc_dev(struct inet6_dev *idev) if (!idev || !idev->dev) return -EINVAL; + if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), + __alignof__(struct ipstats_mib)) < 0) + goto err_ip; if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), __alignof__(struct icmpv6_mib)) < 0) goto err_icmp; @@ -288,12 +292,15 @@ int snmp6_alloc_dev(struct inet6_dev *idev) return 0; err_icmp: + snmp6_mib_free((void **)idev->stats.ipv6); +err_ip: return err; } int snmp6_free_dev(struct inet6_dev *idev) { snmp6_mib_free((void **)idev->stats.icmpv6); + snmp6_mib_free((void **)idev->stats.ipv6); return 0; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6bc66552442..18a90075f94 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -586,7 +586,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, if (err) goto error_fault; - IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) @@ -600,7 +600,7 @@ error_fault: err = -EFAULT; kfree_skb(skb); error: - IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f39bbedd132..3af0d5a6cee 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -257,7 +258,7 @@ static __inline__ void fq_kill(struct frag_queue *fq) } } -static void ip6_evictor(void) +static void ip6_evictor(struct inet6_dev *idev) { struct frag_queue *fq; struct list_head *tmp; @@ -284,14 +285,14 @@ static void ip6_evictor(void) spin_unlock(&fq->lock); fq_put(fq, &work); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); } } static void ip6_frag_expire(unsigned long data) { struct frag_queue *fq = (struct frag_queue *) data; - struct net_device *dev; + struct net_device *dev = NULL; spin_lock(&fq->lock); @@ -300,17 +301,19 @@ static void ip6_frag_expire(unsigned long data) fq_kill(fq); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + dev = dev_get_by_index(fq->iif); + if (!dev) + goto out; + + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + rcu_read_unlock(); /* Don't send error if the first segment did not arrive. */ if (!(fq->last_in&FIRST_IN) || !fq->fragments) goto out; - dev = dev_get_by_index(fq->iif); - if (!dev) - goto out; - /* But use as source device on which LAST ARRIVED segment was received. And do not use fq->dev @@ -318,8 +321,9 @@ static void ip6_frag_expire(unsigned long data) */ fq->fragments->dev = dev; icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); - dev_put(dev); out: + if (dev) + dev_put(dev); spin_unlock(&fq->lock); fq_put(fq, NULL); } @@ -366,7 +370,8 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) static struct frag_queue * -ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) +ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst, + struct inet6_dev *idev) { struct frag_queue *fq; @@ -386,12 +391,13 @@ ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) return ip6_frag_intern(fq); oom: - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); return NULL; } static __inline__ struct frag_queue * -fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) +fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst, + struct inet6_dev *idev) { struct frag_queue *fq; struct hlist_node *n; @@ -410,7 +416,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) } read_unlock(&ip6_frag_lock); - return ip6_frag_create(id, src, dst); + return ip6_frag_create(id, src, dst, idev); } @@ -428,7 +434,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); if ((unsigned int)end > IPV6_MAXPLEN) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); return; } @@ -455,7 +462,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, /* RFC2460 says always send parameter problem in * this case. -DaveM */ - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, offsetof(struct ipv6hdr, payload_len)); return; @@ -571,7 +579,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, return; err: - IP6_INC_STATS(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); } @@ -665,7 +673,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, if (head->ip_summed == CHECKSUM_COMPLETE) head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); + rcu_read_unlock(); fq->fragments = NULL; return 1; @@ -677,7 +687,9 @@ out_oom: if (net_ratelimit()) printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); out_fail: - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + rcu_read_lock(); + IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + rcu_read_unlock(); return -1; } @@ -691,16 +703,16 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) hdr = skb->nh.ipv6h; - IP6_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); /* Jumbo payload inhibits frag. header */ if (hdr->payload_len==0) { - IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); return -1; } if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { - IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); return -1; } @@ -711,16 +723,17 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) if (!(fhdr->frag_off & htons(0xFFF9))) { /* It is not a fragmented frame */ skb->h.raw += sizeof(struct frag_hdr); - IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; return 1; } if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) - ip6_evictor(); + ip6_evictor(ip6_dst_idev(skb->dst)); - if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) { + if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, + ip6_dst_idev(skb->dst))) != NULL) { int ret = -1; spin_lock(&fq->lock); @@ -736,7 +749,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) return ret; } - IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index eb78b525224..0ad07c9087a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1749,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) { int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) - IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); kfree_skb(skb); return 0; -- cgit v1.2.3 From af879cc704372ef762584e916129d19ffb39e844 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:14:37 -0200 Subject: [IPV6]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/ipv6.ko.before /tmp/ipv6.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/ip6_output.c: ip6_output | -52 ip6_append_data | +2 2 functions changed, 2 bytes added, 52 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/addrconf.c: addrconf_sysctl_register | -27 1 function changed, 27 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/tcp_ipv6.c: tcp_v6_syn_recv_sock | -32 tcp_v6_parse_md5_keys | -24 2 functions changed, 56 bytes removed /tmp/ipv6.ko.after: 5 functions changed, 2 bytes added, 135 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv6/addrconf.c | 3 +-- net/ipv6/ah6.c | 3 +-- net/ipv6/ip6_output.c | 3 +-- net/ipv6/tcp_ipv6.c | 9 +++------ 4 files changed, 6 insertions(+), 12 deletions(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b41c5d8b278..a5e8d207a51 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3969,10 +3969,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf struct addrconf_sysctl_table *t; char *dev_name = NULL; - t = kmalloc(sizeof(*t), GFP_KERNEL); + t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL); if (t == NULL) return; - memcpy(t, &addrconf_sysctl, sizeof(*t)); for (i=0; t->addrconf_vars[i].data; i++) { t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; t->addrconf_vars[i].de = NULL; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2d9e495cf69..12c5a4dec09 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -354,10 +354,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) if (!pskb_may_pull(skb, ah_hlen)) goto out; - tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); if (!tmp_hdr) goto out; - memcpy(tmp_hdr, skb->nh.raw, hdr_len); if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) goto free_out; skb->nh.ipv6h->priority = 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 85f88927049..e05ecbb1412 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -624,14 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_shinfo(skb)->frag_list = NULL; /* BUILD HEADER */ - tmp_hdr = kmalloc(hlen, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); if (!tmp_hdr) { IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } *prevhdr = NEXTHDR_FRAGMENT; - memcpy(tmp_hdr, skb->nh.raw, hlen); __skb_pull(skb, hlen); fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); skb->nh.raw = __skb_push(skb, hlen); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 147ce499f50..d2170da77e5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -720,10 +720,9 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, tp->md5sig_info = p; } - newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); if (!newkey) return -ENOMEM; - memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], newkey, cmd.tcpm_keylen); @@ -1503,12 +1502,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * memory, then we end up not copying the key * across. Shucks. */ - char *newkey = kmalloc(key->keylen, GFP_ATOMIC); - if (newkey) { - memcpy(newkey, key->key, key->keylen); + char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); + if (newkey != NULL) tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, newkey, key->keylen); - } } #endif -- cgit v1.2.3