Skip to content

Commit

Permalink
Merge branch 'pass_net_through_output_path'
Browse files Browse the repository at this point in the history
Eric W. Biederman says:

====================
net: Pass net through the output path v2

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.

The first patch in this series is a fix for a bug that came in when sk
was passed through the functions in the output path, and as such is
probably a candidate for net.  At the same time my later patches depend
on it so sending the fix separately would be confusing.

The second patch in this series is another fix that for an issue that
came in when sk was passed through the output path.  I don't think it
needs a backport as I don't think anyone uses the path where the code
was incorrect.

The rest of the patchset focuses on the path from xxx_local_out to
dst_output and in the end succeeds in passing sock_net(sk) from the
socket a packet locally originates on to the dst->output function.

Given the size reduction in the code I think this counts as a cleanup as
much as feature work.

There remain a number of helper functions (like ip option processing) to
take care of before the network stack can support destination devices in
other network namespaces but with this set of changes the backbone of
the work is done.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 8, 2015
2 parents e28383d + ede2059 commit 6b92d0c
Show file tree
Hide file tree
Showing 43 changed files with 125 additions and 155 deletions.
10 changes: 6 additions & 4 deletions drivers/net/ipvlan/ipvlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
{
const struct iphdr *ip4h = ip_hdr(skb);
struct net_device *dev = skb->dev;
struct net *net = dev_net(dev);
struct rtable *rt;
int err, ret = NET_XMIT_DROP;
struct flowi4 fl4 = {
Expand All @@ -354,7 +355,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
.saddr = ip4h->saddr,
};

rt = ip_route_output_flow(dev_net(dev), &fl4, NULL);
rt = ip_route_output_flow(net, &fl4, NULL);
if (IS_ERR(rt))
goto err;

Expand All @@ -364,7 +365,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
}
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
err = ip_local_out(skb);
err = ip_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;
else
Expand All @@ -381,6 +382,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
struct net_device *dev = skb->dev;
struct net *net = dev_net(dev);
struct dst_entry *dst;
int err, ret = NET_XMIT_DROP;
struct flowi6 fl6 = {
Expand All @@ -393,15 +395,15 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
.flowi6_proto = ip6h->nexthdr,
};

dst = ip6_route_output(dev_net(dev), NULL, &fl6);
dst = ip6_route_output(net, NULL, &fl6);
if (dst->error) {
ret = dst->error;
dst_release(dst);
goto err;
}
skb_dst_drop(skb);
skb_dst_set(skb, dst);
err = ip6_local_out(skb);
err = ip6_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;
else
Expand Down
7 changes: 4 additions & 3 deletions drivers/net/ppp/pptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
{
struct sock *sk = (struct sock *) chan->private;
struct pppox_sock *po = pppox_sk(sk);
struct net *net = sock_net(sk);
struct pptp_opt *opt = &po->proto.pptp;
struct pptp_gre_header *hdr;
unsigned int header_len = sizeof(*hdr);
Expand All @@ -187,7 +188,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
goto tx_error;

rt = ip_route_output_ports(sock_net(sk), &fl4, NULL,
rt = ip_route_output_ports(net, &fl4, NULL,
opt->dst_addr.sin_addr.s_addr,
opt->src_addr.sin_addr.s_addr,
0, 0, IPPROTO_GRE,
Expand Down Expand Up @@ -279,10 +280,10 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
nf_reset(skb);

skb->ip_summed = CHECKSUM_NONE;
ip_select_ident(sock_net(sk), skb, NULL);
ip_select_ident(net, skb, NULL);
ip_send_check(iph);

ip_local_out(skb);
ip_local_out(net, skb->sk, skb);
return 1;

tx_error:
Expand Down
9 changes: 4 additions & 5 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie)
return dst;
}

static int vrf_ip_local_out(struct sk_buff *skb)
static int vrf_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return ip_local_out(skb);
return ip_local_out(net, sk, skb);
}

static unsigned int vrf_v4_mtu(const struct dst_entry *dst)
Expand Down Expand Up @@ -222,7 +222,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
RT_SCOPE_LINK);
}

ret = ip_local_out(skb);
ret = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
if (unlikely(net_xmit_eval(ret)))
vrf_dev->stats.tx_errors++;
else
Expand Down Expand Up @@ -312,10 +312,9 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
return ret;
}

