linux/samples/bpf/tcp_tos_reflect_kern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2018 Facebook
   4 *
   5 * BPF program to automatically reflect TOS option from received syn packet
   6 *
   7 * Use "bpftool cgroup attach $cg sock_ops $prog" to load this BPF program.
   8 */
   9
  10#include <uapi/linux/bpf.h>
  11#include <uapi/linux/tcp.h>
  12#include <uapi/linux/if_ether.h>
  13#include <uapi/linux/if_packet.h>
  14#include <uapi/linux/ip.h>
  15#include <uapi/linux/ipv6.h>
  16#include <uapi/linux/in.h>
  17#include <linux/socket.h>
  18#include <bpf/bpf_helpers.h>
  19#include <bpf/bpf_endian.h>
  20
  21#define DEBUG 1
  22
  23SEC("sockops")
  24int bpf_basertt(struct bpf_sock_ops *skops)
  25{
  26        char header[sizeof(struct ipv6hdr)];
  27        struct ipv6hdr *hdr6;
  28        struct iphdr *hdr;
  29        int hdr_size = 0;
  30        int save_syn = 1;
  31        int tos = 0;
  32        int rv = 0;
  33        int op;
  34
  35        op = (int) skops->op;
  36
  37#ifdef DEBUG
  38        bpf_printk("BPF command: %d\n", op);
  39#endif
  40        switch (op) {
  41        case BPF_SOCK_OPS_TCP_LISTEN_CB:
  42                rv = bpf_setsockopt(skops, SOL_TCP, TCP_SAVE_SYN,
  43                                   &save_syn, sizeof(save_syn));
  44                break;
  45        case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
  46                if (skops->family == AF_INET)
  47                        hdr_size = sizeof(struct iphdr);
  48                else
  49                        hdr_size = sizeof(struct ipv6hdr);
  50                rv = bpf_getsockopt(skops, SOL_TCP, TCP_SAVED_SYN,
  51                                    header, hdr_size);
  52                if (!rv) {
  53                        if (skops->family == AF_INET) {
  54                                hdr = (struct iphdr *) header;
  55                                tos = hdr->tos;
  56                                if (tos != 0)
  57                                        bpf_setsockopt(skops, SOL_IP, IP_TOS,
  58                                                       &tos, sizeof(tos));
  59                        } else {
  60                                hdr6 = (struct ipv6hdr *) header;
  61                                tos = ((hdr6->priority) << 4 |
  62                                       (hdr6->flow_lbl[0]) >>  4);
  63                                if (tos)
  64                                        bpf_setsockopt(skops, SOL_IPV6,
  65                                                       IPV6_TCLASS,
  66                                                       &tos, sizeof(tos));
  67                        }
  68                        rv = 0;
  69                }
  70                break;
  71        default:
  72                rv = -1;
  73        }
  74#ifdef DEBUG
  75        bpf_printk("Returning %d\n", rv);
  76#endif
  77        skops->reply = rv;
  78        return 1;
  79}
  80char _license[] SEC("license") = "GPL";
  81