From 69dc7623760bee4f15a3096616a328cb80df3c19 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 13 Nov 2012 09:53:26 +0800 Subject: [PATCH] --- yaml --- r: 351359 b: refs/heads/master c: 569174433d3bd96e206a4b5969a4498371c70d16 h: refs/heads/master i: 351357: 394722a8cc57a825ca5ad2372344b2977dfe28a2 351355: 408c1e11961497091c555d57c89ea4124d4d8d83 351351: 59311f6ff6e7277d09e3e4df20375edd2c5d8193 351343: 466ce3b487b74d999e9329ebe25e6b85390be1c9 351327: df5cafbe600c6a06ca02f201ccebd48855f1d012 351295: 71a52cb469f9b924cc9d687ee5ece33ae22a8a1e 351231: e0521f96fc912b2c74b6905cb729e1213fc64e5c v: v3 --- [refs] | 2 +- trunk/include/linux/ipv6.h | 8 ++++++-- trunk/include/net/addrconf.h | 26 +------------------------ trunk/include/net/ipv6.h | 14 ------------- trunk/include/uapi/linux/ipv6.h | 2 -- trunk/net/batman-adv/main.h | 4 +--- trunk/net/ipv6/datagram.c | 12 +++++------- trunk/net/ipv6/exthdrs.c | 3 +-- trunk/net/ipv6/ip6_gre.c | 6 ++++-- trunk/net/ipv6/ip6_input.c | 26 ++++++++++++++++++++----- trunk/net/ipv6/ip6_output.c | 8 +++++--- trunk/net/ipv6/ip6_tunnel.c | 4 +++- trunk/net/ipv6/mcast.c | 27 ++++++++++++++++++++++++++ trunk/net/ipv6/netfilter/ip6t_REJECT.c | 2 +- trunk/net/ipv6/route.c | 17 +++++++++++----- trunk/net/ipv6/tcp_ipv6.c | 6 +++--- trunk/net/ipv6/xfrm6_tunnel.c | 2 +- 17 files changed, 92 insertions(+), 77 deletions(-) diff --git a/[refs] b/[refs] index 1a9270af096e..4f974ada1430 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dd3332bfcb2223458f553f341d3388cb84040e6a +refs/heads/master: 569174433d3bd96e206a4b5969a4498371c70d16 diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index e971e3742172..faed1e357dd6 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -77,6 +77,11 @@ static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb) return (struct ipv6hdr *)skb_transport_header(skb); } +static inline __u8 ipv6_tclass(const struct ipv6hdr *iph) +{ + return (ntohl(*(__be32 *)iph) >> 20) & 0xff; +} + /* This structure contains results of exthdrs parsing as offsets from skb->nh. @@ -84,7 +89,7 @@ static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb) struct inet6_skb_parm { int iif; - __be16 ra; + __u16 ra; __u16 hop; __u16 dst0; __u16 srcrt; @@ -100,7 +105,6 @@ struct inet6_skb_parm { #define IP6SKB_XFRM_TRANSFORMED 1 #define IP6SKB_FORWARDED 2 #define IP6SKB_REROUTED 4 -#define IP6SKB_ROUTERALERT 8 }; #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) diff --git a/trunk/include/net/addrconf.h b/trunk/include/net/addrconf.h index 7cd14c007fc5..df4ef9453384 100644 --- a/trunk/include/net/addrconf.h +++ b/trunk/include/net/addrconf.h @@ -150,31 +150,7 @@ extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); extern bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, const struct in6_addr *src_addr); - -/* - * identify MLD packets for MLD filter exceptions - */ -static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset) -{ - struct icmp6hdr *hdr; - - if (nexthdr != IPPROTO_ICMPV6 || - !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr))) - return false; - - hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset); - - switch (hdr->icmp6_type) { - case ICMPV6_MGM_QUERY: - case ICMPV6_MGM_REPORT: - case ICMPV6_MGM_REDUCTION: - case ICMPV6_MLD2_REPORT: - return true; - default: - break; - } - return false; -} +extern bool ipv6_is_mld(struct sk_buff *skb, int nexthdr); extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao); diff --git a/trunk/include/net/ipv6.h b/trunk/include/net/ipv6.h index ed672080c690..5af66b26ebdd 100644 --- a/trunk/include/net/ipv6.h +++ b/trunk/include/net/ipv6.h @@ -546,20 +546,6 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); -/* - * Header manipulation - */ -static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass, - __be32 flowlabel) -{ - *(__be32 *)hdr = ntohl(0x60000000 | (tclass << 20)) | flowlabel; -} - -static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) -{ - return *(__be32 *)hdr & IPV6_FLOWINFO_MASK; -} - /* * Prototypes exported by ipv6 */ diff --git a/trunk/include/uapi/linux/ipv6.h b/trunk/include/uapi/linux/ipv6.h index 4bda4cf5b0f5..5a2991cf0251 100644 --- a/trunk/include/uapi/linux/ipv6.h +++ b/trunk/include/uapi/linux/ipv6.h @@ -63,8 +63,6 @@ struct ipv6_opt_hdr { #define ipv6_destopt_hdr ipv6_opt_hdr #define ipv6_hopopt_hdr ipv6_opt_hdr -/* Router Alert option values (RFC2711) */ -#define IPV6_OPT_ROUTERALERT_MLD 0x0000 /* MLD(RFC2710) */ /* * routing header type 0 (used in cmsghdr struct) diff --git a/trunk/net/batman-adv/main.h b/trunk/net/batman-adv/main.h index 2f85577086a7..c4fe41f7c2f0 100644 --- a/trunk/net/batman-adv/main.h +++ b/trunk/net/batman-adv/main.h @@ -276,9 +276,7 @@ static inline bool batadv_has_timed_out(unsigned long timestamp, static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx, size_t count) { - int cpu = get_cpu(); - per_cpu_ptr(bat_priv->bat_counters, cpu)[idx] += count; - put_cpu(); + this_cpu_add(bat_priv->bat_counters[idx], count); } #define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1) diff --git a/trunk/net/ipv6/datagram.c b/trunk/net/ipv6/datagram.c index 33be36398a78..56b692bb94a7 100644 --- a/trunk/net/ipv6/datagram.c +++ b/trunk/net/ipv6/datagram.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -361,7 +360,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) struct ipv6hdr, daddr); sin->sin6_addr = ip6h->daddr; if (np->sndflow) - sin->sin6_flowinfo = ip6_flowinfo(ip6h); + sin->sin6_flowinfo = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK; if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) sin->sin6_scope_id = IP6CB(skb)->iif; } else { @@ -488,14 +487,13 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) } if (np->rxopt.bits.rxtclass) { - int tclass = ipv6_get_dsfield(ipv6_hdr(skb)); + int tclass = ipv6_tclass(ipv6_hdr(skb)); put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); } - if (np->rxopt.bits.rxflow) { - __be32 flowinfo = ip6_flowinfo((struct ipv6hdr *)nh); - if (flowinfo) - put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); + if (np->rxopt.bits.rxflow && (*(__be32 *)nh & IPV6_FLOWINFO_MASK)) { + __be32 flowinfo = *(__be32 *)nh & IPV6_FLOWINFO_MASK; + put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); } /* HbH is allowed only once */ diff --git a/trunk/net/ipv6/exthdrs.c b/trunk/net/ipv6/exthdrs.c index 07a7d65a7cb6..473f628f9f20 100644 --- a/trunk/net/ipv6/exthdrs.c +++ b/trunk/net/ipv6/exthdrs.c @@ -553,8 +553,7 @@ static bool ipv6_hop_ra(struct sk_buff *skb, int optoff) const unsigned char *nh = skb_network_header(skb); if (nh[optoff + 1] == 2) { - IP6CB(skb)->flags |= IP6SKB_ROUTERALERT; - memcpy(&IP6CB(skb)->ra, nh + optoff + 2, sizeof(IP6CB(skb)->ra)); + IP6CB(skb)->ra = optoff; return true; } LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", diff --git a/trunk/net/ipv6/ip6_gre.c b/trunk/net/ipv6/ip6_gre.c index db91fe3466a3..c727e4712751 100644 --- a/trunk/net/ipv6/ip6_gre.c +++ b/trunk/net/ipv6/ip6_gre.c @@ -772,7 +772,9 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, * Push down and install the IP header. */ ipv6h = ipv6_hdr(skb); - ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); + *(__be32 *)ipv6h = fl6->flowlabel | htonl(0x60000000); + dsfield = INET_ECN_encapsulate(0, dsfield); + ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); ipv6h->hop_limit = tunnel->parms.hop_limit; ipv6h->nexthdr = proto; ipv6h->saddr = fl6->saddr; @@ -1238,7 +1240,7 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); __be16 *p = (__be16 *)(ipv6h+1); - ip6_flow_hdr(ipv6h, 0, t->fl.u.ip6.flowlabel); + *(__be32 *)ipv6h = t->fl.u.ip6.flowlabel | htonl(0x60000000); ipv6h->hop_limit = t->parms.hop_limit; ipv6h->nexthdr = NEXTHDR_GRE; ipv6h->saddr = t->parms.laddr; diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index 4ac5bf30e16a..a52d864d562b 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -212,7 +212,7 @@ static int ip6_input_finish(struct sk_buff *skb) if (ipv6_addr_is_multicast(&hdr->daddr) && !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, &hdr->saddr) && - !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) + !ipv6_is_mld(skb, nexthdr)) goto discard; } if (!(ipprot->flags & INET6_PROTO_NOPOLICY) && @@ -280,8 +280,10 @@ int ip6_mc_input(struct sk_buff *skb) struct inet6_skb_parm *opt = IP6CB(skb); /* Check for MLD */ - if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) { + if (unlikely(opt->ra)) { /* Check if this is a mld message */ + u8 *ptr = skb_network_header(skb) + opt->ra; + struct icmp6hdr *icmp6; u8 nexthdr = hdr->nexthdr; __be16 frag_off; int offset; @@ -289,7 +291,7 @@ int ip6_mc_input(struct sk_buff *skb) /* Check if the value of Router Alert * is for MLD (0x0000). */ - if (opt->ra == htons(IPV6_OPT_ROUTERALERT_MLD)) { + if ((ptr[2] | ptr[3]) == 0) { deliver = false; if (!ipv6_ext_hdr(nexthdr)) { @@ -301,10 +303,24 @@ int ip6_mc_input(struct sk_buff *skb) if (offset < 0) goto out; - if (!ipv6_is_mld(skb, nexthdr, offset)) + if (nexthdr != IPPROTO_ICMPV6) goto out; - deliver = true; + if (!pskb_may_pull(skb, (skb_network_header(skb) + + offset + 1 - skb->data))) + goto out; + + icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); + + switch (icmp6->icmp6_type) { + case ICMPV6_MGM_QUERY: + case ICMPV6_MGM_REPORT: + case ICMPV6_MGM_REDUCTION: + case ICMPV6_MLD2_REPORT: + deliver = true; + break; + } + goto out; } /* unknown RA - process it normally */ } diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 9250c696de9d..5552d13ae92f 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -216,7 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); - ip6_flow_hdr(hdr, tclass, fl6->flowlabel); + *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel; hdr->payload_len = htons(seg_len); hdr->nexthdr = proto; @@ -267,7 +267,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, skb_put(skb, sizeof(struct ipv6hdr)); hdr = ipv6_hdr(skb); - ip6_flow_hdr(hdr, 0, 0); + *(__be32*)hdr = htonl(0x60000000); hdr->payload_len = htons(len); hdr->nexthdr = proto; @@ -1548,7 +1548,9 @@ int ip6_push_pending_frames(struct sock *sk) skb_reset_network_header(skb); hdr = ipv6_hdr(skb); - ip6_flow_hdr(hdr, np->cork.tclass, fl6->flowlabel); + *(__be32*)hdr = fl6->flowlabel | + htonl(0x60000000 | ((int)np->cork.tclass << 20)); + hdr->hop_limit = np->cork.hop_limit; hdr->nexthdr = proto; hdr->saddr = fl6->saddr; diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index fff83cbc197f..a14f28b280f5 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -1030,7 +1030,9 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, skb_push(skb, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); ipv6h = ipv6_hdr(skb); - ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); + *(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000); + dsfield = INET_ECN_encapsulate(0, dsfield); + ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); ipv6h->hop_limit = t->parms.hop_limit; ipv6h->nexthdr = proto; ipv6h->saddr = fl6->saddr; diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 8237ee15eafd..28dfa5f3801f 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -934,6 +934,33 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) return err; } +/* + * identify MLD packets for MLD filter exceptions + */ +bool ipv6_is_mld(struct sk_buff *skb, int nexthdr) +{ + struct icmp6hdr *pic; + + if (nexthdr != IPPROTO_ICMPV6) + return false; + + if (!pskb_may_pull(skb, sizeof(struct icmp6hdr))) + return false; + + pic = icmp6_hdr(skb); + + switch (pic->icmp6_type) { + case ICMPV6_MGM_QUERY: + case ICMPV6_MGM_REPORT: + case ICMPV6_MGM_REDUCTION: + case ICMPV6_MLD2_REPORT: + return true; + default: + break; + } + return false; +} + /* * check if the interface/address pair is valid */ diff --git a/trunk/net/ipv6/netfilter/ip6t_REJECT.c b/trunk/net/ipv6/netfilter/ip6t_REJECT.c index 8e75b6f3db91..fd4fb34c51c7 100644 --- a/trunk/net/ipv6/netfilter/ip6t_REJECT.c +++ b/trunk/net/ipv6/netfilter/ip6t_REJECT.c @@ -126,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) skb_put(nskb, sizeof(struct ipv6hdr)); skb_reset_network_header(nskb); ip6h = ipv6_hdr(nskb); - ip6_flow_hdr(ip6h, tclass, 0); + *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); ip6h->hop_limit = ip6_dst_hoplimit(dst); ip6h->nexthdr = IPPROTO_TCP; ip6h->saddr = oip6h->daddr; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 34f392f050c1..621b68ecf16f 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -388,8 +388,15 @@ static int rt6_info_hash_nhsfn(unsigned int candidate_count, { unsigned int val = fl6->flowi6_proto; - val ^= ipv6_addr_hash(&fl6->daddr); - val ^= ipv6_addr_hash(&fl6->saddr); + val ^= (__force u32)fl6->daddr.s6_addr32[0]; + val ^= (__force u32)fl6->daddr.s6_addr32[1]; + val ^= (__force u32)fl6->daddr.s6_addr32[2]; + val ^= (__force u32)fl6->daddr.s6_addr32[3]; + + val ^= (__force u32)fl6->saddr.s6_addr32[0]; + val ^= (__force u32)fl6->saddr.s6_addr32[1]; + val ^= (__force u32)fl6->saddr.s6_addr32[2]; + val ^= (__force u32)fl6->saddr.s6_addr32[3]; /* Work only if this not encapsulated */ switch (fl6->flowi6_proto) { @@ -987,7 +994,7 @@ void ip6_route_input(struct sk_buff *skb) .flowi6_iif = skb->dev->ifindex, .daddr = iph->daddr, .saddr = iph->saddr, - .flowlabel = ip6_flowinfo(iph), + .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, .flowi6_mark = skb->mark, .flowi6_proto = iph->nexthdr, }; @@ -1152,7 +1159,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, fl6.flowi6_flags = 0; fl6.daddr = iph->daddr; fl6.saddr = iph->saddr; - fl6.flowlabel = ip6_flowinfo(iph); + fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK; dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) @@ -1180,7 +1187,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) fl6.flowi6_flags = 0; fl6.daddr = iph->daddr; fl6.saddr = iph->saddr; - fl6.flowlabel = ip6_flowinfo(iph); + fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK; dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 3701c3c6e2eb..3164ad272a74 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -1163,7 +1163,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newnp->opt = NULL; newnp->mcast_oif = inet6_iif(skb); newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; - newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); + newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); /* * No need to charge this sock to the relevant IPv6 refcnt debug socks count @@ -1243,7 +1243,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newnp->opt = NULL; newnp->mcast_oif = inet6_iif(skb); newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; - newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); + newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); /* Clone native IPv6 options from listening socket (if any) @@ -1456,7 +1456,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; if (np->rxopt.bits.rxtclass) - np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); + np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); if (ipv6_opt_accepted(sk, opt_skb)) { skb_set_owner_r(opt_skb, sk); opt_skb = xchg(&np->pktoptions, opt_skb); diff --git a/trunk/net/ipv6/xfrm6_tunnel.c b/trunk/net/ipv6/xfrm6_tunnel.c index babd1674388a..ee5a7065aacc 100644 --- a/trunk/net/ipv6/xfrm6_tunnel.c +++ b/trunk/net/ipv6/xfrm6_tunnel.c @@ -72,7 +72,7 @@ static inline unsigned int xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *ad { unsigned int h; - h = ipv6_addr_hash((const struct in6_addr *)addr); + h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]); h ^= h >> 16; h ^= h >> 8; h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1;