root/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. update_event_map
  2. SEC

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <stddef.h>
   3 #include <string.h>
   4 #include <netinet/in.h>
   5 #include <linux/bpf.h>
   6 #include <linux/if_ether.h>
   7 #include <linux/if_packet.h>
   8 #include <linux/ip.h>
   9 #include <linux/ipv6.h>
  10 #include <linux/types.h>
  11 #include <linux/socket.h>
  12 #include <linux/tcp.h>
  13 #include "bpf_helpers.h"
  14 #include "bpf_endian.h"
  15 #include "test_tcpbpf.h"
  16 
  17 struct {
  18         __uint(type, BPF_MAP_TYPE_ARRAY);
  19         __uint(max_entries, 4);
  20         __type(key, __u32);
  21         __type(value, struct tcpbpf_globals);
  22 } global_map SEC(".maps");
  23 
  24 struct {
  25         __uint(type, BPF_MAP_TYPE_ARRAY);
  26         __uint(max_entries, 2);
  27         __type(key, __u32);
  28         __type(value, int);
  29 } sockopt_results SEC(".maps");
  30 
  31 static inline void update_event_map(int event)
  32 {
  33         __u32 key = 0;
  34         struct tcpbpf_globals g, *gp;
  35 
  36         gp = bpf_map_lookup_elem(&global_map, &key);
  37         if (gp == NULL) {
  38                 struct tcpbpf_globals g = {0};
  39 
  40                 g.event_map |= (1 << event);
  41                 bpf_map_update_elem(&global_map, &key, &g,
  42                             BPF_ANY);
  43         } else {
  44                 g = *gp;
  45                 g.event_map |= (1 << event);
  46                 bpf_map_update_elem(&global_map, &key, &g,
  47                             BPF_ANY);
  48         }
  49 }
  50 
  51 int _version SEC("version") = 1;
  52 
  53 SEC("sockops")
  54 int bpf_testcb(struct bpf_sock_ops *skops)
  55 {
  56         char header[sizeof(struct ipv6hdr) + sizeof(struct tcphdr)];
  57         struct tcphdr *thdr;
  58         int good_call_rv = 0;
  59         int bad_call_rv = 0;
  60         int save_syn = 1;
  61         int rv = -1;
  62         int v = 0;
  63         int op;
  64 
  65         op = (int) skops->op;
  66 
  67         update_event_map(op);
  68 
  69         switch (op) {
  70         case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
  71                 /* Test failure to set largest cb flag (assumes not defined) */
  72                 bad_call_rv = bpf_sock_ops_cb_flags_set(skops, 0x80);
  73                 /* Set callback */
  74                 good_call_rv = bpf_sock_ops_cb_flags_set(skops,
  75                                                  BPF_SOCK_OPS_STATE_CB_FLAG);
  76                 /* Update results */
  77                 {
  78                         __u32 key = 0;
  79                         struct tcpbpf_globals g, *gp;
  80 
  81                         gp = bpf_map_lookup_elem(&global_map, &key);
  82                         if (!gp)
  83                                 break;
  84                         g = *gp;
  85                         g.bad_cb_test_rv = bad_call_rv;
  86                         g.good_cb_test_rv = good_call_rv;
  87                         bpf_map_update_elem(&global_map, &key, &g,
  88                                             BPF_ANY);
  89                 }
  90                 break;
  91         case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
  92                 skops->sk_txhash = 0x12345f;
  93                 v = 0xff;
  94                 rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v,
  95                                     sizeof(v));
  96                 if (skops->family == AF_INET6) {
  97                         v = bpf_getsockopt(skops, IPPROTO_TCP, TCP_SAVED_SYN,
  98                                            header, (sizeof(struct ipv6hdr) +
  99                                                     sizeof(struct tcphdr)));
 100                         if (!v) {
 101                                 int offset = sizeof(struct ipv6hdr);
 102 
 103                                 thdr = (struct tcphdr *)(header + offset);
 104                                 v = thdr->syn;
 105                                 __u32 key = 1;
 106 
 107                                 bpf_map_update_elem(&sockopt_results, &key, &v,
 108                                                     BPF_ANY);
 109                         }
 110                 }
 111                 break;
 112         case BPF_SOCK_OPS_RTO_CB:
 113                 break;
 114         case BPF_SOCK_OPS_RETRANS_CB:
 115                 break;
 116         case BPF_SOCK_OPS_STATE_CB:
 117                 if (skops->args[1] == BPF_TCP_CLOSE) {
 118                         __u32 key = 0;
 119                         struct tcpbpf_globals g, *gp;
 120 
 121                         gp = bpf_map_lookup_elem(&global_map, &key);
 122                         if (!gp)
 123                                 break;
 124                         g = *gp;
 125                         if (skops->args[0] == BPF_TCP_LISTEN) {
 126                                 g.num_listen++;
 127                         } else {
 128                                 g.total_retrans = skops->total_retrans;
 129                                 g.data_segs_in = skops->data_segs_in;
 130                                 g.data_segs_out = skops->data_segs_out;
 131                                 g.bytes_received = skops->bytes_received;
 132                                 g.bytes_acked = skops->bytes_acked;
 133                         }
 134                         bpf_map_update_elem(&global_map, &key, &g,
 135                                             BPF_ANY);
 136                 }
 137                 break;
 138         case BPF_SOCK_OPS_TCP_LISTEN_CB:
 139                 bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
 140                 v = bpf_setsockopt(skops, IPPROTO_TCP, TCP_SAVE_SYN,
 141                                    &save_syn, sizeof(save_syn));
 142                 /* Update global map w/ result of setsock opt */
 143                 __u32 key = 0;
 144 
 145                 bpf_map_update_elem(&sockopt_results, &key, &v, BPF_ANY);
 146                 break;
 147         default:
 148                 rv = -1;
 149         }
 150         skops->reply = rv;
 151         return 1;
 152 }
 153 char _license[] SEC("license") = "GPL";

/* [<][>][^][v][top][bottom][index][help] */