1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Facebook */
5 #include <netinet/in.h>
8 #include "bpf_helpers.h"
9 #include "bpf_endian.h"
11 enum bpf_addr_array_idx
{
14 __NR_BPF_ADDR_ARRAY_IDX
,
17 enum bpf_result_array_idx
{
21 __NR_BPF_RESULT_ARRAY_IDX
,
24 enum bpf_linum_array_idx
{
27 __NR_BPF_LINUM_ARRAY_IDX
,
30 struct bpf_map_def
SEC("maps") addr_map
= {
31 .type
= BPF_MAP_TYPE_ARRAY
,
32 .key_size
= sizeof(__u32
),
33 .value_size
= sizeof(struct sockaddr_in6
),
34 .max_entries
= __NR_BPF_ADDR_ARRAY_IDX
,
37 struct bpf_map_def
SEC("maps") sock_result_map
= {
38 .type
= BPF_MAP_TYPE_ARRAY
,
39 .key_size
= sizeof(__u32
),
40 .value_size
= sizeof(struct bpf_sock
),
41 .max_entries
= __NR_BPF_RESULT_ARRAY_IDX
,
44 struct bpf_map_def
SEC("maps") tcp_sock_result_map
= {
45 .type
= BPF_MAP_TYPE_ARRAY
,
46 .key_size
= sizeof(__u32
),
47 .value_size
= sizeof(struct bpf_tcp_sock
),
48 .max_entries
= __NR_BPF_RESULT_ARRAY_IDX
,
51 struct bpf_map_def
SEC("maps") linum_map
= {
52 .type
= BPF_MAP_TYPE_ARRAY
,
53 .key_size
= sizeof(__u32
),
54 .value_size
= sizeof(__u32
),
55 .max_entries
= __NR_BPF_LINUM_ARRAY_IDX
,
58 static bool is_loopback6(__u32
*a6
)
60 return !a6
[0] && !a6
[1] && !a6
[2] && a6
[3] == bpf_htonl(1);
63 static void skcpy(struct bpf_sock
*dst
,
64 const struct bpf_sock
*src
)
66 dst
->bound_dev_if
= src
->bound_dev_if
;
67 dst
->family
= src
->family
;
68 dst
->type
= src
->type
;
69 dst
->protocol
= src
->protocol
;
70 dst
->mark
= src
->mark
;
71 dst
->priority
= src
->priority
;
72 dst
->src_ip4
= src
->src_ip4
;
73 dst
->src_ip6
[0] = src
->src_ip6
[0];
74 dst
->src_ip6
[1] = src
->src_ip6
[1];
75 dst
->src_ip6
[2] = src
->src_ip6
[2];
76 dst
->src_ip6
[3] = src
->src_ip6
[3];
77 dst
->src_port
= src
->src_port
;
78 dst
->dst_ip4
= src
->dst_ip4
;
79 dst
->dst_ip6
[0] = src
->dst_ip6
[0];
80 dst
->dst_ip6
[1] = src
->dst_ip6
[1];
81 dst
->dst_ip6
[2] = src
->dst_ip6
[2];
82 dst
->dst_ip6
[3] = src
->dst_ip6
[3];
83 dst
->dst_port
= src
->dst_port
;
84 dst
->state
= src
->state
;
87 static void tpcpy(struct bpf_tcp_sock
*dst
,
88 const struct bpf_tcp_sock
*src
)
90 dst
->snd_cwnd
= src
->snd_cwnd
;
91 dst
->srtt_us
= src
->srtt_us
;
92 dst
->rtt_min
= src
->rtt_min
;
93 dst
->snd_ssthresh
= src
->snd_ssthresh
;
94 dst
->rcv_nxt
= src
->rcv_nxt
;
95 dst
->snd_nxt
= src
->snd_nxt
;
96 dst
->snd_una
= src
->snd_una
;
97 dst
->mss_cache
= src
->mss_cache
;
98 dst
->ecn_flags
= src
->ecn_flags
;
99 dst
->rate_delivered
= src
->rate_delivered
;
100 dst
->rate_interval_us
= src
->rate_interval_us
;
101 dst
->packets_out
= src
->packets_out
;
102 dst
->retrans_out
= src
->retrans_out
;
103 dst
->total_retrans
= src
->total_retrans
;
104 dst
->segs_in
= src
->segs_in
;
105 dst
->data_segs_in
= src
->data_segs_in
;
106 dst
->segs_out
= src
->segs_out
;
107 dst
->data_segs_out
= src
->data_segs_out
;
108 dst
->lost_out
= src
->lost_out
;
109 dst
->sacked_out
= src
->sacked_out
;
110 dst
->bytes_received
= src
->bytes_received
;
111 dst
->bytes_acked
= src
->bytes_acked
;
116 bpf_map_update_elem(&linum_map, &linum_idx, &linum, 0); \
120 SEC("cgroup_skb/egress")
121 int egress_read_sock_fields(struct __sk_buff
*skb
)
123 __u32 srv_idx
= ADDR_SRV_IDX
, cli_idx
= ADDR_CLI_IDX
, result_idx
;
124 struct sockaddr_in6
*srv_sa6
, *cli_sa6
;
125 struct bpf_tcp_sock
*tp
, *tp_ret
;
126 struct bpf_sock
*sk
, *sk_ret
;
127 __u32 linum
, linum_idx
;
129 linum_idx
= EGRESS_LINUM_IDX
;
132 if (!sk
|| sk
->state
== 10)
135 sk
= bpf_sk_fullsock(sk
);
136 if (!sk
|| sk
->family
!= AF_INET6
|| sk
->protocol
!= IPPROTO_TCP
||
137 !is_loopback6(sk
->src_ip6
))
140 tp
= bpf_tcp_sock(sk
);
144 srv_sa6
= bpf_map_lookup_elem(&addr_map
, &srv_idx
);
145 cli_sa6
= bpf_map_lookup_elem(&addr_map
, &cli_idx
);
146 if (!srv_sa6
|| !cli_sa6
)
149 if (sk
->src_port
== bpf_ntohs(srv_sa6
->sin6_port
))
150 result_idx
= EGRESS_SRV_IDX
;
151 else if (sk
->src_port
== bpf_ntohs(cli_sa6
->sin6_port
))
152 result_idx
= EGRESS_CLI_IDX
;
156 sk_ret
= bpf_map_lookup_elem(&sock_result_map
, &result_idx
);
157 tp_ret
= bpf_map_lookup_elem(&tcp_sock_result_map
, &result_idx
);
158 if (!sk_ret
|| !tp_ret
)
167 SEC("cgroup_skb/ingress")
168 int ingress_read_sock_fields(struct __sk_buff
*skb
)
170 __u32 srv_idx
= ADDR_SRV_IDX
, result_idx
= INGRESS_LISTEN_IDX
;
171 struct bpf_tcp_sock
*tp
, *tp_ret
;
172 struct bpf_sock
*sk
, *sk_ret
;
173 struct sockaddr_in6
*srv_sa6
;
174 __u32 linum
, linum_idx
;
176 linum_idx
= INGRESS_LINUM_IDX
;
179 if (!sk
|| sk
->family
!= AF_INET6
|| !is_loopback6(sk
->src_ip6
))
182 srv_sa6
= bpf_map_lookup_elem(&addr_map
, &srv_idx
);
183 if (!srv_sa6
|| sk
->src_port
!= bpf_ntohs(srv_sa6
->sin6_port
))
186 if (sk
->state
!= 10 && sk
->state
!= 12)
189 sk
= bpf_get_listener_sock(sk
);
193 tp
= bpf_tcp_sock(sk
);
197 sk_ret
= bpf_map_lookup_elem(&sock_result_map
, &result_idx
);
198 tp_ret
= bpf_map_lookup_elem(&tcp_sock_result_map
, &result_idx
);
199 if (!sk_ret
|| !tp_ret
)
208 char _license
[] SEC("license") = "GPL";