Commit b6a7719a authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller

ipv4: hash net ptr into fragmentation bucket selection

As namespaces are sometimes used with overlapping ip address ranges,
we should also use the namespace as input to the hash to select the ip
fragmentation counter bucket.

Cc: Eric Dumazet <edumazet@google.com>
Cc: Flavio Leitner <fbl@redhat.com>
Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8fa38a38
...@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) ...@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
nf_reset(skb); nf_reset(skb);
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
ip_select_ident(skb, NULL); ip_select_ident(sock_net(sk), skb, NULL);
ip_send_check(iph); ip_send_check(iph);
ip_local_out(skb); ip_local_out(skb);
......
...@@ -318,9 +318,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) ...@@ -318,9 +318,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
} }
u32 ip_idents_reserve(u32 hash, int segs); u32 ip_idents_reserve(u32 hash, int segs);
void __ip_select_ident(struct iphdr *iph, int segs); void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
struct sock *sk, int segs)
{ {
struct iphdr *iph = ip_hdr(skb); struct iphdr *iph = ip_hdr(skb);
...@@ -337,13 +338,14 @@ static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, in ...@@ -337,13 +338,14 @@ static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, in
iph->id = 0; iph->id = 0;
} }
} else { } else {
__ip_select_ident(iph, segs); __ip_select_ident(net, iph, segs);
} }
} }
static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk) static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
struct sock *sk)
{ {
ip_select_ident_segs(skb, sk, 1); ip_select_ident_segs(net, skb, sk, 1);
} }
static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
......
...@@ -370,7 +370,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu) ...@@ -370,7 +370,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
pip->saddr = fl4.saddr; pip->saddr = fl4.saddr;
pip->protocol = IPPROTO_IGMP; pip->protocol = IPPROTO_IGMP;
pip->tot_len = 0; /* filled in later */ pip->tot_len = 0; /* filled in later */
ip_select_ident(skb, NULL); ip_select_ident(net, skb, NULL);
((u8 *)&pip[1])[0] = IPOPT_RA; ((u8 *)&pip[1])[0] = IPOPT_RA;
((u8 *)&pip[1])[1] = 4; ((u8 *)&pip[1])[1] = 4;
((u8 *)&pip[1])[2] = 0; ((u8 *)&pip[1])[2] = 0;
...@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, ...@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
iph->daddr = dst; iph->daddr = dst;
iph->saddr = fl4.saddr; iph->saddr = fl4.saddr;
iph->protocol = IPPROTO_IGMP; iph->protocol = IPPROTO_IGMP;
ip_select_ident(skb, NULL); ip_select_ident(net, skb, NULL);
((u8 *)&iph[1])[0] = IPOPT_RA; ((u8 *)&iph[1])[0] = IPOPT_RA;
((u8 *)&iph[1])[1] = 4; ((u8 *)&iph[1])[1] = 4;
((u8 *)&iph[1])[2] = 0; ((u8 *)&iph[1])[2] = 0;
......
...@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, ...@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
iph->saddr = saddr; iph->saddr = saddr;
iph->protocol = sk->sk_protocol; iph->protocol = sk->sk_protocol;
ip_select_ident(skb, sk); ip_select_ident(sock_net(sk), skb, sk);
if (opt && opt->opt.optlen) { if (opt && opt->opt.optlen) {
iph->ihl += opt->opt.optlen>>2; iph->ihl += opt->opt.optlen>>2;
...@@ -430,7 +430,8 @@ int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl) ...@@ -430,7 +430,8 @@ int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl)
ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0);
} }
ip_select_ident_segs(skb, sk, skb_shinfo(skb)->gso_segs ?: 1); ip_select_ident_segs(sock_net(sk), skb, sk,
skb_shinfo(skb)->gso_segs ?: 1);
/* TODO : should we use skb->sk here instead of sk ? */ /* TODO : should we use skb->sk here instead of sk ? */
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
...@@ -1379,7 +1380,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, ...@@ -1379,7 +1380,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
iph->ttl = ttl; iph->ttl = ttl;
iph->protocol = sk->sk_protocol; iph->protocol = sk->sk_protocol;
ip_copy_addrs(iph, fl4); ip_copy_addrs(iph, fl4);
ip_select_ident(skb, sk); ip_select_ident(net, skb, sk);
if (opt) { if (opt) {
iph->ihl += opt->optlen>>2; iph->ihl += opt->optlen>>2;
......
...@@ -74,7 +74,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, ...@@ -74,7 +74,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
iph->daddr = dst; iph->daddr = dst;
iph->saddr = src; iph->saddr = src;
iph->ttl = ttl; iph->ttl = ttl;
__ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1); __ip_select_ident(sock_net(sk), iph, skb_shinfo(skb)->gso_segs ?: 1);
err = ip_local_out_sk(sk, skb); err = ip_local_out_sk(sk, skb);
if (unlikely(net_xmit_eval(err))) if (unlikely(net_xmit_eval(err)))
......
...@@ -1642,7 +1642,8 @@ static struct notifier_block ip_mr_notifier = { ...@@ -1642,7 +1642,8 @@ static struct notifier_block ip_mr_notifier = {
* important for multicast video. * important for multicast video.
*/ */
static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) static void ip_encap(struct net *net, struct sk_buff *skb,
__be32 saddr, __be32 daddr)
{ {
struct iphdr *iph; struct iphdr *iph;
const struct iphdr *old_iph = ip_hdr(skb); const struct iphdr *old_iph = ip_hdr(skb);
...@@ -1661,7 +1662,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) ...@@ -1661,7 +1662,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
iph->protocol = IPPROTO_IPIP; iph->protocol = IPPROTO_IPIP;
iph->ihl = 5; iph->ihl = 5;
iph->tot_len = htons(skb->len); iph->tot_len = htons(skb->len);
ip_select_ident(skb, NULL); ip_select_ident(net, skb, NULL);
ip_send_check(iph); ip_send_check(iph);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
...@@ -1758,7 +1759,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, ...@@ -1758,7 +1759,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
* What do we do with netfilter? -- RR * What do we do with netfilter? -- RR
*/ */
if (vif->flags & VIFF_TUNNEL) { if (vif->flags & VIFF_TUNNEL) {
ip_encap(skb, vif->local, vif->remote); ip_encap(net, skb, vif->local, vif->remote);
/* FIXME: extra output firewall step used to be here. --RR */ /* FIXME: extra output firewall step used to be here. --RR */
vif->dev->stats.tx_packets++; vif->dev->stats.tx_packets++;
vif->dev->stats.tx_bytes += skb->len; vif->dev->stats.tx_bytes += skb->len;
......
...@@ -404,7 +404,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, ...@@ -404,7 +404,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
iph->check = 0; iph->check = 0;
iph->tot_len = htons(length); iph->tot_len = htons(length);
if (!iph->id) if (!iph->id)
ip_select_ident(skb, NULL); ip_select_ident(net, skb, NULL);
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
} }
......
...@@ -482,7 +482,7 @@ u32 ip_idents_reserve(u32 hash, int segs) ...@@ -482,7 +482,7 @@ u32 ip_idents_reserve(u32 hash, int segs)
} }
EXPORT_SYMBOL(ip_idents_reserve); EXPORT_SYMBOL(ip_idents_reserve);
void __ip_select_ident(struct iphdr *iph, int segs) void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
{ {
static u32 ip_idents_hashrnd __read_mostly; static u32 ip_idents_hashrnd __read_mostly;
u32 hash, id; u32 hash, id;
...@@ -491,7 +491,7 @@ void __ip_select_ident(struct iphdr *iph, int segs) ...@@ -491,7 +491,7 @@ void __ip_select_ident(struct iphdr *iph, int segs)
hash = jhash_3words((__force u32)iph->daddr, hash = jhash_3words((__force u32)iph->daddr,
(__force u32)iph->saddr, (__force u32)iph->saddr,
iph->protocol, iph->protocol ^ net_hash_mix(net),
ip_idents_hashrnd); ip_idents_hashrnd);
id = ip_idents_reserve(hash, segs); id = ip_idents_reserve(hash, segs);
iph->id = htons(id); iph->id = htons(id);
......
...@@ -63,7 +63,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -63,7 +63,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->saddr = x->props.saddr.a4; top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4; top_iph->daddr = x->id.daddr.a4;
ip_select_ident(skb, NULL); ip_select_ident(dev_net(dst->dev), skb, NULL);
return 0; return 0;
} }
......
...@@ -924,7 +924,8 @@ int ...@@ -924,7 +924,8 @@ int
ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{ {
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb)); struct net *net = skb_net(skb);
struct netns_ipvs *ipvs = net_ipvs(net);
struct rtable *rt; /* Route to the other host */ struct rtable *rt; /* Route to the other host */
__be32 saddr; /* Source for tunnel */ __be32 saddr; /* Source for tunnel */
struct net_device *tdev; /* Device to other host */ struct net_device *tdev; /* Device to other host */
...@@ -991,7 +992,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ...@@ -991,7 +992,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
iph->daddr = cp->daddr.ip; iph->daddr = cp->daddr.ip;
iph->saddr = saddr; iph->saddr = saddr;
iph->ttl = ttl; iph->ttl = ttl;
ip_select_ident(skb, NULL); ip_select_ident(net, skb, NULL);
/* Another hack: avoid icmp_send in ip_fragment */ /* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1; skb->ignore_df = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment