xref: /aosp_15_r20/external/bcc/examples/networking/sockmap.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2021 Chenyue Zhou
5*387f9dfdSAndroid Build Coastguard Worker
6*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
7*387f9dfdSAndroid Build Coastguard Workerimport os
8*387f9dfdSAndroid Build Coastguard Workerimport sys
9*387f9dfdSAndroid Build Coastguard Workerimport time
10*387f9dfdSAndroid Build Coastguard Workerimport atexit
11*387f9dfdSAndroid Build Coastguard Workerimport argparse
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, BPFAttachType, lib
14*387f9dfdSAndroid Build Coastguard Worker
15*387f9dfdSAndroid Build Coastguard Worker
16*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
17*387f9dfdSAndroid Build Coastguard Worker    ./sockmap.py -c /root/cgroup # attach to /root/cgroup
18*387f9dfdSAndroid Build Coastguard Worker"""
19*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
20*387f9dfdSAndroid Build Coastguard Worker        description="pipe data across multiple sockets",
21*387f9dfdSAndroid Build Coastguard Worker        formatter_class=argparse.RawDescriptionHelpFormatter,
22*387f9dfdSAndroid Build Coastguard Worker        epilog=examples)
23*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-c", "--cgroup", required=True,
24*387f9dfdSAndroid Build Coastguard Worker        help="Specify the cgroup address. Note. must be cgroup2")
25*387f9dfdSAndroid Build Coastguard Worker
26*387f9dfdSAndroid Build Coastguard Workerbpf_text = '''
27*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h>
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker#define MAX_SOCK_OPS_MAP_ENTRIES 65535
30*387f9dfdSAndroid Build Coastguard Worker
31*387f9dfdSAndroid Build Coastguard Workerstruct sock_key {
32*387f9dfdSAndroid Build Coastguard Worker    u32 remote_ip4;
33*387f9dfdSAndroid Build Coastguard Worker    u32 local_ip4;
34*387f9dfdSAndroid Build Coastguard Worker    u32 remote_port;
35*387f9dfdSAndroid Build Coastguard Worker    u32 local_port;
36*387f9dfdSAndroid Build Coastguard Worker    u32 family;
37*387f9dfdSAndroid Build Coastguard Worker};
38*387f9dfdSAndroid Build Coastguard Worker
39*387f9dfdSAndroid Build Coastguard WorkerBPF_SOCKHASH(sock_hash, struct sock_key, MAX_SOCK_OPS_MAP_ENTRIES);
40*387f9dfdSAndroid Build Coastguard Worker
41*387f9dfdSAndroid Build Coastguard Workerstatic __always_inline void bpf_sock_ops_ipv4(struct bpf_sock_ops *skops) {
42*387f9dfdSAndroid Build Coastguard Worker    struct sock_key skk = {
43*387f9dfdSAndroid Build Coastguard Worker        .remote_ip4 = skops->remote_ip4,
44*387f9dfdSAndroid Build Coastguard Worker        .local_ip4  = skops->local_ip4,
45*387f9dfdSAndroid Build Coastguard Worker        .local_port = skops->local_port,
46*387f9dfdSAndroid Build Coastguard Worker        .remote_port  = bpf_ntohl(skops->remote_port),
47*387f9dfdSAndroid Build Coastguard Worker        .family = skops->family,
48*387f9dfdSAndroid Build Coastguard Worker    };
49*387f9dfdSAndroid Build Coastguard Worker    int ret;
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard Worker    bpf_trace_printk("remote-port: %d, local-port: %d\\n", skk.remote_port,
52*387f9dfdSAndroid Build Coastguard Worker                     skk.local_port);
53*387f9dfdSAndroid Build Coastguard Worker    ret = sock_hash.sock_hash_update(skops, &skk, BPF_NOEXIST);
54*387f9dfdSAndroid Build Coastguard Worker    if (ret) {
55*387f9dfdSAndroid Build Coastguard Worker        bpf_trace_printk("bpf_sock_hash_update() failed. %d\\n", -ret);
56*387f9dfdSAndroid Build Coastguard Worker        return;
57*387f9dfdSAndroid Build Coastguard Worker    }
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker    bpf_trace_printk("Sockhash op: %d, port %d --> %d\\n", skops->op,
60*387f9dfdSAndroid Build Coastguard Worker                     skk.local_port, skk.remote_port);
61*387f9dfdSAndroid Build Coastguard Worker}
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Workerint bpf_sockhash(struct bpf_sock_ops *skops) {
64*387f9dfdSAndroid Build Coastguard Worker    u32 op = skops->op;
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard Worker    /* ipv4 only */
67*387f9dfdSAndroid Build Coastguard Worker    if (skops->family != AF_INET)
68*387f9dfdSAndroid Build Coastguard Worker	return 0;
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Worker    switch (op) {
71*387f9dfdSAndroid Build Coastguard Worker        case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
72*387f9dfdSAndroid Build Coastguard Worker        case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
73*387f9dfdSAndroid Build Coastguard Worker            bpf_sock_ops_ipv4(skops);
74*387f9dfdSAndroid Build Coastguard Worker            break;
75*387f9dfdSAndroid Build Coastguard Worker        default:
76*387f9dfdSAndroid Build Coastguard Worker            break;
77*387f9dfdSAndroid Build Coastguard Worker    }
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Worker    return 0;
80*387f9dfdSAndroid Build Coastguard Worker}
81*387f9dfdSAndroid Build Coastguard Worker
82*387f9dfdSAndroid Build Coastguard Workerint bpf_redir(struct sk_msg_md *msg) {
83*387f9dfdSAndroid Build Coastguard Worker    if (msg->family != AF_INET)
84*387f9dfdSAndroid Build Coastguard Worker        return SK_PASS;
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Worker    if (msg->remote_ip4 != msg->local_ip4)
87*387f9dfdSAndroid Build Coastguard Worker        return SK_PASS;
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker    struct sock_key skk = {
90*387f9dfdSAndroid Build Coastguard Worker        .remote_ip4 = msg->local_ip4,
91*387f9dfdSAndroid Build Coastguard Worker        .local_ip4  = msg->remote_ip4,
92*387f9dfdSAndroid Build Coastguard Worker        .local_port = bpf_ntohl(msg->remote_port),
93*387f9dfdSAndroid Build Coastguard Worker        .remote_port = msg->local_port,
94*387f9dfdSAndroid Build Coastguard Worker        .family = msg->family,
95*387f9dfdSAndroid Build Coastguard Worker    };
96*387f9dfdSAndroid Build Coastguard Worker    int ret = 0;
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard Worker    ret = sock_hash.msg_redirect_hash(msg, &skk, BPF_F_INGRESS);
99*387f9dfdSAndroid Build Coastguard Worker    bpf_trace_printk("try redirect port %d --> %d\\n", msg->local_port,
100*387f9dfdSAndroid Build Coastguard Worker                     bpf_ntohl(msg->remote_port));
101*387f9dfdSAndroid Build Coastguard Worker    if (ret != SK_PASS)
102*387f9dfdSAndroid Build Coastguard Worker        bpf_trace_printk("redirect port %d --> %d failed\\n", msg->local_port,
103*387f9dfdSAndroid Build Coastguard Worker                         bpf_ntohl(msg->remote_port));
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Worker    return ret;
106*387f9dfdSAndroid Build Coastguard Worker}
107*387f9dfdSAndroid Build Coastguard Worker'''
108*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
109*387f9dfdSAndroid Build Coastguard Workerbpf = BPF(text=bpf_text)
110*387f9dfdSAndroid Build Coastguard Workerfunc_sock_ops = bpf.load_func("bpf_sockhash", bpf.SOCK_OPS)
111*387f9dfdSAndroid Build Coastguard Workerfunc_sock_redir = bpf.load_func("bpf_redir", bpf.SK_MSG)
112*387f9dfdSAndroid Build Coastguard Worker# raise if error
113*387f9dfdSAndroid Build Coastguard Workerfd = os.open(args.cgroup, os.O_RDONLY)
114*387f9dfdSAndroid Build Coastguard Workermap_fd = lib.bpf_table_fd(bpf.module, b"sock_hash")
115*387f9dfdSAndroid Build Coastguard Workerbpf.attach_func(func_sock_ops, fd, BPFAttachType.CGROUP_SOCK_OPS)
116*387f9dfdSAndroid Build Coastguard Workerbpf.attach_func(func_sock_redir, map_fd, BPFAttachType.SK_MSG_VERDICT)
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Workerdef detach_all():
119*387f9dfdSAndroid Build Coastguard Worker    bpf.detach_func(func_sock_ops, fd, BPFAttachType.CGROUP_SOCK_OPS)
120*387f9dfdSAndroid Build Coastguard Worker    bpf.detach_func(func_sock_redir, map_fd, BPFAttachType.SK_MSG_VERDICT)
121*387f9dfdSAndroid Build Coastguard Worker    print("Detaching...")
122*387f9dfdSAndroid Build Coastguard Worker
123*387f9dfdSAndroid Build Coastguard Workeratexit.register(detach_all)
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Workerwhile True:
126*387f9dfdSAndroid Build Coastguard Worker    try:
127*387f9dfdSAndroid Build Coastguard Worker        bpf.trace_print()
128*387f9dfdSAndroid Build Coastguard Worker        sleep(1)
129*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
130*387f9dfdSAndroid Build Coastguard Worker        sys.exit(0)
131