Skip to content

Commit 40e1068

Browse files
committed
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/net-next
Eric W. Biederman says: ==================== net: Pass net through ip fragmention This is the next installment of my work to pass struct net through the output path so the code does not need to guess how to figure out which network namespace it is in, and ultimately routes can have output devices in another network namespace. This round focuses on passing net through ip fragmentation which we seem to call from about everywhere. That is the main ip output paths, the bridge netfilter code, and openvswitch. This has to happend at once accross the tree as function pointers are involved. First some prep work is done, then ipv4 and ipv6 are converted and then temporary helper functions are removed. ==================== Acked-by: Nicolas Dichtel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents 7e2832f + b1842ff commit 40e1068

File tree

8 files changed

+53
-56
lines changed

8 files changed

+53
-56
lines changed

include/linux/netfilter_ipv6.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ struct nf_ipv6_ops {
1717
int (*chk_addr)(struct net *net, const struct in6_addr *addr,
1818
const struct net_device *dev, int strict);
1919
void (*route_input)(struct sk_buff *skb);
20-
int (*fragment)(struct sock *sk, struct sk_buff *skb,
21-
int (*output)(struct sock *, struct sk_buff *));
20+
int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb,
21+
int (*output)(struct net *, struct sock *, struct sk_buff *));
2222
};
2323

2424
#ifdef CONFIG_NETFILTER

include/net/ip.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ int ip_local_deliver(struct sk_buff *skb);
109109
int ip_mr_input(struct sk_buff *skb);
110110
int ip_output(struct sock *sk, struct sk_buff *skb);
111111
int ip_mc_output(struct sock *sk, struct sk_buff *skb);
112-
int ip_do_fragment(struct sock *sk, struct sk_buff *skb,
113-
int (*output)(struct sock *, struct sk_buff *));
112+
int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
113+
int (*output)(struct net *, struct sock *, struct sk_buff *));
114114
void ip_send_check(struct iphdr *ip);
115115
int __ip_local_out(struct sk_buff *skb);
116116
int ip_local_out_sk(struct sock *sk, struct sk_buff *skb);

include/net/ip6_route.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ static inline bool ipv6_anycast_destination(const struct dst_entry *dst,
173173
ipv6_addr_equal(&rt->rt6i_dst.addr, daddr));
174174
}
175175

176-
int ip6_fragment(struct sock *sk, struct sk_buff *skb,
177-
int (*output)(struct sock *, struct sk_buff *));
176+
int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
177+
int (*output)(struct net *, struct sock *, struct sk_buff *));
178178

179179
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
180180
{

net/bridge/br_netfilter_hooks.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -691,17 +691,12 @@ static int br_nf_push_frag_xmit(struct net *net, struct sock *sk, struct sk_buff
691691
nf_bridge_info_free(skb);
692692
return br_dev_queue_push_xmit(net, sk, skb);
693693
}
694-
static int br_nf_push_frag_xmit_sk(struct sock *sk, struct sk_buff *skb)
695-
{
696-
struct net *net = dev_net(skb_dst(skb)->dev);
697-
return br_nf_push_frag_xmit(net, sk, skb);
698-
}
699694
#endif
700695

701696
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
702697
static int
703698
br_nf_ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
704-
int (*output)(struct sock *, struct sk_buff *))
699+
int (*output)(struct net *, struct sock *, struct sk_buff *))
705700
{
706701
unsigned int mtu = ip_skb_dst_mtu(skb);
707702
struct iphdr *iph = ip_hdr(skb);
@@ -714,7 +709,7 @@ br_nf_ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
714709
return -EMSGSIZE;
715710
}
716711

717-
return ip_do_fragment(sk, skb, output);
712+
return ip_do_fragment(net, sk, skb, output);
718713
}
719714
#endif
720715

@@ -763,7 +758,7 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff
763758
skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
764759
data->size);
765760

