Skip to content

Commit a8e3e1a

Browse files
David Aherndavem330
authored andcommitted
net: l3mdev: Add hook to output path
This patch adds the infrastructure to the output path to pass an skb to an l3mdev device if it has a hook registered. This is the Tx parallel to l3mdev_ip{6}_rcv in the receive path and is the basis for removing the existing hook that returns the vrf dst on the fib lookup. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9ee0034 commit a8e3e1a

File tree

5 files changed

+78
-0
lines changed

5 files changed

+78
-0
lines changed

include/net/l3mdev.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111
#ifndef _NET_L3MDEV_H_
1212
#define _NET_L3MDEV_H_
1313

14+
#include <net/dst.h>
1415
#include <net/fib_rules.h>
1516

1617
/**
1718
* struct l3mdev_ops - l3mdev operations
1819
*
1920
* @l3mdev_fib_table: Get FIB table id to use for lookups
2021
*
22+
* @l3mdev_l3_rcv: Hook in L3 receive path
23+
*
24+
* @l3mdev_l3_out: Hook in L3 output path
25+
*
2126
* @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device
2227
*
2328
* @l3mdev_get_saddr: Get source address for a flow
@@ -29,6 +34,9 @@ struct l3mdev_ops {
2934
u32 (*l3mdev_fib_table)(const struct net_device *dev);
3035
struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
3136
struct sk_buff *skb, u16 proto);
37+
struct sk_buff * (*l3mdev_l3_out)(struct net_device *dev,
38+
struct sock *sk, struct sk_buff *skb,
39+
u16 proto);
3240

3341
/* IPv4 ops */
3442
struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev,
@@ -201,6 +209,34 @@ struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
201209
return l3mdev_l3_rcv(skb, AF_INET6);
202210
}
203211

212+
static inline
213+
struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
214+
{
215+
struct net_device *dev = skb_dst(skb)->dev;
216+
217+
if (netif_is_l3_slave(dev)) {
218+
struct net_device *master;
219+
220+
master = netdev_master_upper_dev_get_rcu(dev);
221+
if (master && master->l3mdev_ops->l3mdev_l3_out)
222+
skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
223+
skb, proto);
224+
}
225+
226+
return skb;
227+
}
228+
229+
static inline
230+
struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
231+
{
232+
return l3mdev_l3_out(sk, skb, AF_INET);
233+
}
234+
235+
static inline
236+
struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
237+
{
238+
return l3mdev_l3_out(sk, skb, AF_INET6);
239+
}
204240
#else
205241

206242
static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
@@ -286,6 +322,18 @@ struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
286322
return skb;
287323
}
288324

325+
static inline
326+
struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
327+
{
328+
return skb;
329+
}
330+
331+
static inline
332+
struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
333+
{
334+
return skb;
335+
}
336+
289337
static inline
290338
int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
291339
struct fib_lookup_arg *arg)

net/ipv4/ip_output.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
9999

100100
iph->tot_len = htons(skb->len);
101101
ip_send_check(iph);
102+
103+
/* if egress device is enslaved to an L3 master device pass the
104+
* skb to its handler for processing
105+
*/
106+
skb = l3mdev_ip_out(sk, skb);
107+
if (unlikely(!skb))
108+
return 0;
109+
102110
return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
103111
net, sk, skb, NULL, skb_dst(skb)->dev,
104112
dst_output);

net/ipv6/ip6_output.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,14 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
236236
if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
237237
IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)),
238238
IPSTATS_MIB_OUT, skb->len);
239+
240+
/* if egress device is enslaved to an L3 master device pass the
241+
* skb to its handler for processing
242+
*/
243+
skb = l3mdev_ip6_out((struct sock *)sk, skb);
244+
if (unlikely(!skb))
245+
return 0;
246+
239247
/* hooks should never assume socket lock is held.
240248
* we promote our socket to non const
241249
*/

net/ipv6/output_core.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
148148
ipv6_hdr(skb)->payload_len = htons(len);
149149
IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
150150

151+
/* if egress device is enslaved to an L3 master device pass the
152+
* skb to its handler for processing
153+
*/
154+
skb = l3mdev_ip6_out(sk, skb);
155+
if (unlikely(!skb))
156+
return 0;
157+
151158
return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
152159
net, sk, skb, NULL, skb_dst(skb)->dev,
153160
dst_output);

net/ipv6/raw.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,13 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
653653
if (err)
654654
goto error_fault;
655655

656+
/* if egress device is enslaved to an L3 master device pass the
657+
* skb to its handler for processing
658+
*/
659+
skb = l3mdev_ip6_out(sk, skb);
660+
if (unlikely(!skb))
661+
return 0;
662+
656663
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
657664
err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
658665
NULL, rt->dst.dev, dst_output);

0 commit comments

Comments
 (0)