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:
Toke Høiland-Jørgensen
2022-06-28 16:18:09 +02:00
parent e4530b04ce
commit 6f47602582
3 changed files with 47 additions and 5 deletions
+10 -2
View File
@@ -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");
+24 -3
View File
@@ -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
*/
+13
View File
@@ -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