766-
return br_nf_ip_fragment(net, sk, skb, br_nf_push_frag_xmit_sk);
761+
return br_nf_ip_fragment(net, sk, skb, br_nf_push_frag_xmit);
767762
}
768763
#endif
769764
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
@@ -786,7 +781,7 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff
786781
data->size);
787782

788783
if (v6ops)
789-
return v6ops->fragment(sk, skb, br_nf_push_frag_xmit_sk);
784+
return v6ops->fragment(net, sk, skb, br_nf_push_frag_xmit);
790785

791786
kfree_skb(skb);
792787
return -EMSGSIZE;

net/ipv4/ip_output.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@
8383
int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
8484
EXPORT_SYMBOL(sysctl_ip_default_ttl);
8585

86-
static int ip_fragment(struct sock *sk, struct sk_buff *skb,
87-
unsigned int mtu,
88-
int (*output)(struct sock *, struct sk_buff *));
86+
static int
87+
ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
88+
unsigned int mtu,
89+
int (*output)(struct net *, struct sock *, struct sk_buff *));
8990

9091
/* Generate a checksum for an outgoing IP datagram. */
9192
void ip_send_check(struct iphdr *iph)
@@ -176,12 +177,11 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
176177
}
177178
EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
178179

179-
static int ip_finish_output2(struct sock *sk, struct sk_buff *skb)
180+
static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
180181
{
181182
struct dst_entry *dst = skb_dst(skb);
182183
struct rtable *rt = (struct rtable *)dst;
183184
struct net_device *dev = dst->dev;
184-
struct net *net = dev_net(dev);
185185
unsigned int hh_len = LL_RESERVED_SPACE(dev);
186186
struct neighbour *neigh;
187187
u32 nexthop;
@@ -225,8 +225,8 @@ static int ip_finish_output2(struct sock *sk, struct sk_buff *skb)
225225
return -EINVAL;
226226
}
227227

228-
static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb,
229-
unsigned int mtu)
228+
static int ip_finish_output_gso(struct net *net, struct sock *sk,
229+
struct sk_buff *skb, unsigned int mtu)
230230
{
231231
netdev_features_t features;
232232
struct sk_buff *segs;
@@ -235,7 +235,7 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb,
235235
/* common case: locally created skb or seglen is <= mtu */
236236
if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) ||
237237
skb_gso_network_seglen(skb) <= mtu)
238-
return ip_finish_output2(sk, skb);
238+
return ip_finish_output2(net, sk, skb);
239239

240240
/* Slowpath - GSO segment length is exceeding the dst MTU.
241241
*
@@ -258,7 +258,7 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb,
258258
int err;
259259

260260
segs->next = NULL;
261-
err = ip_fragment(sk, segs, mtu, ip_finish_output2);
261+
err = ip_fragment(net, sk, segs, mtu, ip_finish_output2);
262262

263263
if (err && ret == 0)
264264
ret = err;
@@ -281,12 +281,12 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk
281281
#endif
282282
mtu = ip_skb_dst_mtu(skb);
283283
if (skb_is_gso(skb))
284-
return ip_finish_output_gso(sk, skb, mtu);
284+
return ip_finish_output_gso(net, sk, skb, mtu);
285285

286286
if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU))
287-
return ip_fragment(sk, skb, mtu, ip_finish_output2);
287+
return ip_fragment(net, sk, skb, mtu, ip_finish_output2);
288288

289-
return ip_finish_output2(sk, skb);
289+
return ip_finish_output2(net, sk, skb);
290290
}
291291

292292
int ip_mc_output(struct sock *sk, struct sk_buff *skb)
@@ -495,28 +495,26 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
495495
skb_copy_secmark(to, from);
496496
}
497497

498-
static int ip_fragment(struct sock *sk, struct sk_buff *skb,
498+
static int ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
499499
unsigned int mtu,
500-
int (*output)(struct sock *, struct sk_buff *))
500+
int (*output)(struct net *, struct sock *, struct sk_buff *))
501501
{
502502
struct iphdr *iph = ip_hdr(skb);
503503

504504
if ((iph->frag_off & htons(IP_DF)) == 0)
505-
return ip_do_fragment(sk, skb, output);
505+
return ip_do_fragment(net, sk, skb, output);
506506

507507
if (unlikely(!skb->ignore_df ||
508508
(IPCB(skb)->frag_max_size &&
509509
IPCB(skb)->frag_max_size > mtu))) {
510-
struct net *net = dev_net(skb_rtable(skb)->dst.dev);
511-
512510
IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
513511
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
514512
htonl(mtu));
515513
kfree_skb(skb);
516514
return -EMSGSIZE;
517515
}
518516

519-
return ip_do_fragment(sk, skb, output);
517+
return ip_do_fragment(net, sk, skb, output);
520518
}
521519

522520
/*
@@ -526,8 +524,8 @@ static int ip_fragment(struct sock *sk, struct sk_buff *skb,
526524
* single device frame, and queue such a frame for sending.
527525
*/
528526

