linux/tools/testing/selftests/bpf/test_tcpbpf_kern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stddef.h>
   3#include <string.h>
   4#include <linux/bpf.h>
   5#include <linux/if_ether.h>
   6#include <linux/if_packet.h>
   7#include <linux/ip.h>
   8#include <linux/types.h>
   9#include <linux/socket.h>
  10#include <linux/tcp.h>
  11#include <netinet/in.h>
  12#include "bpf_helpers.h"
  13#include "bpf_endian.h"
  14#include "test_tcpbpf.h"
  15
  16struct bpf_map_def SEC("maps") global_map = {
  17        .type = BPF_MAP_TYPE_ARRAY,
  18        .key_size = sizeof(__u32),
  19        .value_size = sizeof(struct tcpbpf_globals),
  20        .max_entries = 2,
  21};
  22
  23static inline void update_event_map(int event)
  24{
  25        __u32 key = 0;
  26        struct tcpbpf_globals g, *gp;
  27
  28        gp = bpf_map_lookup_elem(&global_map, &key);
  29        if (gp == NULL) {
  30                struct tcpbpf_globals g = {0};
  31
  32                g.event_map |= (1 << event);
  33                bpf_map_update_elem(&global_map, &key, &g,
  34                            BPF_ANY);
  35        } else {
  36                g = *gp;
  37                g.event_map |= (1 << event);
  38                bpf_map_update_elem(&global_map, &key, &g,
  39                            BPF_ANY);
  40        }
  41}
  42
  43int _version SEC("version") = 1;
  44
  45SEC("sockops")
  46int bpf_testcb(struct bpf_sock_ops *skops)
  47{
  48        int rv = -1;
  49        int bad_call_rv = 0;
  50        int good_call_rv = 0;
  51        int op;
  52        int v = 0;
  53
  54        op = (int) skops->op;
  55
  56        update_event_map(op);
  57
  58        switch (op) {
  59        case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
  60                /* Test failure to set largest cb flag (assumes not defined) */
  61                bad_call_rv = bpf_sock_ops_cb_flags_set(skops, 0x80);
  62                /* Set callback */
  63                good_call_rv = bpf_sock_ops_cb_flags_set(skops,
  64                                                 BPF_SOCK_OPS_STATE_CB_FLAG);
  65                /* Update results */
  66                {
  67                        __u32 key = 0;
  68                        struct tcpbpf_globals g, *gp;
  69
  70                        gp = bpf_map_lookup_elem(&global_map, &key);
  71                        if (!gp)
  72                                break;
  73                        g = *gp;
  74                        g.bad_cb_test_rv = bad_call_rv;
  75                        g.good_cb_test_rv = good_call_rv;
  76                        bpf_map_update_elem(&global_map, &key, &g,
  77                                            BPF_ANY);
  78                }
  79                break;
  80        case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
  81                skops->sk_txhash = 0x12345f;
  82                v = 0xff;
  83                rv = bpf_setsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v,
  84                                    sizeof(v));
  85                break;
  86        case BPF_SOCK_OPS_RTO_CB:
  87                break;
  88        case BPF_SOCK_OPS_RETRANS_CB:
  89                break;
  90        case BPF_SOCK_OPS_STATE_CB:
  91                if (skops->args[1] == BPF_TCP_CLOSE) {
  92                        __u32 key = 0;
  93                        struct tcpbpf_globals g, *gp;
  94
  95                        gp = bpf_map_lookup_elem(&global_map, &key);
  96                        if (!gp)
  97                                break;
  98                        g = *gp;
  99                        if (skops->args[0] == BPF_TCP_LISTEN) {
 100                                g.num_listen++;
 101                        } else {
 102                                g.total_retrans = skops->total_retrans;
 103                                g.data_segs_in = skops->data_segs_in;
 104                                g.data_segs_out = skops->data_segs_out;
 105                                g.bytes_received = skops->bytes_received;
 106                                g.bytes_acked = skops->bytes_acked;
 107                        }
 108                        bpf_map_update_elem(&global_map, &key, &g,
 109                                            BPF_ANY);
 110                }
 111                break;
 112        case BPF_SOCK_OPS_TCP_LISTEN_CB:
 113                bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
 114                break;
 115        default:
 116                rv = -1;
 117        }
 118        skops->reply = rv;
 119        return 1;
 120}
 121char _license[] SEC("license") = "GPL";
 122