mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
530b2c8619
Usage: $ sudo ./sockex3 IP src.port -> dst.port bytes packets 127.0.0.1.42010 -> 127.0.0.1.12865 1568 8 127.0.0.1.59526 -> 127.0.0.1.33778 11422636 173070 127.0.0.1.33778 -> 127.0.0.1.59526 11260224828 341974 127.0.0.1.12865 -> 127.0.0.1.42010 1832 12 IP src.port -> dst.port bytes packets 127.0.0.1.42010 -> 127.0.0.1.12865 1568 8 127.0.0.1.59526 -> 127.0.0.1.33778 23198092 351486 127.0.0.1.33778 -> 127.0.0.1.59526 22972698518 698616 127.0.0.1.12865 -> 127.0.0.1.42010 1832 12 this example is similar to sockex2 in a way that it accumulates per-flow statistics, but it does packet parsing differently. sockex2 inlines full packet parser routine into single bpf program. This sockex3 example have 4 independent programs that parse vlan, mpls, ip, ipv6 and one main program that starts the process. bpf_tail_call() mechanism allows each program to be small and be called on demand potentially multiple times, so that many vlan, mpls, ip in ip, gre encapsulations can be parsed. These and other protocol parsers can be added or removed at runtime. TLVs can be parsed in similar manner. Note, tail_call_cnt dynamic check limits the number of tail calls to 32. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
66 lines
1.3 KiB
C
66 lines
1.3 KiB
C
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <linux/bpf.h>
|
|
#include "libbpf.h"
|
|
#include "bpf_load.h"
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
|
|
struct flow_keys {
|
|
__be32 src;
|
|
__be32 dst;
|
|
union {
|
|
__be32 ports;
|
|
__be16 port16[2];
|
|
};
|
|
__u32 ip_proto;
|
|
};
|
|
|
|
struct pair {
|
|
__u64 packets;
|
|
__u64 bytes;
|
|
};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
char filename[256];
|
|
FILE *f;
|
|
int i, sock;
|
|
|
|
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
|
|
|
if (load_bpf_file(filename)) {
|
|
printf("%s", bpf_log_buf);
|
|
return 1;
|
|
}
|
|
|
|
sock = open_raw_sock("lo");
|
|
|
|
assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd[4],
|
|
sizeof(__u32)) == 0);
|
|
|
|
if (argc > 1)
|
|
f = popen("ping -c5 localhost", "r");
|
|
else
|
|
f = popen("netperf -l 4 localhost", "r");
|
|
(void) f;
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
struct flow_keys key = {}, next_key;
|
|
struct pair value;
|
|
|
|
sleep(1);
|
|
printf("IP src.port -> dst.port bytes packets\n");
|
|
while (bpf_get_next_key(map_fd[2], &key, &next_key) == 0) {
|
|
bpf_lookup_elem(map_fd[2], &next_key, &value);
|
|
printf("%s.%05d -> %s.%05d %12lld %12lld\n",
|
|
inet_ntoa((struct in_addr){htonl(next_key.src)}),
|
|
next_key.port16[0],
|
|
inet_ntoa((struct in_addr){htonl(next_key.dst)}),
|
|
next_key.port16[1],
|
|
value.bytes, value.packets);
|
|
key = next_key;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|