529-
int ip_do_fragment(struct sock *sk, struct sk_buff *skb,
530-
int (*output)(struct sock *, struct sk_buff *))
527+
int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
528+
int (*output)(struct net *, struct sock *, struct sk_buff *))
531529
{
532530
struct iphdr *iph;
533531
int ptr;
@@ -537,11 +535,9 @@ int ip_do_fragment(struct sock *sk, struct sk_buff *skb,
537535
int offset;
538536
__be16 not_last_frag;
539537
struct rtable *rt = skb_rtable(skb);
540-
struct net *net;
541538
int err = 0;
542539

543540
dev = rt->dst.dev;
544-
net = dev_net(dev);
545541

546542
/*
547543
* Point into the IP datagram header.
@@ -631,7 +627,7 @@ int ip_do_fragment(struct sock *sk, struct sk_buff *skb,
631627
ip_send_check(iph);
632628
}
633629

634-
err = output(sk, skb);
630+
err = output(net, sk, skb);
635631

636632
if (!err)
637633
IP_INC_STATS(net, IPSTATS_MIB_FRAGCREATES);
@@ -771,7 +767,7 @@ int ip_do_fragment(struct sock *sk, struct sk_buff *skb,
771767

772768
ip_send_check(iph);
773769

774-
err = output(sk, skb2);
770+
err = output(net, sk, skb2);
775771
if (err)
776772
goto fail;
777773

net/ipv6/ip6_output.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@
5656
#include <net/checksum.h>
5757
#include <linux/mroute6.h>
5858

59-
static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb)
59+
static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
6060
{
6161
struct dst_entry *dst = skb_dst(skb);
6262
struct net_device *dev = dst->dev;
63-
struct net *net = dev_net(dev);
6463
struct neighbour *neigh;
6564
struct in6_addr *nexthop;
6665
int ret;
@@ -126,9 +125,9 @@ static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
126125
if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
127126
dst_allfrag(skb_dst(skb)) ||
128127
(IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
129-
return ip6_fragment(sk, skb, ip6_finish_output2);
128+
return ip6_fragment(net, sk, skb, ip6_finish_output2);
130129
else
131-
return ip6_finish_output2(sk, skb);
130+
return ip6_finish_output2(net, sk, skb);
132131
}
133132

134133
int ip6_output(struct sock *sk, struct sk_buff *skb)
@@ -554,8 +553,8 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
554553
skb_copy_secmark(to, from);
555554
}
556555

557-
int ip6_fragment(struct sock *sk, struct sk_buff *skb,
558-
int (*output)(struct sock *, struct sk_buff *))
556+
int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
557+
int (*output)(struct net *, struct sock *, struct sk_buff *))
559558
{
560559
struct sk_buff *frag;
561560
struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
@@ -568,7 +567,6 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
568567
__be32 frag_id;
569568
int ptr, offset = 0, err = 0;
570569
u8 *prevhdr, nexthdr = 0;
571-
struct net *net = dev_net(skb_dst(skb)->dev);
572570

573571
hlen = ip6_find_1stfragopt(skb, &prevhdr);
574572
nexthdr = *prevhdr;
@@ -688,7 +686,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
688686
ip6_copy_metadata(frag, skb);
689687
}
690688

691-
err = output(sk, skb);
689+
err = output(net, sk, skb);
692690
if (!err)
693691
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
694692
IPSTATS_MIB_FRAGCREATES);
@@ -816,7 +814,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
816814
/*
817815
* Put this fragment into the sending queue.
818816
*/
819-
err = output(sk, frag);
817+
err = output(net, sk, frag);
820818
if (err)
821819
goto fail;
822820

net/ipv6/xfrm6_output.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
131131
return xfrm_output(sk, skb);
132132
}
133133

134+
static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
135+
{
136+
struct xfrm_state *x = skb_dst(skb)->xfrm;
137+
138+
return x->outer_mode->afinfo->output_finish(sk, skb);
139+
}
140+
134141
static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
135142
{
136143
struct dst_entry *dst = skb_dst(skb);
@@ -160,8 +167,8 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
160167
if (x->props.mode == XFRM_MODE_TUNNEL &&
161168
((skb->len > mtu && !skb_is_gso(skb)) ||
162169
dst_allfrag(skb_dst(skb)))) {
163-
return ip6_fragment(sk, skb,
164-
x->outer_mode->afinfo->output_finish);
170+
return ip6_fragment(net, sk, skb,
171+
__xfrm6_output_finish);
165172
}
166173
return x->outer_mode->afinfo->output_finish(sk, skb);
167174
}

net/openvswitch/actions.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key,
620620
return 0;
621621
}
622622

