Blame view
samples/bpf/sockex2_kern.c
4.72 KB
fbe331084 samples: bpf: lar... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <uapi/linux/bpf.h> #include "bpf_helpers.h" #include <uapi/linux/in.h> #include <uapi/linux/if.h> #include <uapi/linux/if_ether.h> #include <uapi/linux/ip.h> #include <uapi/linux/ipv6.h> #include <uapi/linux/if_tunnel.h> #define IP_MF 0x2000 #define IP_OFFSET 0x1FFF struct vlan_hdr { __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; |
2b064fff8 bpf samples: fix ... |
16 |
struct bpf_flow_keys { |
fbe331084 samples: bpf: lar... |
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
__be32 src; __be32 dst; union { __be32 ports; __be16 port16[2]; }; __u16 thoff; __u8 ip_proto; }; static inline int proto_ports_offset(__u64 proto) { switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_DCCP: case IPPROTO_ESP: case IPPROTO_SCTP: case IPPROTO_UDPLITE: return 0; case IPPROTO_AH: return 4; default: return 0; } } |
614cd3bd3 samples: bpf: add... |
43 |
static inline int ip_is_fragment(struct __sk_buff *ctx, __u64 nhoff) |
fbe331084 samples: bpf: lar... |
44 45 46 47 |
{ return load_half(ctx, nhoff + offsetof(struct iphdr, frag_off)) & (IP_MF | IP_OFFSET); } |
614cd3bd3 samples: bpf: add... |
48 |
static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off) |
fbe331084 samples: bpf: lar... |
49 50 51 52 53 54 55 56 |
{ __u64 w0 = load_word(ctx, off); __u64 w1 = load_word(ctx, off + 4); __u64 w2 = load_word(ctx, off + 8); __u64 w3 = load_word(ctx, off + 12); return (__u32)(w0 ^ w1 ^ w2 ^ w3); } |
614cd3bd3 samples: bpf: add... |
57 |
static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto, |
2b064fff8 bpf samples: fix ... |
58 |
struct bpf_flow_keys *flow) |
fbe331084 samples: bpf: lar... |
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
{ __u64 verlen; if (unlikely(ip_is_fragment(skb, nhoff))) *ip_proto = 0; else *ip_proto = load_byte(skb, nhoff + offsetof(struct iphdr, protocol)); if (*ip_proto != IPPROTO_GRE) { flow->src = load_word(skb, nhoff + offsetof(struct iphdr, saddr)); flow->dst = load_word(skb, nhoff + offsetof(struct iphdr, daddr)); } verlen = load_byte(skb, nhoff + 0/*offsetof(struct iphdr, ihl)*/); if (likely(verlen == 0x45)) nhoff += 20; else nhoff += (verlen & 0xF) << 2; return nhoff; } |
614cd3bd3 samples: bpf: add... |
80 |
static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto, |
2b064fff8 bpf samples: fix ... |
81 |
struct bpf_flow_keys *flow) |
fbe331084 samples: bpf: lar... |
82 83 84 85 86 87 88 89 90 91 92 |
{ *ip_proto = load_byte(skb, nhoff + offsetof(struct ipv6hdr, nexthdr)); flow->src = ipv6_addr_hash(skb, nhoff + offsetof(struct ipv6hdr, saddr)); flow->dst = ipv6_addr_hash(skb, nhoff + offsetof(struct ipv6hdr, daddr)); nhoff += sizeof(struct ipv6hdr); return nhoff; } |
2b064fff8 bpf samples: fix ... |
93 |
static inline bool flow_dissector(struct __sk_buff *skb, struct bpf_flow_keys *flow) |
fbe331084 samples: bpf: lar... |
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
{ __u64 nhoff = ETH_HLEN; __u64 ip_proto; __u64 proto = load_half(skb, 12); int poff; if (proto == ETH_P_8021AD) { proto = load_half(skb, nhoff + offsetof(struct vlan_hdr, h_vlan_encapsulated_proto)); nhoff += sizeof(struct vlan_hdr); } if (proto == ETH_P_8021Q) { proto = load_half(skb, nhoff + offsetof(struct vlan_hdr, h_vlan_encapsulated_proto)); nhoff += sizeof(struct vlan_hdr); } if (likely(proto == ETH_P_IP)) nhoff = parse_ip(skb, nhoff, &ip_proto, flow); else if (proto == ETH_P_IPV6) nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow); else return false; switch (ip_proto) { case IPPROTO_GRE: { struct gre_hdr { __be16 flags; __be16 proto; }; __u64 gre_flags = load_half(skb, nhoff + offsetof(struct gre_hdr, flags)); __u64 gre_proto = load_half(skb, nhoff + offsetof(struct gre_hdr, proto)); if (gre_flags & (GRE_VERSION|GRE_ROUTING)) break; proto = gre_proto; nhoff += 4; if (gre_flags & GRE_CSUM) nhoff += 4; if (gre_flags & GRE_KEY) nhoff += 4; if (gre_flags & GRE_SEQ) nhoff += 4; if (proto == ETH_P_8021Q) { proto = load_half(skb, nhoff + offsetof(struct vlan_hdr, h_vlan_encapsulated_proto)); nhoff += sizeof(struct vlan_hdr); } if (proto == ETH_P_IP) nhoff = parse_ip(skb, nhoff, &ip_proto, flow); else if (proto == ETH_P_IPV6) nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow); else return false; break; } case IPPROTO_IPIP: nhoff = parse_ip(skb, nhoff, &ip_proto, flow); break; case IPPROTO_IPV6: nhoff = parse_ipv6(skb, nhoff, &ip_proto, flow); break; default: break; } flow->ip_proto = ip_proto; poff = proto_ports_offset(ip_proto); if (poff >= 0) { nhoff += poff; flow->ports = load_word(skb, nhoff); } flow->thoff = (__u16) nhoff; return true; } |
614cd3bd3 samples: bpf: add... |
179 180 181 182 |
struct pair { long packets; long bytes; }; |
fbe331084 samples: bpf: lar... |
183 184 185 |
struct bpf_map_def SEC("maps") hash_map = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(__be32), |
614cd3bd3 samples: bpf: add... |
186 |
.value_size = sizeof(struct pair), |
fbe331084 samples: bpf: lar... |
187 188 189 190 |
.max_entries = 1024, }; SEC("socket2") |
614cd3bd3 samples: bpf: add... |
191 |
int bpf_prog2(struct __sk_buff *skb) |
fbe331084 samples: bpf: lar... |
192 |
{ |
2b064fff8 bpf samples: fix ... |
193 |
struct bpf_flow_keys flow; |
614cd3bd3 samples: bpf: add... |
194 |
struct pair *value; |
fbe331084 samples: bpf: lar... |
195 196 197 198 199 200 201 202 |
u32 key; if (!flow_dissector(skb, &flow)) return 0; key = flow.dst; value = bpf_map_lookup_elem(&hash_map, &key); if (value) { |
614cd3bd3 samples: bpf: add... |
203 204 |
__sync_fetch_and_add(&value->packets, 1); __sync_fetch_and_add(&value->bytes, skb->len); |
fbe331084 samples: bpf: lar... |
205 |
} else { |
614cd3bd3 samples: bpf: add... |
206 |
struct pair val = {1, skb->len}; |
fbe331084 samples: bpf: lar... |
207 208 209 210 211 212 213 |
bpf_map_update_elem(&hash_map, &key, &val, BPF_ANY); } return 0; } char _license[] SEC("license") = "GPL"; |