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 <bra...@fb.com>
---
 samples/bpf/Makefile        |  1 +
 samples/bpf/tcp_cong_kern.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 samples/bpf/tcp_cong_kern.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 3b300db..6fdf32d 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -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
index 0000000..fdced0f
--- /dev/null
+++ b/samples/bpf/tcp_cong_kern.c
@@ -0,0 +1,74 @@
+/* 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).
+ */
+
+#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"
+
+#define DEBUG 1
+
+SEC("sockops")
+int bpf_cong(struct bpf_sock_ops *skops)
+{
+       char fmt1[] = "BPF command: %d\n";
+       char fmt2[] = "  Returning %d\n";
+       char cong[] = "dctcp";
+       int rv = 0;
+       int op;
+
+       /* For testing purposes, only execute rest of BPF program
+        * if neither port numberis 55601
+        */
+       if (skops->remote_port != 55601 && skops->local_port != 55601)
+               return -1;
+
+       op = (int) skops->op;
+
+#ifdef DEBUG
+       bpf_trace_printk(fmt1, sizeof(fmt1), 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] &&
+           (skops->local_ip6[1] & 0xfff00000) ==
+           (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_trace_printk(fmt2, sizeof(fmt2), rv);
+#endif
+       skops->reply = rv;
+       return 1;
+}
+char _license[] SEC("license") = "GPL";
-- 
2.9.3

Reply via email to