623-
static int ovs_vport_output(struct sock *sock, struct sk_buff *skb)
623+
static int ovs_vport_output(struct net *net, struct sock *sk, struct sk_buff *skb)
624624
{
625625
struct ovs_frag_data *data = this_cpu_ptr(&ovs_frag_data_storage);
626626
struct vport *vport = data->vport;
@@ -679,8 +679,8 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb)
679679
skb_pull(skb, hlen);
680680
}
681681

682-
static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
683-
__be16 ethertype)
682+
static void ovs_fragment(struct net *net, struct vport *vport,
683+
struct sk_buff *skb, u16 mru, __be16 ethertype)
684684
{
685685
if (skb_network_offset(skb) > MAX_L2_LEN) {
686686
OVS_NLERR(1, "L2 header too long to fragment");
@@ -700,7 +700,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
700700
skb_dst_set_noref(skb, &ovs_dst);
701701
IPCB(skb)->frag_max_size = mru;
702702

703-
ip_do_fragment(skb->sk, skb, ovs_vport_output);
703+
ip_do_fragment(net, skb->sk, skb, ovs_vport_output);
704704
refdst_drop(orig_dst);
705705
} else if (ethertype == htons(ETH_P_IPV6)) {
706706
const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
@@ -722,7 +722,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
722722
skb_dst_set_noref(skb, &ovs_rt.dst);
723723
IP6CB(skb)->frag_max_size = mru;
724724

725-
v6ops->fragment(skb->sk, skb, ovs_vport_output);
725+
v6ops->fragment(net, skb->sk, skb, ovs_vport_output);
726726
refdst_drop(orig_dst);
727727
} else {
728728
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
@@ -743,6 +743,7 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
743743
if (likely(!mru || (skb->len <= mru + ETH_HLEN))) {
744744
ovs_vport_send(vport, skb);
745745
} else if (mru <= vport->dev->mtu) {
746+
struct net *net = read_pnet(&dp->net);
746747
__be16 ethertype = key->eth.type;
747748

748749
if (!is_flow_key_valid(key)) {
@@ -752,7 +753,7 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
752753
ethertype = vlan_get_protocol(skb);
753754
}
754755

755-
ovs_fragment(vport, skb, mru, ethertype);
756+
ovs_fragment(net, vport, skb, mru, ethertype);
756757
} else {
757758
kfree_skb(skb);
758759
}

0 commit comments

Comments
 (0)