Subject: Re: Linux Socket Filter

From: Omer Musaev <[email-masked]>
Date: Wed, 20 Dec 2000 14:25:45 +0000

Nadav Har'El wrote:

> I'm trying to program something (on Linux, of course) that will need to
> capture arbitrary packets coming to the machine (TCP segments, for example).
> One obvious solution is to use libpcap [1]. However, it apears that libpcap
> (even the latest version) uses a very inefficient method to capture packets
> that match some criterion (defined using a BPF program [2, 4]) - it moves
> all packets to user space, and does the matching there.
>
> However, it appears that Linux provides an in-kernel BFP-like feature called
> "Linux Socket Filter" [3], that is included in modern kernels (e.g., it
> is included in Redhat 7, but probably in earlier distributions too), which
> seems perfect for my needs. But searching around, it seems that nobody is
> actually using it... Does anybody know why? Also why didn't the libpcap people
> use LSF on Linux, instead of their inefficient user-space solution? Is there
> something wrong with LSF? I'd love to hear from anybody with any experience
> in LSF.
>

I do relply to hackers-il, since I find that place more appropriate for that
kind of discussion.

We had faced similar problem at my workplace. I had to write loadable module
for kernel, and that does give all traffic from 100mbps copper even on slow
machine.

As you understand, I can not give you a source - it belongs to Mercury, or
even tell you what I had done - algorithms are copirighted, but here what I
can tell:

First: for all those for whom
LSF is based on BSF and is
a language for defining filters and a compiler to transform filter
definitions to stack based intermediate language.
The language defines turing-machine like instructions like
"test where you are" and "proceed N bytes". It operates on ethernet frames.
It is interesting thing, but not really what you want.

A simple solution to your problem is to use ethertap.o and produce
/dev/tap character device and tap0 network interface. All data you will
write to /dev/tap will appear as though it came from outside to your
machine via tap0 interface, and all data routed to tap0 interface will
be readable via /dev/tap .

ethertap is not a high performance thingy, since it uses kernel-user netlink,
which sucks. However, it does provide you with somewhat easy to implement
solution.

Another solution is using "packet socket". This is an interface to datalink
layer (second layer by OSI). you create that by using socket call, but instead
of specifying PF_INET you put there PF_PACKET. Then you bind that socket and
use it if it was ordinary socket.
However, packet socket has all deficiencies of libcap, and lacks its API.
More specifically, packet socket will not give you any performance improvement.

Yet another solution is LiS (http://www.sparre.dk/pub/linux/LiS/documentation),
which gives you somewhat analogous to DLPI. I did not tried that though.

Yet another solution (not really a solution, but an idea) is porting dpli from
BSD.

And final solution, that one that I had implemented is using kernel module -
which is suprerior in terms of performance, but is really a heavy project to
implement.

>
> [1] http://www.tcpdump.org
> [2] http://www.tcpdump.org/papers/bpf-usenix93.pdf
> [3] http://www.linuxhq.com/kernel/v2.2/doc/networking/filter.txt.html
> [4] http://www.neosoft.com/neosoft/man/bpf.4.html
>
> Thanks,
>         Nadav.
>
> --
> Nadav Har'El                        |   Wednesday, Dec 20 2000, 23 Kislev 5761
> [email-masked]             |-----------------------------------------
> Phone: +972-53-245868, ICQ 13349191 |Don't be irreplaceable. If you can't be
> http://nadav.harel.org.il           |replaced, you can't be promoted.
>
> =================================================================
> To unsubscribe, send mail to [email-masked] with
> the word "unsubscribe" in the message body, e.g., run the command
> echo unsubscribe | mail [email-masked]

--
Omer Mussaev 054308250 mailto:[email-masked]
  Mercury Interactive / APM core technologies R&D

---

From: "Nadav Har'El" <[email-masked]>
Date: Wed, 20 Dec 2000 13:50:49 +0200

> I do relply to hackers-il, since I find that place more appropriate for that

Well, I thought that this was a Linux question par-excellence, but if you want
it on hackers-il, then I don't object :)

> It is interesting thing, but not really what you want.

Why is not what I want? I have a machine that is doing a lot of stuff, with
potentially a lot of traffic, and I need to process (in user space, hopefully)
some selected part of this traffic (say, TCP packets headed to specific port
which is also ipchain'ed so the kernel won't reply and ruin what I'm trying to
do). BPF may be an overkill for what I want, but I think it can do what I want.

> be readable via /dev/tap .

Yes, I can use ipchains+ethertap. It's a nice idea - I'll have to consider it.

> However, packet socket has all deficiencies of libcap, and lacks its API.

Sure, this is exactly what libpcap does by default :) But it means that if
I'm only interested in processing 1% of the packets that enter the machine,
I'll still need to process all of them - which is totally useless. This
is where LSF comes in - it's suppose to filter out of that socket only the
packets I'm really interested in.

> Yet another solution (not really a solution, but an idea) is porting dpli from

I think I'll rather stay away from AT&T STREAMS... It's not really the method
of choice on BSD-inspired kernels.

> which is suprerior in terms of performance, but is really a heavy project to

Since all I'd want that module to do is to pick out the "relevant" packets
I'm interested in and hand them to a user-space program, I hoped that LSF
would be exactly the module you described, and I wouldn't need to write my own.
This is why I wanted to hear if anybody has experience with LSF.

P.S. I looked at Redhat's patched libpcap (apparently they don't take it from
www.tcpdump.org), and it is patched to use LSF to do kernel filtering on
Linux too! Redhat 7's precompiled /usr/lib/libpcap.a doesn't seem to work at
all, but if I can get it to work (maybe I'll compile it myself) then maybe
using it will solve my problem.

---

From: Omer Mussaev <[email-masked]>
Date: Wed, 20 Dec 2000 16:34:24 +0000

> do). BPF may be an overkill for what I want, but I think it can do what I want.

BPF may be overkill for almost anything, but it is an elegant and generic approach.
The problem is however in kernel->user data transfer. In case all you want to do
is maybe 0.5% of whole traffic, then it is ok, but if you are talking to larger
amounts of data, you will spend too much time in copy_from_user( ) function.
In short: unlike SunOS (nit) or Solaris (STREAMS), you are dealing with a socket
here, and socket is not any good in HUGE data transfer.

> Yes, I can use ipchains+ethertap. It's a nice idea - I'll have to consider it.

ethertap woould be more appropriate for me than LSF because of char_device
interface (one read can pick more than one frame a time).

> packets I'm really interested in.

As I stated before, as long as you are interested in processing less than 1%
(the number is of course does not reflect nothing, but just an example) socket
based data transfer is ok. And indeed, with LSF instead of using user-space process
to
filter jewels from dust, you do it in kernel, which means that ping -fd won't make
you to miss first SYN from a client :)
However, if TCP traffic is most of traffic that is going to your machine, or your
network (if you want to be promiscous), you"ll start lose frames.

> of choice on BSD-inspired kernels.

STREAMS are great. the problem is that to insert them on permanent basis into
linux kernel you will end up with kludgy and dirty design and bad performance

> using it will solve my problem.

Thanx for info, did not know it:) It is interesting to compare performace of
those two.

> To unsubscribe from this group, send an email to:
> [email-masked]