blob: ffd386ea0dbb3ea96d2d484bb25bf47cd7a70aa3 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Jiri Pirko1bd758e2015-05-12 14:56:07 +02002#ifndef _NET_FLOW_DISSECTOR_H
3#define _NET_FLOW_DISSECTOR_H
Eric Dumazet0744dd02011-11-28 05:22:18 +00004
Jiri Pirkoc3f8eae2015-05-12 14:56:17 +02005#include <linux/types.h>
Jiri Pirkob9249332015-05-12 14:56:18 +02006#include <linux/in6.h>
Eric Dumazet55667442019-10-22 07:57:46 -07007#include <linux/siphash.h>
Jason Baron8a9093c2020-02-17 15:38:09 -05008#include <linux/string.h>
Jiri Pirko67a900c2015-05-12 14:56:19 +02009#include <uapi/linux/if_ether.h>
Jiri Pirkoc3f8eae2015-05-12 14:56:17 +020010
Jakub Sitnickib27f7bb2020-05-31 10:28:37 +020011struct bpf_prog;
12struct net;
Matteo Croce5dec5972019-10-29 14:50:52 +010013struct sk_buff;
14
Jiri Pirkofbff9492015-05-12 14:56:15 +020015/**
Tom Herbert42aecaa2015-06-04 09:16:39 -070016 * struct flow_dissector_key_control:
17 * @thoff: Transport header offset
18 */
19struct flow_dissector_key_control {
20 u16 thoff;
Tom Herbertc3f83242015-06-04 09:16:40 -070021 u16 addr_type;
David S. Miller4b369932015-09-01 16:46:08 -070022 u32 flags;
Tom Herbert42aecaa2015-06-04 09:16:39 -070023};
24
David S. Miller4b369932015-09-01 16:46:08 -070025#define FLOW_DIS_IS_FRAGMENT BIT(0)
26#define FLOW_DIS_FIRST_FRAG BIT(1)
27#define FLOW_DIS_ENCAPSULATION BIT(2)
28
Tom Herbert3a1214e2017-09-01 14:04:11 -070029enum flow_dissect_ret {
30 FLOW_DISSECT_RET_OUT_GOOD,
31 FLOW_DISSECT_RET_OUT_BAD,
32 FLOW_DISSECT_RET_PROTO_AGAIN,
33 FLOW_DISSECT_RET_IPPROTO_AGAIN,
34 FLOW_DISSECT_RET_CONTINUE,
35};
36
Tom Herbert42aecaa2015-06-04 09:16:39 -070037/**
Jiri Pirkofbff9492015-05-12 14:56:15 +020038 * struct flow_dissector_key_basic:
Jiri Pirkofbff9492015-05-12 14:56:15 +020039 * @n_proto: Network header protocol (eg. IPv4/IPv6)
40 * @ip_proto: Transport header protocol (eg. TCP/UDP)
41 */
42struct flow_dissector_key_basic {
Jiri Pirkofbff9492015-05-12 14:56:15 +020043 __be16 n_proto;
44 u8 ip_proto;
Tom Herbert42aecaa2015-06-04 09:16:39 -070045 u8 padding;
Jiri Pirkofbff9492015-05-12 14:56:15 +020046};
47
Tom Herbertd34af822015-06-04 09:16:43 -070048struct flow_dissector_key_tags {
Hadar Hen Zionf6a66922016-08-17 13:36:11 +030049 u32 flow_label;
50};
51
52struct flow_dissector_key_vlan {
Pablo Neira Ayusoa82055a2019-11-19 23:05:54 +010053 union {
Petr Machatad1746d12019-11-22 15:47:21 +000054 struct {
55 u16 vlan_id:12,
56 vlan_dei:1,
57 vlan_priority:3;
58 };
Pablo Neira Ayusoa82055a2019-11-19 23:05:54 +010059 __be16 vlan_tci;
60 };
Jianbo Liu2064c3d2018-07-06 05:38:12 +000061 __be16 vlan_tpid;
Tom Herbertd34af822015-06-04 09:16:43 -070062};
63
Guillaume Nault58cff782020-05-26 14:29:00 +020064struct flow_dissector_mpls_lse {
Benjamin LaHaise029c1ec2017-04-22 16:52:46 -040065 u32 mpls_ttl:8,
66 mpls_bos:1,
67 mpls_tc:3,
68 mpls_label:20;
69};
70
Guillaume Nault58cff782020-05-26 14:29:00 +020071#define FLOW_DIS_MPLS_MAX 7
72struct flow_dissector_key_mpls {
73 struct flow_dissector_mpls_lse ls[FLOW_DIS_MPLS_MAX]; /* Label Stack */
74 u8 used_lses; /* One bit set for each Label Stack Entry in use */
75};
76
77static inline void dissector_set_mpls_lse(struct flow_dissector_key_mpls *mpls,
78 int lse_index)
79{
80 mpls->used_lses |= 1 << lse_index;
81}
82
Simon Horman92e2c402018-08-07 17:36:00 +020083#define FLOW_DIS_TUN_OPTS_MAX 255
84/**
85 * struct flow_dissector_key_enc_opts:
86 * @data: tunnel option data
87 * @len: length of tunnel option data
88 * @dst_opt_type: tunnel option type
89 */
90struct flow_dissector_key_enc_opts {
91 u8 data[FLOW_DIS_TUN_OPTS_MAX]; /* Using IP_TUNNEL_OPTS_MAX is desired
92 * here but seems difficult to #include
93 */
94 u8 len;
95 __be16 dst_opt_type;
96};
97
Tom Herbert1fdd5122015-06-04 09:16:45 -070098struct flow_dissector_key_keyid {
99 __be32 keyid;
100};
101
Jiri Pirkofbff9492015-05-12 14:56:15 +0200102/**
Tom Herbertc3f83242015-06-04 09:16:40 -0700103 * struct flow_dissector_key_ipv4_addrs:
104 * @src: source ip address
105 * @dst: destination ip address
Jiri Pirkofbff9492015-05-12 14:56:15 +0200106 */
Tom Herbertc3f83242015-06-04 09:16:40 -0700107struct flow_dissector_key_ipv4_addrs {
Jiri Pirkofbff9492015-05-12 14:56:15 +0200108 /* (src,dst) must be grouped, in the same way than in IP header */
109 __be32 src;
110 __be32 dst;
111};
112
113/**
Tom Herbertc3f83242015-06-04 09:16:40 -0700114 * struct flow_dissector_key_ipv6_addrs:
115 * @src: source ip address
116 * @dst: destination ip address
117 */
118struct flow_dissector_key_ipv6_addrs {
119 /* (src,dst) must be grouped, in the same way than in IP header */
120 struct in6_addr src;
121 struct in6_addr dst;
122};
123
124/**
Jon Maloy8d6e79d2017-11-08 09:59:26 +0100125 * struct flow_dissector_key_tipc:
126 * @key: source node address combined with selector
Tom Herbert9f249082015-06-04 09:16:41 -0700127 */
Jon Maloy8d6e79d2017-11-08 09:59:26 +0100128struct flow_dissector_key_tipc {
129 __be32 key;
Tom Herbert9f249082015-06-04 09:16:41 -0700130};
131
132/**
Tom Herbertc3f83242015-06-04 09:16:40 -0700133 * struct flow_dissector_key_addrs:
134 * @v4addrs: IPv4 addresses
135 * @v6addrs: IPv6 addresses
136 */
137struct flow_dissector_key_addrs {
138 union {
139 struct flow_dissector_key_ipv4_addrs v4addrs;
140 struct flow_dissector_key_ipv6_addrs v6addrs;
Jon Maloy8d6e79d2017-11-08 09:59:26 +0100141 struct flow_dissector_key_tipc tipckey;
Tom Herbertc3f83242015-06-04 09:16:40 -0700142 };
143};
144
145/**
Simon Horman55733352017-01-11 14:05:42 +0100146 * flow_dissector_key_arp:
147 * @ports: Operation, source and target addresses for an ARP header
148 * for Ethernet hardware addresses and IPv4 protocol addresses
149 * sip: Sender IP address
150 * tip: Target IP address
151 * op: Operation
152 * sha: Sender hardware address
153 * tpa: Target hardware address
154 */
155struct flow_dissector_key_arp {
156 __u32 sip;
157 __u32 tip;
158 __u8 op;
159 unsigned char sha[ETH_ALEN];
160 unsigned char tha[ETH_ALEN];
161};
162
163/**
Jiri Pirkofbff9492015-05-12 14:56:15 +0200164 * flow_dissector_key_tp_ports:
165 * @ports: port numbers of Transport header
Jiri Pirko59346af2015-05-12 14:56:20 +0200166 * src: source port number
167 * dst: destination port number
Jiri Pirkofbff9492015-05-12 14:56:15 +0200168 */
169struct flow_dissector_key_ports {
170 union {
171 __be32 ports;
Jiri Pirko59346af2015-05-12 14:56:20 +0200172 struct {
173 __be16 src;
174 __be16 dst;
175 };
Jiri Pirkofbff9492015-05-12 14:56:15 +0200176 };
177};
178
Simon Horman972d3872016-12-07 13:48:27 +0100179/**
180 * flow_dissector_key_icmp:
Simon Horman972d3872016-12-07 13:48:27 +0100181 * type: ICMP type
182 * code: ICMP code
Matteo Croce5dec5972019-10-29 14:50:52 +0100183 * id: session identifier
Simon Horman972d3872016-12-07 13:48:27 +0100184 */
185struct flow_dissector_key_icmp {
Matteo Croce5dec5972019-10-29 14:50:52 +0100186 struct {
187 u8 type;
188 u8 code;
Simon Horman972d3872016-12-07 13:48:27 +0100189 };
Matteo Croce5dec5972019-10-29 14:50:52 +0100190 u16 id;
Simon Horman972d3872016-12-07 13:48:27 +0100191};
Jiri Pirkob9249332015-05-12 14:56:18 +0200192
Jiri Pirko67a900c2015-05-12 14:56:19 +0200193/**
194 * struct flow_dissector_key_eth_addrs:
195 * @src: source Ethernet address
196 * @dst: destination Ethernet address
197 */
198struct flow_dissector_key_eth_addrs {
199 /* (dst,src) must be grouped, in the same way than in ETH header */
200 unsigned char dst[ETH_ALEN];
201 unsigned char src[ETH_ALEN];
202};
203
Jiri Pirkoac4bb5d2017-05-23 18:40:44 +0200204/**
205 * struct flow_dissector_key_tcp:
206 * @flags: flags
207 */
208struct flow_dissector_key_tcp {
209 __be16 flags;
210};
211
Or Gerlitz518d8a22017-06-01 21:37:37 +0300212/**
213 * struct flow_dissector_key_ip:
214 * @tos: tos
215 * @ttl: ttl
216 */
217struct flow_dissector_key_ip {
218 __u8 tos;
219 __u8 ttl;
220};
221
Jiri Pirko82828b82019-06-19 09:41:02 +0300222/**
223 * struct flow_dissector_key_meta:
224 * @ingress_ifindex: ingress ifindex
Pablo Neira Ayuso8819efc2019-11-19 23:05:53 +0100225 * @ingress_iftype: ingress interface type
Jiri Pirko82828b82019-06-19 09:41:02 +0300226 */
227struct flow_dissector_key_meta {
228 int ingress_ifindex;
Pablo Neira Ayuso8819efc2019-11-19 23:05:53 +0100229 u16 ingress_iftype;
Jiri Pirko82828b82019-06-19 09:41:02 +0300230};
231
Paul Blakey75a56752019-07-09 10:30:49 +0300232/**
233 * struct flow_dissector_key_ct:
234 * @ct_state: conntrack state after converting with map
235 * @ct_mark: conttrack mark
236 * @ct_zone: conntrack zone
237 * @ct_labels: conntrack labels
238 */
239struct flow_dissector_key_ct {
240 u16 ct_state;
241 u16 ct_zone;
242 u32 ct_mark;
243 u32 ct_labels[4];
244};
245
Ariel Levkovich0cb09af2020-07-23 01:03:00 +0300246/**
247 * struct flow_dissector_key_hash:
248 * @hash: hash value
249 */
250struct flow_dissector_key_hash {
251 u32 hash;
252};
253
Jiri Pirkofbff9492015-05-12 14:56:15 +0200254enum flow_dissector_key_id {
Tom Herbert42aecaa2015-06-04 09:16:39 -0700255 FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
Jiri Pirkofbff9492015-05-12 14:56:15 +0200256 FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
Tom Herbertc3f83242015-06-04 09:16:40 -0700257 FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
258 FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
Jiri Pirkofbff9492015-05-12 14:56:15 +0200259 FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
Yoshiki Komachi8ffb0552019-12-03 19:40:12 +0900260 FLOW_DISSECTOR_KEY_PORTS_RANGE, /* struct flow_dissector_key_ports */
Simon Horman972d3872016-12-07 13:48:27 +0100261 FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
Jiri Pirko67a900c2015-05-12 14:56:19 +0200262 FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
Jon Maloy8d6e79d2017-11-08 09:59:26 +0100263 FLOW_DISSECTOR_KEY_TIPC, /* struct flow_dissector_key_tipc */
Simon Horman55733352017-01-11 14:05:42 +0100264 FLOW_DISSECTOR_KEY_ARP, /* struct flow_dissector_key_arp */
Edward Cree91c45952018-11-27 15:40:59 +0000265 FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_vlan */
266 FLOW_DISSECTOR_KEY_FLOW_LABEL, /* struct flow_dissector_key_tags */
Tom Herbert1fdd5122015-06-04 09:16:45 -0700267 FLOW_DISSECTOR_KEY_GRE_KEYID, /* struct flow_dissector_key_keyid */
Tom Herbertb3baa0f2015-06-04 09:16:46 -0700268 FLOW_DISSECTOR_KEY_MPLS_ENTROPY, /* struct flow_dissector_key_keyid */
Hadar Hen Zion9ba6a9a2016-11-07 15:14:37 +0200269 FLOW_DISSECTOR_KEY_ENC_KEYID, /* struct flow_dissector_key_keyid */
270 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
271 FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
272 FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */
Hadar Hen Zionf4d997f2016-11-07 15:14:39 +0200273 FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
Benjamin LaHaise029c1ec2017-04-22 16:52:46 -0400274 FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */
Jiri Pirkoac4bb5d2017-05-23 18:40:44 +0200275 FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */
Or Gerlitz518d8a22017-06-01 21:37:37 +0300276 FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */
Edward Cree91c45952018-11-27 15:40:59 +0000277 FLOW_DISSECTOR_KEY_CVLAN, /* struct flow_dissector_key_vlan */
Or Gerlitz5544adb2018-07-17 19:27:17 +0300278 FLOW_DISSECTOR_KEY_ENC_IP, /* struct flow_dissector_key_ip */
Simon Horman92e2c402018-08-07 17:36:00 +0200279 FLOW_DISSECTOR_KEY_ENC_OPTS, /* struct flow_dissector_key_enc_opts */
Jiri Pirko82828b82019-06-19 09:41:02 +0300280 FLOW_DISSECTOR_KEY_META, /* struct flow_dissector_key_meta */
Paul Blakey75a56752019-07-09 10:30:49 +0300281 FLOW_DISSECTOR_KEY_CT, /* struct flow_dissector_key_ct */
Ariel Levkovich0cb09af2020-07-23 01:03:00 +0300282 FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */
Simon Horman92e2c402018-08-07 17:36:00 +0200283
Jiri Pirkofbff9492015-05-12 14:56:15 +0200284 FLOW_DISSECTOR_KEY_MAX,
285};
286
Tom Herbert807e1652015-09-01 09:24:28 -0700287#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
Stanislav Fomichev1cc26452019-05-31 14:05:06 -0700288#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)
289#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)
Tom Herbert807e1652015-09-01 09:24:28 -0700290
Jiri Pirkofbff9492015-05-12 14:56:15 +0200291struct flow_dissector_key {
292 enum flow_dissector_key_id key_id;
293 size_t offset; /* offset of struct flow_dissector_key_*
294 in target the struct */
295};
296
297struct flow_dissector {
298 unsigned int used_keys; /* each bit repesents presence of one key id */
299 unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
300};
301
Paolo Abeni72a338b2018-05-04 11:32:59 +0200302struct flow_keys_basic {
303 struct flow_dissector_key_control control;
304 struct flow_dissector_key_basic basic;
305};
306
Jiri Pirko06635a32015-05-12 14:56:16 +0200307struct flow_keys {
Tom Herbert42aecaa2015-06-04 09:16:39 -0700308 struct flow_dissector_key_control control;
309#define FLOW_KEYS_HASH_START_FIELD basic
Eric Dumazet55667442019-10-22 07:57:46 -0700310 struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
Tom Herbertd34af822015-06-04 09:16:43 -0700311 struct flow_dissector_key_tags tags;
Hadar Hen Zionf6a66922016-08-17 13:36:11 +0300312 struct flow_dissector_key_vlan vlan;
Jianbo Liu24c590e2018-07-06 05:38:14 +0000313 struct flow_dissector_key_vlan cvlan;
Tom Herbert1fdd5122015-06-04 09:16:45 -0700314 struct flow_dissector_key_keyid keyid;
Tom Herbert42aecaa2015-06-04 09:16:39 -0700315 struct flow_dissector_key_ports ports;
Matteo Croce5dec5972019-10-29 14:50:52 +0100316 struct flow_dissector_key_icmp icmp;
Matteo Croce98298e62019-10-29 14:50:50 +0100317 /* 'addrs' must be the last member */
Tom Herbert42aecaa2015-06-04 09:16:39 -0700318 struct flow_dissector_key_addrs addrs;
Jiri Pirko06635a32015-05-12 14:56:16 +0200319};
320
Tom Herbert42aecaa2015-06-04 09:16:39 -0700321#define FLOW_KEYS_HASH_OFFSET \
322 offsetof(struct flow_keys, FLOW_KEYS_HASH_START_FIELD)
323
Tom Herbertc3f83242015-06-04 09:16:40 -0700324__be32 flow_get_u32_src(const struct flow_keys *flow);
325__be32 flow_get_u32_dst(const struct flow_keys *flow);
326
Jiri Pirko06635a32015-05-12 14:56:16 +0200327extern struct flow_dissector flow_keys_dissector;
Paolo Abeni72a338b2018-05-04 11:32:59 +0200328extern struct flow_dissector flow_keys_basic_dissector;
Jiri Pirko06635a32015-05-12 14:56:16 +0200329
Tom Herbert2f59e1e2015-05-01 11:30:17 -0700330/* struct flow_keys_digest:
331 *
332 * This structure is used to hold a digest of the full flow keys. This is a
333 * larger "hash" of a flow to allow definitively matching specific flows where
334 * the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
Wolfram Sang53bc0172018-05-06 13:23:52 +0200335 * that it can be used in CB of skb (see sch_choke for an example).
Tom Herbert2f59e1e2015-05-01 11:30:17 -0700336 */
337#define FLOW_KEYS_DIGEST_LEN 16
338struct flow_keys_digest {
339 u8 data[FLOW_KEYS_DIGEST_LEN];
340};
341
342void make_flow_keys_digest(struct flow_keys_digest *digest,
343 const struct flow_keys *flow);
344
Gao Feng66fdd052016-08-31 11:16:22 +0800345static inline bool flow_keys_have_l4(const struct flow_keys *keys)
Tom Herbertbcc83832015-09-01 09:24:24 -0700346{
347 return (keys->ports.ports || keys->tags.flow_label);
348}
349
Tom Herbertc6cc1ca2015-09-01 09:24:25 -0700350u32 flow_hash_from_keys(struct flow_keys *keys);
Matteo Croce5dec5972019-10-29 14:50:52 +0100351void skb_flow_get_icmp_tci(const struct sk_buff *skb,
352 struct flow_dissector_key_icmp *key_icmp,
Alexander Lobakinf96533c2021-03-14 11:11:23 +0000353 const void *data, int thoff, int hlen);
Tom Herbertc6cc1ca2015-09-01 09:24:25 -0700354
Amir Vadai8de2d792016-03-08 12:42:30 +0200355static inline bool dissector_uses_key(const struct flow_dissector *flow_dissector,
356 enum flow_dissector_key_id key_id)
357{
358 return flow_dissector->used_keys & (1 << key_id);
359}
360
361static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissector,
362 enum flow_dissector_key_id key_id,
363 void *target_container)
364{
365 return ((char *)target_container) + flow_dissector->offset[key_id];
366}
367
Stanislav Fomichev089b19a2019-04-22 08:55:44 -0700368struct bpf_flow_dissector {
369 struct bpf_flow_keys *flow_keys;
370 const struct sk_buff *skb;
Alexander Lobakindac06b32021-03-14 11:11:00 +0000371 const void *data;
372 const void *data_end;
Stanislav Fomichev089b19a2019-04-22 08:55:44 -0700373};
374
Jason Baron8a9093c2020-02-17 15:38:09 -0500375static inline void
376flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
377 struct flow_dissector_key_basic *key_basic)
378{
379 memset(key_control, 0, sizeof(*key_control));
380 memset(key_basic, 0, sizeof(*key_basic));
381}
382
Jakub Sitnickib27f7bb2020-05-31 10:28:37 +0200383#ifdef CONFIG_BPF_SYSCALL
Jakub Sitnicki3b701692020-06-25 16:13:54 +0200384int flow_dissector_bpf_prog_attach_check(struct net *net,
385 struct bpf_prog *prog);
Jakub Sitnickib27f7bb2020-05-31 10:28:37 +0200386#endif /* CONFIG_BPF_SYSCALL */
387
Eric Dumazet0744dd02011-11-28 05:22:18 +0000388#endif