bpf: Sample BPF program to set congestion control
authorLawrence Brakmo <brakmo@fb.com>
Sat, 1 Jul 2017 03:02:50 +0000 (20:02 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 1 Jul 2017 23:15:14 +0000 (16:15 -0700)
Sample BPF program that sets congestion control to dctcp when both hosts
are within the same datacenter. In this example that is assumed to be
when they have the first 5.5 bytes of their IPv6 address are the same.

Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
samples/bpf/Makefile
samples/bpf/tcp_cong_kern.c [new file with mode: 0644]

index 3b300db3d74d11166cea568a08c478065a8d5957..6fdf32dffa927cc885fe4f06741ce777f4858ca9 100644 (file)
@@ -116,6 +116,7 @@ always += cookie_uid_helper_example.o
 always += tcp_synrto_kern.o
 always += tcp_rwnd_kern.o
 always += tcp_bufs_kern.o
+always += tcp_cong_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 HOSTCFLAGS += -I$(srctree)/tools/lib/
diff --git a/samples/bpf/tcp_cong_kern.c b/samples/bpf/tcp_cong_kern.c
new file mode 100644 (file)
index 0000000..dac15bc
--- /dev/null
@@ -0,0 +1,83 @@
+/* Copyright (c) 2017 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * BPF program to set congestion control to dctcp when both hosts are
+ * in the same datacenter (as deteremined by IPv6 prefix).
+ *
+ * Use load_sock_ops to load this BPF program.
+ */
+
+#include <uapi/linux/bpf.h>
+#include <uapi/linux/tcp.h>
+#include <uapi/linux/if_ether.h>
+#include <uapi/linux/if_packet.h>
+#include <uapi/linux/ip.h>
+#include <linux/socket.h>
+#include "bpf_helpers.h"
+#include "bpf_endian.h"
+
+#define DEBUG 1
+
+#define bpf_printk(fmt, ...)                                   \
+({                                                             \
+              char ____fmt[] = fmt;                            \
+              bpf_trace_printk(____fmt, sizeof(____fmt),       \
+                               ##__VA_ARGS__);                 \
+})
+
+SEC("sockops")
+int bpf_cong(struct bpf_sock_ops *skops)
+{
+       char cong[] = "dctcp";
+       int rv = 0;
+       int op;
+
+       /* For testing purposes, only execute rest of BPF program
+        * if neither port numberis 55601
+        */
+       if (bpf_ntohl(skops->remote_port) != 55601 &&
+           skops->local_port != 55601)
+               return -1;
+
+       op = (int) skops->op;
+
+#ifdef DEBUG
+       bpf_printk("BPF command: %d\n", op);
+#endif
+
+       /* Check if both hosts are in the same datacenter. For this
+        * example they are if the 1st 5.5 bytes in the IPv6 address
+        * are the same.
+        */
+       if (skops->family == AF_INET6 &&
+           skops->local_ip6[0] == skops->remote_ip6[0] &&
+           (bpf_ntohl(skops->local_ip6[1]) & 0xfff00000) ==
+           (bpf_ntohl(skops->remote_ip6[1]) & 0xfff00000)) {
+               switch (op) {
+               case BPF_SOCK_OPS_NEEDS_ECN:
+                       rv = 1;
+                       break;
+               case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
+                       rv = bpf_setsockopt(skops, SOL_TCP, TCP_CONGESTION,
+                                           cong, sizeof(cong));
+                       break;
+               case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
+                       rv = bpf_setsockopt(skops, SOL_TCP, TCP_CONGESTION,
+                                           cong, sizeof(cong));
+                       break;
+               default:
+                       rv = -1;
+               }
+       } else {
+               rv = -1;
+       }
+#ifdef DEBUG
+       bpf_printk("Returning %d\n", rv);
+#endif
+       skops->reply = rv;
+       return 1;
+}
+char _license[] SEC("license") = "GPL";