1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License.
5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at
6b1b8bc3fSopenharmony_ci *
7b1b8bc3fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b1b8bc3fSopenharmony_ci *
9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and
13b1b8bc3fSopenharmony_ci * limitations under the License.
14b1b8bc3fSopenharmony_ci */
15b1b8bc3fSopenharmony_ci
16b1b8bc3fSopenharmony_ci#include <stdint.h>
17b1b8bc3fSopenharmony_ci#include <linux/bpf.h>
18b1b8bc3fSopenharmony_ci
19b1b8bc3fSopenharmony_ci#define SEC(NAME) __attribute__((section(NAME), used))
20b1b8bc3fSopenharmony_ci
21b1b8bc3fSopenharmony_cistatic const int APP_STATS_MAP_SIZE = 5000;
22b1b8bc3fSopenharmony_cistatic const int IFACE_STATS_MAP_SIZE = 1000;
23b1b8bc3fSopenharmony_cistatic const int IFACE_NAM_MAP_SIZE = 1000;
24b1b8bc3fSopenharmony_cistatic const int IFNAM_SIZE = 16;
25b1b8bc3fSopenharmony_ci
26b1b8bc3fSopenharmony_citypedef struct {
27b1b8bc3fSopenharmony_ci    unsigned int type; // actual bpf_map_type
28b1b8bc3fSopenharmony_ci    unsigned int key_size;
29b1b8bc3fSopenharmony_ci    unsigned int value_size;
30b1b8bc3fSopenharmony_ci    unsigned int max_entries;
31b1b8bc3fSopenharmony_ci    unsigned int map_flags;
32b1b8bc3fSopenharmony_ci    unsigned int inner_map_idx;
33b1b8bc3fSopenharmony_ci    unsigned int numa_node;
34b1b8bc3fSopenharmony_ci} bpf_map_def;
35b1b8bc3fSopenharmony_ci
36b1b8bc3fSopenharmony_citypedef struct {
37b1b8bc3fSopenharmony_ci    uint64_t rx_packets;
38b1b8bc3fSopenharmony_ci    uint64_t rx_bytes;
39b1b8bc3fSopenharmony_ci    uint64_t tx_packets;
40b1b8bc3fSopenharmony_ci    uint64_t tx_bytes;
41b1b8bc3fSopenharmony_ci} stats_value;
42b1b8bc3fSopenharmony_ci
43b1b8bc3fSopenharmony_citypedef struct {
44b1b8bc3fSopenharmony_ci    char name[IFNAM_SIZE];
45b1b8bc3fSopenharmony_ci} iface_name;
46b1b8bc3fSopenharmony_ci
47b1b8bc3fSopenharmony_cibpf_map_def SEC("maps") iface_stats_map = {
48b1b8bc3fSopenharmony_ci    .type = BPF_MAP_TYPE_HASH,
49b1b8bc3fSopenharmony_ci    .key_size = sizeof(uint32_t),
50b1b8bc3fSopenharmony_ci    .value_size = sizeof(stats_value),
51b1b8bc3fSopenharmony_ci    .max_entries = IFACE_STATS_MAP_SIZE,
52b1b8bc3fSopenharmony_ci    .map_flags = 0,
53b1b8bc3fSopenharmony_ci    .inner_map_idx = 0,
54b1b8bc3fSopenharmony_ci    .numa_node = 0,
55b1b8bc3fSopenharmony_ci};
56b1b8bc3fSopenharmony_ci
57b1b8bc3fSopenharmony_cibpf_map_def SEC("maps") iface_name_map = {
58b1b8bc3fSopenharmony_ci    .type = BPF_MAP_TYPE_HASH,
59b1b8bc3fSopenharmony_ci    .key_size = sizeof(uint32_t),
60b1b8bc3fSopenharmony_ci    .value_size = sizeof(iface_name),
61b1b8bc3fSopenharmony_ci    .max_entries = IFACE_NAM_MAP_SIZE,
62b1b8bc3fSopenharmony_ci    .map_flags = 0,
63b1b8bc3fSopenharmony_ci    .inner_map_idx = 0,
64b1b8bc3fSopenharmony_ci    .numa_node = 0,
65b1b8bc3fSopenharmony_ci};
66b1b8bc3fSopenharmony_ci
67b1b8bc3fSopenharmony_cibpf_map_def SEC("maps") app_uid_stats_map = {
68b1b8bc3fSopenharmony_ci    .type = BPF_MAP_TYPE_HASH,
69b1b8bc3fSopenharmony_ci    .key_size = sizeof(uint32_t),
70b1b8bc3fSopenharmony_ci    .value_size = sizeof(stats_value),
71b1b8bc3fSopenharmony_ci    .max_entries = APP_STATS_MAP_SIZE,
72b1b8bc3fSopenharmony_ci    .map_flags = 0,
73b1b8bc3fSopenharmony_ci    .inner_map_idx = 0,
74b1b8bc3fSopenharmony_ci    .numa_node = 0,
75b1b8bc3fSopenharmony_ci};
76b1b8bc3fSopenharmony_ci
77b1b8bc3fSopenharmony_cistatic SEC("cgroup_skb/uid/ingress") int bpf_cgroup_skb_uid_ingress(struct __sk_buff *skb)
78b1b8bc3fSopenharmony_ci{
79b1b8bc3fSopenharmony_ci    uint32_t sock_uid = bpf_get_socket_uid(skb);
80b1b8bc3fSopenharmony_ci
81b1b8bc3fSopenharmony_ci    stats_value *value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
82b1b8bc3fSopenharmony_ci    if (!value) {
83b1b8bc3fSopenharmony_ci        stats_value newValue = {};
84b1b8bc3fSopenharmony_ci        bpf_map_update_elem(&app_uid_stats_map, &sock_uid, &newValue, BPF_NOEXIST);
85b1b8bc3fSopenharmony_ci        value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
86b1b8bc3fSopenharmony_ci    }
87b1b8bc3fSopenharmony_ci
88b1b8bc3fSopenharmony_ci    if (value) {
89b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->rx_packets, 1);
90b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->rx_bytes, skb->len);
91b1b8bc3fSopenharmony_ci
92b1b8bc3fSopenharmony_ci        const char log[] = "[Uid ingress] sock_uid = %d, value->rx_packets = %d, value->rx_bytes = %d";
93b1b8bc3fSopenharmony_ci        bpf_trace_printk(log, sizeof(log), sock_uid, value->rx_packets, value->rx_bytes);
94b1b8bc3fSopenharmony_ci    }
95b1b8bc3fSopenharmony_ci    return 1;
96b1b8bc3fSopenharmony_ci}
97b1b8bc3fSopenharmony_ci
98b1b8bc3fSopenharmony_cistatic SEC("cgroup_skb/uid/egress") int bpf_cgroup_skb_uid_egress(struct __sk_buff *skb)
99b1b8bc3fSopenharmony_ci{
100b1b8bc3fSopenharmony_ci    uint32_t sock_uid = bpf_get_socket_uid(skb);
101b1b8bc3fSopenharmony_ci
102b1b8bc3fSopenharmony_ci    stats_value *value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
103b1b8bc3fSopenharmony_ci    if (!value) {
104b1b8bc3fSopenharmony_ci        stats_value newValue = {};
105b1b8bc3fSopenharmony_ci        bpf_map_update_elem(&app_uid_stats_map, &sock_uid, &newValue, BPF_NOEXIST);
106b1b8bc3fSopenharmony_ci        value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
107b1b8bc3fSopenharmony_ci    }
108b1b8bc3fSopenharmony_ci
109b1b8bc3fSopenharmony_ci    if (value) {
110b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->tx_packets, 1);
111b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->tx_bytes, skb->len);
112b1b8bc3fSopenharmony_ci
113b1b8bc3fSopenharmony_ci        const char log[] = "[Uid egress] sock_uid = %d, value->tx_packets = %d, value->tx_bytes = %d";
114b1b8bc3fSopenharmony_ci        bpf_trace_printk(log, sizeof(log), sock_uid, value->tx_packets, value->tx_bytes);
115b1b8bc3fSopenharmony_ci    }
116b1b8bc3fSopenharmony_ci    return 1;
117b1b8bc3fSopenharmony_ci}
118b1b8bc3fSopenharmony_ci
119b1b8bc3fSopenharmony_cistatic SEC("socket/iface/ingress") void bpf_socket_iface_ingress(struct __sk_buff *skb)
120b1b8bc3fSopenharmony_ci{
121b1b8bc3fSopenharmony_ci    uint32_t key = skb->ifindex;
122b1b8bc3fSopenharmony_ci
123b1b8bc3fSopenharmony_ci    stats_value *value = bpf_map_lookup_elem(&iface_stats_map, &key);
124b1b8bc3fSopenharmony_ci    if (!value) {
125b1b8bc3fSopenharmony_ci        stats_value newValue = {};
126b1b8bc3fSopenharmony_ci        bpf_map_update_elem(&iface_stats_map, &key, &newValue, BPF_NOEXIST);
127b1b8bc3fSopenharmony_ci        value = bpf_map_lookup_elem(&iface_stats_map, &key);
128b1b8bc3fSopenharmony_ci    }
129b1b8bc3fSopenharmony_ci
130b1b8bc3fSopenharmony_ci    if (value) {
131b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->rx_packets, 1);
132b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->rx_bytes, skb->len);
133b1b8bc3fSopenharmony_ci
134b1b8bc3fSopenharmony_ci        const char log[] = "[Iface ingress] ifindex = %d, value->rx_packets = %d, value->rx_bytes = %d";
135b1b8bc3fSopenharmony_ci        bpf_trace_printk(log, sizeof(log), key, value->rx_packets, value->rx_bytes);
136b1b8bc3fSopenharmony_ci    }
137b1b8bc3fSopenharmony_ci}
138b1b8bc3fSopenharmony_ci
139b1b8bc3fSopenharmony_cistatic SEC("socket/iface/egress") void bpf_socket_iface_egress(struct __sk_buff *skb)
140b1b8bc3fSopenharmony_ci{
141b1b8bc3fSopenharmony_ci    uint32_t key = skb->ifindex;
142b1b8bc3fSopenharmony_ci
143b1b8bc3fSopenharmony_ci    stats_value *value = bpf_map_lookup_elem(&iface_stats_map, &key);
144b1b8bc3fSopenharmony_ci    if (!value) {
145b1b8bc3fSopenharmony_ci        stats_value newValue = {};
146b1b8bc3fSopenharmony_ci        bpf_map_update_elem(&iface_stats_map, &key, &newValue, BPF_NOEXIST);
147b1b8bc3fSopenharmony_ci        value = bpf_map_lookup_elem(&iface_stats_map, &key);
148b1b8bc3fSopenharmony_ci    }
149b1b8bc3fSopenharmony_ci
150b1b8bc3fSopenharmony_ci    if (value) {
151b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->tx_packets, 1);
152b1b8bc3fSopenharmony_ci        __sync_fetch_and_add(&value->tx_bytes, skb->len);
153b1b8bc3fSopenharmony_ci
154b1b8bc3fSopenharmony_ci        const char log[] = "[Iface egress] ifindex = %d, value->tx_packets = %d, value->tx_bytes = %d";
155b1b8bc3fSopenharmony_ci        bpf_trace_printk(log, sizeof(log), key, value->tx_packets, value->tx_bytes);
156b1b8bc3fSopenharmony_ci    }
157b1b8bc3fSopenharmony_ci}
158b1b8bc3fSopenharmony_ci
159b1b8bc3fSopenharmony_cichar _license[] SEC("license") = "GPL";