linux/samples/sockmap/sockmap_kern.c
<<
>>
Prefs
   1/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of version 2 of the GNU General Public
   5 * License as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful, but
   8 * WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10 * General Public License for more details.
  11 */
  12#include <uapi/linux/bpf.h>
  13#include <uapi/linux/if_ether.h>
  14#include <uapi/linux/if_packet.h>
  15#include <uapi/linux/ip.h>
  16#include "../../tools/testing/selftests/bpf/bpf_helpers.h"
  17#include "../../tools/testing/selftests/bpf/bpf_endian.h"
  18
  19/* Sockmap sample program connects a client and a backend together
  20 * using cgroups.
  21 *
  22 *    client:X <---> frontend:80 client:X <---> backend:80
  23 *
  24 * For simplicity we hard code values here and bind 1:1. The hard
  25 * coded values are part of the setup in sockmap.sh script that
  26 * is associated with this BPF program.
  27 *
  28 * The bpf_printk is verbose and prints information as connections
  29 * are established and verdicts are decided.
  30 */
  31
  32#define bpf_printk(fmt, ...)                                    \
  33({                                                              \
  34               char ____fmt[] = fmt;                            \
  35               bpf_trace_printk(____fmt, sizeof(____fmt),       \
  36                                ##__VA_ARGS__);                 \
  37})
  38
  39struct bpf_map_def SEC("maps") sock_map = {
  40        .type = BPF_MAP_TYPE_SOCKMAP,
  41        .key_size = sizeof(int),
  42        .value_size = sizeof(int),
  43        .max_entries = 20,
  44};
  45
  46SEC("sk_skb1")
  47int bpf_prog1(struct __sk_buff *skb)
  48{
  49        return skb->len;
  50}
  51
  52SEC("sk_skb2")
  53int bpf_prog2(struct __sk_buff *skb)
  54{
  55        __u32 lport = skb->local_port;
  56        __u32 rport = skb->remote_port;
  57        int ret = 0;
  58
  59        if (lport == 10000)
  60                ret = 10;
  61        else
  62                ret = 1;
  63
  64        bpf_printk("sockmap: %d -> %d @ %d\n", lport, bpf_ntohl(rport), ret);
  65        return bpf_sk_redirect_map(skb, &sock_map, ret, 0);
  66}
  67
  68SEC("sockops")
  69int bpf_sockmap(struct bpf_sock_ops *skops)
  70{
  71        __u32 lport, rport;
  72        int op, err = 0, index, key, ret;
  73
  74
  75        op = (int) skops->op;
  76
  77        switch (op) {
  78        case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
  79                lport = skops->local_port;
  80                rport = skops->remote_port;
  81
  82                if (lport == 10000) {
  83                        ret = 1;
  84                        err = bpf_sock_map_update(skops, &sock_map, &ret,
  85                                                  BPF_NOEXIST);
  86                        bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
  87                                   lport, bpf_ntohl(rport), err);
  88                }
  89                break;
  90        case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
  91                lport = skops->local_port;
  92                rport = skops->remote_port;
  93
  94                if (bpf_ntohl(rport) == 10001) {
  95                        ret = 10;
  96                        err = bpf_sock_map_update(skops, &sock_map, &ret,
  97                                                  BPF_NOEXIST);
  98                        bpf_printk("active(%i -> %i) map ctx update err: %d\n",
  99                                   lport, bpf_ntohl(rport), err);
 100                }
 101                break;
 102        default:
 103                break;
 104        }
 105
 106        return 0;
 107}
 108char _license[] SEC("license") = "GPL";
 109