static int vrf_output(struct sock *sk, struct sk_buff *skb)
static int vrf_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
struct net *net = dev_net(dev);

IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len);

Expand Down
14 changes: 5 additions & 9 deletions include/net/dst.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct dst_entry {
void *__pad1;
#endif
int (*input)(struct sk_buff *);
int (*output)(struct sock *sk, struct sk_buff *skb);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);

unsigned short flags;
#define DST_HOST 0x0001
Expand Down Expand Up @@ -365,10 +365,10 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
__skb_tunnel_rx(skb, dev, net);
}

int dst_discard_sk(struct sock *sk, struct sk_buff *skb);
int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static inline int dst_discard(struct sk_buff *skb)
{
return dst_discard_sk(skb->sk, skb);
return dst_discard_out(&init_net, skb->sk, skb);
}
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
int initial_obsolete, unsigned short flags);
Expand Down Expand Up @@ -454,13 +454,9 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
}

/* Output packet to network from transport. */
static inline int dst_output(struct sock *sk, struct sk_buff *skb)
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return skb_dst(skb)->output(sk, skb);
}
static inline int dst_output_okfn(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return dst_output(sk, skb);
return skb_dst(skb)->output(net, sk, skb);
}

/* Input packet from network to transport. */
Expand Down
3 changes: 2 additions & 1 deletion include/net/dst_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct kmem_cachep;
struct net_device;
struct sk_buff;
struct sock;
struct net;

struct dst_ops {
unsigned short family;
Expand All @@ -28,7 +29,7 @@ struct dst_ops {
struct sk_buff *skb, u32 mtu);
void (*redirect)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb);
int (*local_out)(struct sk_buff *skb);
int (*local_out)(struct net *net, struct sock *sk, struct sk_buff *skb);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);
Expand Down
12 changes: 4 additions & 8 deletions include/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,13 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct net_device *orig_dev);
int ip_local_deliver(struct sk_buff *skb);
int ip_mr_input(struct sk_buff *skb);
int ip_output(struct sock *sk, struct sk_buff *skb);
int ip_mc_output(struct sock *sk, struct sk_buff *skb);
int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
int (*output)(struct net *, struct sock *, struct sk_buff *));
void ip_send_check(struct iphdr *ip);
int __ip_local_out(struct sk_buff *skb);
int ip_local_out_sk(struct sock *sk, struct sk_buff *skb);
static inline int ip_local_out(struct sk_buff *skb)
{
return ip_local_out_sk(skb->sk, skb);
}
int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);

int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void ip_init(void);
Expand Down
2 changes: 1 addition & 1 deletion include/net/ip6_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
int pkt_len, err;

pkt_len = skb->len - skb_inner_network_offset(skb);
err = ip6_local_out_sk(sk, skb);
err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);

