diff options
author | John Fastabend <john.fastabend@gmail.com> | 2017-07-17 19:27:50 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-07-17 19:48:06 +0300 |
commit | 6103aa96ec077c976e851e0b89cc2446cb76573d (patch) | |
tree | a54dbc7a88b1737d6f02840ee97eecefef49070b /net/core/dev.c | |
parent | 832622e6bd1884c95475094941914969ff82b329 (diff) | |
download | linux-6103aa96ec077c976e851e0b89cc2446cb76573d.tar.xz |
net: implement XDP_REDIRECT for xdp generic
Add support for redirect to xdp generic creating a fall back for
devices that do not yet have support and allowing test infrastructure
using veth pairs to be built.
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Tested-by: Andy Gospodarek <andy@greyhouse.net>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index a1ed7b41b3e8..9f3f4083ada5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3902,6 +3902,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, __skb_push(skb, -off); switch (act) { + case XDP_REDIRECT: case XDP_TX: __skb_push(skb, mac_len); /* fall through */ @@ -3956,14 +3957,27 @@ static int do_xdp_generic(struct sk_buff *skb) if (xdp_prog) { u32 act = netif_receive_generic_xdp(skb, xdp_prog); + int err; if (act != XDP_PASS) { - if (act == XDP_TX) + switch (act) { + case XDP_REDIRECT: + err = xdp_do_generic_redirect(skb->dev, skb); + if (err) + goto out_redir; + /* fallthru to submit skb */ + case XDP_TX: generic_xdp_tx(skb, xdp_prog); + break; + } return XDP_DROP; } } return XDP_PASS; +out_redir: + trace_xdp_exception(skb->dev, xdp_prog, XDP_REDIRECT); + kfree_skb(skb); + return XDP_DROP; } static int netif_rx_internal(struct sk_buff *skb) @@ -3977,8 +3991,12 @@ static int netif_rx_internal(struct sk_buff *skb) if (static_key_false(&generic_xdp_needed)) { int ret = do_xdp_generic(skb); + /* Consider XDP consuming the packet a success from + * the netdev point of view we do not want to count + * this as an error. + */ if (ret != XDP_PASS) - return NET_RX_DROP; + return NET_RX_SUCCESS; } #ifdef CONFIG_RPS |