4

I compiled BPF example from samples/bpf/pare_simple.c (from the Linux kernel tree) with very simple change:

SEC("simple")
int handle_ingress(struct __sk_buff *skb)
{
   return TC_ACT_SHOT;
}

So I want ANY packets to be dropped. I install it as follows:

This happens on Ubuntu 16.04.3 LTS with kernel 4.4.0-98, llvm and clang of version 3.8 installed from packages, iproute2 is the latest from github.

$ tc qdisc add dev eth0 clsact
$ tc filter add dev eth0 ingress bpf \
      object-file ./net-next.git/samples/bpf/parse_simple.o \
      section simple verbose

Prog section 'simple' loaded (5)!
 - Type:         3
 - Instructions: 2 (0 over limit)
 - License:      GPL

Verifier analysis:

0: (b7) r0 = 2
1: (95) exit
processed 2 insns, stack depth 0

So it seems it installs successfully, however this filter/ebpf does not drop packets, I generate ingress traffic on eth0 interface, e.g. ICMP, and it passes on. What am I doing wrong?

pchaigno
  • 11,313
  • 2
  • 29
  • 54
Mark
  • 6,052
  • 8
  • 61
  • 129
  • 1
    Could you try with the `direct-action` tc flag on your command line (before `verbose` I believe) ([see here](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=045efa82ff563cd4e656ca1c2e354fa5bf6bbda4)) – Qeole Dec 01 '17 at 10:33
  • @Qeole, indeed this helped, thanks! What does this flag indicate? – Mark Dec 01 '17 at 11:21
  • Good question, I've been willing to make a blog post to answer to that but never found the time :) Here are some explanations in a proper answer – Qeole Dec 01 '17 at 11:39

1 Answers1

5

TL;DR: You should add direct-action flag to the tc filter command, as in

tc filter add dev eth0 ingress bpf \
    object-file ./net-next.git/samples/bpf/parse_simple.o \
    section simple direct-action verbose
                   ^^^^^^^^^^^^^

The short help for tc bpf filter bpf help mentions this flag, but is has not made its way to the tc-bpf(8) manual page at this time, if I remember correctly.

So, what is this flag for?

eBPF programs can be attached two ways with tc: as actions, or as classifiers. Classifiers, attached with tc filter add, are supposed to be used for filtering packets, and do not apply an action by default. Which means that their return values have the following meaning (from man tc-bpf):

0 , denotes a mismatch

-1 , denotes the default classid configured from the command line

else , everything else will override the default classid to provide a facility for non-linear matching

Actions attached with tc action add, on the other hand, can drop or mirror or perform other operations with packets, but they are not supposed to actually filter them.

Because eBPF is kind of more flexible than the traditional actions and filters of tc, you can actually do both at once, filter a packet (i.e. identify this packet) and perform an action on it. To reflect this flexibility, the direct-action, or da flag was added (for kernel 4.4 or newer, with matching iproute2 package). It tells the kernel to use the return values of actions (TC_ACT_SHOT, TC_ACT_OK, etc.) for classifiers. And this is what you need here to return TC_ACT_SHOT in a way the kernel understands you want to drop the packet.

If I remember correctly, the reason why we use this flag instead of just dropping filters for actions is that you need a filter anyway with tc to attach you action to? (to be confirmed). So with the direct-action flag you do not have to attach both one filter and one action, the filter can do both operations. This should be the preferred way to go for eBPF programming with tc.

Qeole
  • 8,284
  • 1
  • 24
  • 52