]> asedeno.scripts.mit.edu Git - linux.git/blob - samples/bpf/hbm_kern.h
Merge tag '5.1-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
[linux.git] / samples / bpf / hbm_kern.h
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  * Copyright (c) 2019 Facebook
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public
7  * License as published by the Free Software Foundation.
8  *
9  * Include file for sample Host Bandwidth Manager (HBM) BPF programs
10  */
11 #define KBUILD_MODNAME "foo"
12 #include <stddef.h>
13 #include <stdbool.h>
14 #include <uapi/linux/bpf.h>
15 #include <uapi/linux/if_ether.h>
16 #include <uapi/linux/if_packet.h>
17 #include <uapi/linux/ip.h>
18 #include <uapi/linux/ipv6.h>
19 #include <uapi/linux/in.h>
20 #include <uapi/linux/tcp.h>
21 #include <uapi/linux/filter.h>
22 #include <uapi/linux/pkt_cls.h>
23 #include <net/ipv6.h>
24 #include <net/inet_ecn.h>
25 #include "bpf_endian.h"
26 #include "bpf_helpers.h"
27 #include "hbm.h"
28
29 #define DROP_PKT        0
30 #define ALLOW_PKT       1
31 #define TCP_ECN_OK      1
32
33 #define HBM_DEBUG 0  // Set to 1 to enable debugging
34 #if HBM_DEBUG
35 #define bpf_printk(fmt, ...)                                    \
36 ({                                                              \
37         char ____fmt[] = fmt;                                   \
38         bpf_trace_printk(____fmt, sizeof(____fmt),              \
39                          ##__VA_ARGS__);                        \
40 })
41 #else
42 #define bpf_printk(fmt, ...)
43 #endif
44
45 #define INITIAL_CREDIT_PACKETS  100
46 #define MAX_BYTES_PER_PACKET    1500
47 #define MARK_THRESH             (40 * MAX_BYTES_PER_PACKET)
48 #define DROP_THRESH             (80 * 5 * MAX_BYTES_PER_PACKET)
49 #define LARGE_PKT_DROP_THRESH   (DROP_THRESH - (15 * MAX_BYTES_PER_PACKET))
50 #define MARK_REGION_SIZE        (LARGE_PKT_DROP_THRESH - MARK_THRESH)
51 #define LARGE_PKT_THRESH        120
52 #define MAX_CREDIT              (100 * MAX_BYTES_PER_PACKET)
53 #define INIT_CREDIT             (INITIAL_CREDIT_PACKETS * MAX_BYTES_PER_PACKET)
54
55 // rate in bytes per ns << 20
56 #define CREDIT_PER_NS(delta, rate) ((((u64)(delta)) * (rate)) >> 20)
57
58 struct bpf_map_def SEC("maps") queue_state = {
59         .type = BPF_MAP_TYPE_CGROUP_STORAGE,
60         .key_size = sizeof(struct bpf_cgroup_storage_key),
61         .value_size = sizeof(struct hbm_vqueue),
62 };
63 BPF_ANNOTATE_KV_PAIR(queue_state, struct bpf_cgroup_storage_key,
64                      struct hbm_vqueue);
65
66 struct bpf_map_def SEC("maps") queue_stats = {
67         .type = BPF_MAP_TYPE_ARRAY,
68         .key_size = sizeof(u32),
69         .value_size = sizeof(struct hbm_queue_stats),
70         .max_entries = 1,
71 };
72 BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats);
73
74 struct hbm_pkt_info {
75         bool    is_ip;
76         bool    is_tcp;
77         short   ecn;
78 };
79
80 static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb,
81                                              struct hbm_pkt_info *pkti)
82 {
83         struct iphdr iph;
84         struct ipv6hdr *ip6h;
85
86         bpf_skb_load_bytes(skb, 0, &iph, 12);
87         if (iph.version == 6) {
88                 ip6h = (struct ipv6hdr *)&iph;
89                 pkti->is_ip = true;
90                 pkti->is_tcp = (ip6h->nexthdr == 6);
91                 pkti->ecn = (ip6h->flow_lbl[0] >> 4) & INET_ECN_MASK;
92         } else if (iph.version == 4) {
93                 pkti->is_ip = true;
94                 pkti->is_tcp = (iph.protocol == 6);
95                 pkti->ecn = iph.tos & INET_ECN_MASK;
96         } else {
97                 pkti->is_ip = false;
98                 pkti->is_tcp = false;
99                 pkti->ecn = 0;
100         }
101 }
102
103 static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate)
104 {
105                 bpf_printk("Initializing queue_state, rate:%d\n", rate * 128);
106                 qdp->lasttime = bpf_ktime_get_ns();
107                 qdp->credit = INIT_CREDIT;
108                 qdp->rate = rate * 128;
109 }
110
111 static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp,
112                                              int len,
113                                              unsigned long long curtime,
114                                              bool congestion_flag,
115                                              bool drop_flag)
116 {
117         if (qsp != NULL) {
118                 // Following is needed for work conserving
119                 __sync_add_and_fetch(&(qsp->bytes_total), len);
120                 if (qsp->stats) {
121                         // Optionally update statistics
122                         if (qsp->firstPacketTime == 0)
123                                 qsp->firstPacketTime = curtime;
124                         qsp->lastPacketTime = curtime;
125                         __sync_add_and_fetch(&(qsp->pkts_total), 1);
126                         if (congestion_flag || drop_flag) {
127                                 __sync_add_and_fetch(&(qsp->pkts_marked), 1);
128                                 __sync_add_and_fetch(&(qsp->bytes_marked), len);
129                         }
130                         if (drop_flag) {
131                                 __sync_add_and_fetch(&(qsp->pkts_dropped), 1);
132                                 __sync_add_and_fetch(&(qsp->bytes_dropped),
133                                                      len);
134                         }
135                 }
136         }
137 }