summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJesper Dangaard Brouer <brouer@redhat.com>2017-08-17 18:22:37 +0200
committerDavid S. Miller <davem@davemloft.net>2017-08-18 16:18:40 -0700
commit4c03bdd7b5c084c3c6973cb2419edac5363c051f (patch)
tree77e091a3b5de3c55433947ec41891ba2b1e52019 /net
parentd2cee2e5d0106abb5da25f393b3c50e0bb01f7f9 (diff)
downloadlinux-4c03bdd7b5c084c3c6973cb2419edac5363c051f.tar.gz
linux-4c03bdd7b5c084c3c6973cb2419edac5363c051f.tar.bz2
linux-4c03bdd7b5c084c3c6973cb2419edac5363c051f.zip
xdp: adjust xdp redirect tracepoint to include return error code
The return error code need to be included in the tracepoint xdp:xdp_redirect, else its not possible to distinguish successful or failed XDP_REDIRECT transmits. XDP have no queuing mechanism. Thus, it is fairly easily to overrun a NIC transmit queue. The eBPF program invoking helpers (bpf_redirect or bpf_redirect_map) to redirect a packet doesn't get any feedback whether the packet was actually transmitted. Info on failed transmits in the tracepoint xdp:xdp_redirect, is interesting as this opens for providing a feedback-loop to the receiving XDP program. Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 0f4df86d936a..fa2115695037 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2535,14 +2535,16 @@ int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
struct bpf_map *map = ri->map;
u32 index = ri->ifindex;
struct net_device *fwd;
- int err = -EINVAL;
+ int err;
ri->ifindex = 0;
ri->map = NULL;
fwd = __dev_map_lookup_elem(map, index);
- if (!fwd)
+ if (!fwd) {
+ err = -EINVAL;
goto out;
+ }
if (ri->map_to_flush && (ri->map_to_flush != map))
xdp_do_flush_map();
@@ -2552,7 +2554,7 @@ int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
ri->map_to_flush = map;
out:
- trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT);
+ trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT, err);
return err;
}
@@ -2562,6 +2564,7 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
struct net_device *fwd;
u32 index = ri->ifindex;
+ int err;
if (ri->map)
return xdp_do_redirect_map(dev, xdp, xdp_prog);
@@ -2570,12 +2573,14 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
ri->ifindex = 0;
if (unlikely(!fwd)) {
bpf_warn_invalid_xdp_redirect(index);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
- trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT);
-
- return __bpf_tx_xdp(fwd, NULL, xdp, 0);
+ err = __bpf_tx_xdp(fwd, NULL, xdp, 0);
+out:
+ trace_xdp_redirect(dev, fwd, xdp_prog, XDP_REDIRECT, err);
+ return err;
}
EXPORT_SYMBOL_GPL(xdp_do_redirect);