if (net_xmit_eval(err) == 0) {
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
Expand Down
7 changes: 3 additions & 4 deletions include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,14 +860,13 @@ struct dst_entry *ip6_blackhole_route(struct net *net,
* skb processing functions
*/

int ip6_output(struct sock *sk, struct sk_buff *skb);
int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int ip6_forward(struct sk_buff *skb);
int ip6_input(struct sk_buff *skb);
int ip6_mc_input(struct sk_buff *skb);

int __ip6_local_out(struct sk_buff *skb);
int ip6_local_out_sk(struct sock *sk, struct sk_buff *skb);
int ip6_local_out(struct sk_buff *skb);
int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);

/*
* Extension header (options) processing
Expand Down
8 changes: 4 additions & 4 deletions include/net/lwtunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct lwtunnel_state {
__u16 type;
__u16 flags;
atomic_t refcnt;
int (*orig_output)(struct sock *sk, struct sk_buff *skb);
int (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*orig_input)(struct sk_buff *);
int len;
__u8 data[0];
Expand All @@ -28,7 +28,7 @@ struct lwtunnel_encap_ops {
int (*build_state)(struct net_device *dev, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts);
int (*output)(struct sock *sk, struct sk_buff *skb);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*input)(struct sk_buff *skb);
int (*fill_encap)(struct sk_buff *skb,
struct lwtunnel_state *lwtstate);
Expand Down Expand Up @@ -88,7 +88,7 @@ int lwtunnel_fill_encap(struct sk_buff *skb,
int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b);
int lwtunnel_output(struct sock *sk, struct sk_buff *skb);
int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int lwtunnel_input(struct sk_buff *skb);

#else
Expand Down Expand Up @@ -160,7 +160,7 @@ static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a,
return 0;
}

static inline int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
static inline int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return -EOPNOTSUPP;
}
Expand Down
6 changes: 3 additions & 3 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ struct xfrm_state_afinfo {
const xfrm_address_t *saddr);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
int (*output)(struct sock *sk, struct sk_buff *skb);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*output_finish)(struct sock *sk, struct sk_buff *skb);
int (*extract_input)(struct xfrm_state *x,
struct sk_buff *skb);
Expand Down Expand Up @@ -1527,7 +1527,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)

int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_output(struct sock *sk, struct sk_buff *skb);
int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb);
int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
Expand All @@ -1552,7 +1552,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
__be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_output(struct sock *sk, struct sk_buff *skb);
int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb);
int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb);
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);
Expand Down
14 changes: 7 additions & 7 deletions net/core/dst.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ static void dst_gc_task(struct work_struct *work)
mutex_unlock(&dst_gc_mutex);
}

int dst_discard_sk(struct sock *sk, struct sk_buff *skb)
int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL(dst_discard_sk);
EXPORT_SYMBOL(dst_discard_out);

const u32 dst_default_metrics[RTAX_MAX + 1] = {
/* This initializer is needed to force linker to place this variable
Expand Down Expand Up @@ -177,7 +177,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
dst->xfrm = NULL;
#endif
dst->input = dst_discard;
dst->output = dst_discard_sk;
dst->output = dst_discard_out;
dst->error = 0;
dst->obsolete = initial_obsolete;
dst->header_len = 0;
Expand Down Expand Up @@ -224,7 +224,7 @@ static void ___dst_free(struct dst_entry *dst)
*/
if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
dst->input = dst_discard;
dst->output = dst_discard_sk;
dst->output = dst_discard_out;
}
dst->obsolete = DST_OBSOLETE_DEAD;
}
Expand Down Expand Up @@ -352,7 +352,7 @@ static struct dst_ops md_dst_ops = {
.family = AF_UNSPEC,
};

static int dst_md_discard_sk(struct sock *sk, struct sk_buff *skb)
static int dst_md_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
WARN_ONCE(1, "Attempting to call output on metadata dst\n");
kfree_skb(skb);
Expand All @@ -375,7 +375,7 @@ static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen)
DST_METADATA | DST_NOCACHE | DST_NOCOUNT);

dst->input = dst_md_discard;
dst->output = dst_md_discard_sk;
dst->output = dst_md_discard_out;

memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
}
Expand Down Expand Up @@ -430,7 +430,7 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,

if (!unregister) {
dst->input = dst_discard;
dst->output = dst_discard_sk;
dst->output = dst_discard_out;
} else {
dst->dev = dev_net(dst->dev)->loopback_dev;
dev_hold(dst->dev);
Expand Down
4 changes: 2 additions & 2 deletions net/core/lwtunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
}
EXPORT_SYMBOL(lwtunnel_cmp_encap);

int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
const struct lwtunnel_encap_ops *ops;
Expand All @@ -199,7 +199,7 @@ int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
if (likely(ops && ops->output))
ret = ops->output(sk, skb);
ret = ops->output(net, sk, skb);
rcu_read_unlock();

if (ret == -EOPNOTSUPP)
Expand Down
4 changes: 2 additions & 2 deletions net/decnet/dn_nsp_out.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static void dn_nsp_send(struct sk_buff *skb)
if (dst) {
try_again:
skb_dst_set(skb, dst);
dst_output(skb->sk, skb);
dst_output(&init_net, skb->sk, skb);
return;
}

Expand Down Expand Up @@ -582,7 +582,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
* associations.
*/
skb_dst_set(skb, dst_clone(dst));
dst_output(skb->sk, skb);
dst_output(&init_net, skb->sk, skb);
}


Expand Down
Loading

0 comments on commit 6b92d0c

Please sign in to comment.