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