mirror of
https://github.com/xdp-project/bpf-examples.git
synced 2024-05-06 15:54:53 +00:00
pkt-loop-filter: Add optional debugging of dropped packets
Add a debug mode to pkt-loop-filter that outputs debug messages for every dropped packet (with the reason it was dropped). Also add a small script to read the kernel trace pipe, after making sure tracing is active (otherwise there will be no output in the pipe). The source MAC address+VLAN is squeezed into a single u64 when printing as a quick workaround to the lack of MAC address printing in BPF printk. Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
This commit is contained in:
@@ -19,13 +19,13 @@ int main(int argc, char *argv[])
|
||||
int err = 0, i, num_ifindexes = 0, _err, ingress_fd, egress_fd;
|
||||
struct pkt_loop_filter_kern *skel = NULL;
|
||||
struct bpf_link *trace_link = NULL;
|
||||
bool unload = false, debug = false;
|
||||
int ifindex[MAX_IFINDEXES];
|
||||
bool unload = false;
|
||||
char pin_path[100];
|
||||
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <ifname> [..ifname] [--unload]\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <ifname> [..ifname] [--unload] [--debug]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ int main(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(ifname, "--debug")) {
|
||||
debug = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ifindex[num_ifindexes] = if_nametoindex(ifname);
|
||||
if (!ifindex[num_ifindexes]) {
|
||||
fprintf(stderr, "Couldn't find interface '%s'\n", ifname);
|
||||
@@ -78,6 +83,9 @@ int main(int argc, char *argv[])
|
||||
for (i = 0; i < num_ifindexes; i++)
|
||||
skel->bss->active_ifindexes[i] = ifindex[i];
|
||||
|
||||
/* enable debug flag if set on command line */
|
||||
skel->rodata->debug_output = debug;
|
||||
|
||||
err = pkt_loop_filter_kern__load(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to load object\n");
|
||||
|
||||
@@ -46,6 +46,11 @@ struct {
|
||||
|
||||
int active_ifindexes[MAX_IFINDEXES] = {};
|
||||
unsigned int current_ifindex = 0;
|
||||
/* This being const means that the verifier will do dead code elimination to
|
||||
* remove any code that depends on it being true entirely, incurring no runtime
|
||||
* overhead if debug mode is disabled.
|
||||
**/
|
||||
volatile const int debug_output = 0;
|
||||
|
||||
static int get_current_ifindex(void)
|
||||
{
|
||||
@@ -112,7 +117,7 @@ int filter_ingress_pkt(struct __sk_buff *skb)
|
||||
{
|
||||
struct pkt_loop_data *value;
|
||||
struct pkt_loop_key key;
|
||||
int pkt_type;
|
||||
int pkt_type, ifindex;
|
||||
|
||||
pkt_type = parse_pkt(skb, &key);
|
||||
if (pkt_type < 0)
|
||||
@@ -121,13 +126,26 @@ int filter_ingress_pkt(struct __sk_buff *skb)
|
||||
value = bpf_map_lookup_elem(&iface_state, &key);
|
||||
if (value && value->expiry_time > bpf_ktime_get_coarse_ns()) {
|
||||
value->drops++;
|
||||
if (debug_output)
|
||||
/* bpf_trace_printk doesn't know how to format MAC
|
||||
* addresses, and we don't have enough arguments to do
|
||||
* it ourselves; so just pass the whole key as a u64 and
|
||||
* hex-print that
|
||||
*/
|
||||
bpf_printk("Dropping packet with SMAC/vlan %llx - not found in hash table\n",
|
||||
*(__u64 *)&key);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
|
||||
|
||||
/* Only allow multicast pkts on the currently active interface */
|
||||
if (pkt_type == PKT_TYPE_MULTICAST &&
|
||||
skb->ifindex != get_current_ifindex())
|
||||
ifindex = get_current_ifindex();
|
||||
if (pkt_type == PKT_TYPE_MULTICAST && skb->ifindex != ifindex) {
|
||||
if (debug_output)
|
||||
bpf_printk("Dropping multicast packet - ifindex %d != active %d\n",
|
||||
skb->ifindex, ifindex);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
|
||||
out:
|
||||
return TC_ACT_OK;
|
||||
@@ -141,6 +159,9 @@ int BPF_KPROBE(handle_device_notify, unsigned long val, struct netdev_notifier_i
|
||||
|
||||
if (val == NETDEV_GOING_DOWN && cookie == INIT_NS &&
|
||||
ifindex == get_current_ifindex()) {
|
||||
if (debug_output)
|
||||
bpf_printk("Ifindex %d going down\n", ifindex);
|
||||
|
||||
/* Active interface going down, switch to next one; we currently
|
||||
* don't check for ifup and switch back
|
||||
*/
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
|
||||
TRACE_ACTIVE=$(cat /sys/kernel/debug/tracing/tracing_on)
|
||||
|
||||
if [ "$TRACE_ACTIVE" -ne "1" ]; then
|
||||
echo "Kernel tracing disabled, enabling"
|
||||
echo 1 > /sys/kernel/debug/tracing/tracing_on
|
||||
fi
|
||||
|
||||
echo "Reading trace pipe, ^C to exit"
|
||||
cat /sys/kernel/debug/tracing/trace_pipe
|
||||
Reference in New Issue
Block a user