| rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame] | 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 |  | 
|  | 39 | struct 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 |  | 
|  | 46 | SEC("sk_skb1") | 
|  | 47 | int bpf_prog1(struct __sk_buff *skb) | 
|  | 48 | { | 
|  | 49 | return skb->len; | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | SEC("sk_skb2") | 
|  | 53 | int 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 |  | 
|  | 68 | SEC("sockops") | 
|  | 69 | int 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 | } | 
|  | 108 | char _license[] SEC("license") = "GPL"; |