1*bb56d444SLawrence Brakmo /* Copyright (c) 2017 Facebook 2*bb56d444SLawrence Brakmo * 3*bb56d444SLawrence Brakmo * This program is free software; you can redistribute it and/or 4*bb56d444SLawrence Brakmo * modify it under the terms of version 2 of the GNU General Public 5*bb56d444SLawrence Brakmo * License as published by the Free Software Foundation. 6*bb56d444SLawrence Brakmo * 7*bb56d444SLawrence Brakmo * BPF program to set congestion control to dctcp when both hosts are 8*bb56d444SLawrence Brakmo * in the same datacenter (as deteremined by IPv6 prefix). 9*bb56d444SLawrence Brakmo * 10*bb56d444SLawrence Brakmo * Use load_sock_ops to load this BPF program. 11*bb56d444SLawrence Brakmo */ 12*bb56d444SLawrence Brakmo 13*bb56d444SLawrence Brakmo #include <uapi/linux/bpf.h> 14*bb56d444SLawrence Brakmo #include <uapi/linux/tcp.h> 15*bb56d444SLawrence Brakmo #include <uapi/linux/if_ether.h> 16*bb56d444SLawrence Brakmo #include <uapi/linux/if_packet.h> 17*bb56d444SLawrence Brakmo #include <uapi/linux/ip.h> 18*bb56d444SLawrence Brakmo #include <linux/socket.h> 19*bb56d444SLawrence Brakmo #include "bpf_helpers.h" 20*bb56d444SLawrence Brakmo #include "bpf_endian.h" 21*bb56d444SLawrence Brakmo 22*bb56d444SLawrence Brakmo #define DEBUG 1 23*bb56d444SLawrence Brakmo 24*bb56d444SLawrence Brakmo #define bpf_printk(fmt, ...) \ 25*bb56d444SLawrence Brakmo ({ \ 26*bb56d444SLawrence Brakmo char ____fmt[] = fmt; \ 27*bb56d444SLawrence Brakmo bpf_trace_printk(____fmt, sizeof(____fmt), \ 28*bb56d444SLawrence Brakmo ##__VA_ARGS__); \ 29*bb56d444SLawrence Brakmo }) 30*bb56d444SLawrence Brakmo 31*bb56d444SLawrence Brakmo SEC("sockops") 32*bb56d444SLawrence Brakmo int bpf_cong(struct bpf_sock_ops *skops) 33*bb56d444SLawrence Brakmo { 34*bb56d444SLawrence Brakmo char cong[] = "dctcp"; 35*bb56d444SLawrence Brakmo int rv = 0; 36*bb56d444SLawrence Brakmo int op; 37*bb56d444SLawrence Brakmo 38*bb56d444SLawrence Brakmo /* For testing purposes, only execute rest of BPF program 39*bb56d444SLawrence Brakmo * if neither port numberis 55601 40*bb56d444SLawrence Brakmo */ 41*bb56d444SLawrence Brakmo if (bpf_ntohl(skops->remote_port) != 55601 && 42*bb56d444SLawrence Brakmo skops->local_port != 55601) 43*bb56d444SLawrence Brakmo return -1; 44*bb56d444SLawrence Brakmo 45*bb56d444SLawrence Brakmo op = (int) skops->op; 46*bb56d444SLawrence Brakmo 47*bb56d444SLawrence Brakmo #ifdef DEBUG 48*bb56d444SLawrence Brakmo bpf_printk("BPF command: %d\n", op); 49*bb56d444SLawrence Brakmo #endif 50*bb56d444SLawrence Brakmo 51*bb56d444SLawrence Brakmo /* Check if both hosts are in the same datacenter. For this 52*bb56d444SLawrence Brakmo * example they are if the 1st 5.5 bytes in the IPv6 address 53*bb56d444SLawrence Brakmo * are the same. 54*bb56d444SLawrence Brakmo */ 55*bb56d444SLawrence Brakmo if (skops->family == AF_INET6 && 56*bb56d444SLawrence Brakmo skops->local_ip6[0] == skops->remote_ip6[0] && 57*bb56d444SLawrence Brakmo (bpf_ntohl(skops->local_ip6[1]) & 0xfff00000) == 58*bb56d444SLawrence Brakmo (bpf_ntohl(skops->remote_ip6[1]) & 0xfff00000)) { 59*bb56d444SLawrence Brakmo switch (op) { 60*bb56d444SLawrence Brakmo case BPF_SOCK_OPS_NEEDS_ECN: 61*bb56d444SLawrence Brakmo rv = 1; 62*bb56d444SLawrence Brakmo break; 63*bb56d444SLawrence Brakmo case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: 64*bb56d444SLawrence Brakmo rv = bpf_setsockopt(skops, SOL_TCP, TCP_CONGESTION, 65*bb56d444SLawrence Brakmo cong, sizeof(cong)); 66*bb56d444SLawrence Brakmo break; 67*bb56d444SLawrence Brakmo case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: 68*bb56d444SLawrence Brakmo rv = bpf_setsockopt(skops, SOL_TCP, TCP_CONGESTION, 69*bb56d444SLawrence Brakmo cong, sizeof(cong)); 70*bb56d444SLawrence Brakmo break; 71*bb56d444SLawrence Brakmo default: 72*bb56d444SLawrence Brakmo rv = -1; 73*bb56d444SLawrence Brakmo } 74*bb56d444SLawrence Brakmo } else { 75*bb56d444SLawrence Brakmo rv = -1; 76*bb56d444SLawrence Brakmo } 77*bb56d444SLawrence Brakmo #ifdef DEBUG 78*bb56d444SLawrence Brakmo bpf_printk("Returning %d\n", rv); 79*bb56d444SLawrence Brakmo #endif 80*bb56d444SLawrence Brakmo skops->reply = rv; 81*bb56d444SLawrence Brakmo return 1; 82*bb56d444SLawrence Brakmo } 83*bb56d444SLawrence Brakmo char _license[] SEC("license") = "GPL"; 84