| 1 |
|
| 2 | #ifndef _NET_FLOW_DISSECTOR_H
|
| 3 | #define _NET_FLOW_DISSECTOR_H
|
| 4 |
|
| 5 | #include <linux/types.h>
|
| 6 | #include <linux/in6.h>
|
| 7 | #include <linux/siphash.h>
|
| 8 | #include <linux/string.h>
|
| 9 | #include <uapi/linux/if_ether.h>
|
| 10 | #include <uapi/linux/pkt_cls.h>
|
| 11 |
|
| 12 | struct bpf_prog;
|
| 13 | struct net;
|
| 14 | struct sk_buff;
|
| 15 |
|
| 16 | |
| 17 | * struct flow_dissector_key_control:
|
| 18 | * @thoff: Transport header offset
|
| 19 | * @addr_type: Type of key. One of FLOW_DISSECTOR_KEY_*
|
| 20 | * @flags: Key flags.
|
| 21 | * Any of FLOW_DIS_(IS_FRAGMENT|FIRST_FRAG|ENCAPSULATION|F_*)
|
| 22 |
|
| 23 | struct flow_dissector_key_control {
|
| 24 | u16 thoff;
|
| 25 | u16 addr_type;
|
| 26 | u32 flags;
|
| 27 | };
|
| 28 |
|
| 29 | |
| 30 | * flags are exposed to userspace in some error paths, ie. unsupported flags.
|
| 31 |
|
| 32 | enum flow_dissector_ctrl_flags {
|
| 33 | FLOW_DIS_IS_FRAGMENT = TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT,
|
| 34 | FLOW_DIS_FIRST_FRAG = TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST,
|
| 35 | FLOW_DIS_F_TUNNEL_CSUM = TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM,
|
| 36 | FLOW_DIS_F_TUNNEL_DONT_FRAGMENT = TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT,
|
| 37 | FLOW_DIS_F_TUNNEL_OAM = TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM,
|
| 38 | FLOW_DIS_F_TUNNEL_CRIT_OPT = TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT,
|
| 39 |
|
| 40 |
|
| 41 | FLOW_DIS_ENCAPSULATION = (TCA_FLOWER_KEY_FLAGS_MAX << 1),
|
| 42 | };
|
| 43 |
|
| 44 | enum flow_dissect_ret {
|
| 45 | FLOW_DISSECT_RET_OUT_GOOD,
|
| 46 | FLOW_DISSECT_RET_OUT_BAD,
|
| 47 | FLOW_DISSECT_RET_PROTO_AGAIN,
|
| 48 | FLOW_DISSECT_RET_IPPROTO_AGAIN,
|
| 49 | FLOW_DISSECT_RET_CONTINUE,
|
| 50 | };
|
| 51 |
|
| 52 | |
| 53 | * struct flow_dissector_key_basic:
|
| 54 | * @n_proto: Network header protocol (eg. IPv4/IPv6)
|
| 55 | * @ip_proto: Transport header protocol (eg. TCP/UDP)
|
| 56 | * @padding: Unused
|
| 57 |
|
| 58 | struct flow_dissector_key_basic {
|
| 59 | __be16 n_proto;
|
| 60 | u8 ip_proto;
|
| 61 | u8 padding;
|
| 62 | };
|
| 63 |
|
| 64 | struct flow_dissector_key_tags {
|
| 65 | u32 flow_label;
|
| 66 | };
|
| 67 |
|
| 68 | struct flow_dissector_key_vlan {
|
| 69 | union {
|
| 70 | struct {
|
| 71 | u16 vlan_id:12,
|
| 72 | vlan_dei:1,
|
| 73 | vlan_priority:3;
|
| 74 | };
|
| 75 | __be16 vlan_tci;
|
| 76 | };
|
| 77 | __be16 vlan_tpid;
|
| 78 | __be16 vlan_eth_type;
|
| 79 | u16 padding;
|
| 80 | };
|
| 81 |
|
| 82 | struct flow_dissector_mpls_lse {
|
| 83 | u32 mpls_ttl:8,
|
| 84 | mpls_bos:1,
|
| 85 | mpls_tc:3,
|
| 86 | mpls_label:20;
|
| 87 | };
|
| 88 |
|
| 89 | #define FLOW_DIS_MPLS_MAX 7
|
| 90 | struct flow_dissector_key_mpls {
|
| 91 | struct flow_dissector_mpls_lse ls[FLOW_DIS_MPLS_MAX];
|
| 92 | u8 used_lses;
|
| 93 | };
|
| 94 |
|
| 95 | static inline void dissector_set_mpls_lse(struct flow_dissector_key_mpls *mpls,
|
| 96 | int lse_index)
|
| 97 | {
|
| 98 | mpls->used_lses |= 1 << lse_index;
|
| 99 | }
|
| 100 |
|
| 101 | #define FLOW_DIS_TUN_OPTS_MAX 255
|
| 102 | |
| 103 | * struct flow_dissector_key_enc_opts:
|
| 104 | * @data: tunnel option data
|
| 105 | * @len: length of tunnel option data
|
| 106 | * @dst_opt_type: tunnel option type
|
| 107 |
|
| 108 | struct flow_dissector_key_enc_opts {
|
| 109 | u8 data[FLOW_DIS_TUN_OPTS_MAX]; |
| 110 | * here but seems difficult to #include
|
| 111 |
|
| 112 | u8 len;
|
| 113 | u32 dst_opt_type;
|
| 114 | };
|
| 115 |
|
| 116 | struct flow_dissector_key_keyid {
|
| 117 | __be32 keyid;
|
| 118 | };
|
| 119 |
|
| 120 | |
| 121 | * struct flow_dissector_key_ipv4_addrs:
|
| 122 | * @src: source ip address
|
| 123 | * @dst: destination ip address
|
| 124 |
|
| 125 | struct flow_dissector_key_ipv4_addrs {
|
| 126 |
|
| 127 | __be32 src;
|
| 128 | __be32 dst;
|
| 129 | };
|
| 130 |
|
| 131 | |
| 132 | * struct flow_dissector_key_ipv6_addrs:
|
| 133 | * @src: source ip address
|
| 134 | * @dst: destination ip address
|
| 135 |
|
| 136 | struct flow_dissector_key_ipv6_addrs {
|
| 137 |
|
| 138 | struct in6_addr src;
|
| 139 | struct in6_addr dst;
|
| 140 | };
|
| 141 |
|
| 142 | |
| 143 | * struct flow_dissector_key_tipc:
|
| 144 | * @key: source node address combined with selector
|
| 145 |
|
| 146 | struct flow_dissector_key_tipc {
|
| 147 | __be32 key;
|
| 148 | };
|
| 149 |
|
| 150 | |
| 151 | * struct flow_dissector_key_addrs:
|
| 152 | * @v4addrs: IPv4 addresses
|
| 153 | * @v6addrs: IPv6 addresses
|
| 154 | * @tipckey: TIPC key
|
| 155 |
|
| 156 | struct flow_dissector_key_addrs {
|
| 157 | union {
|
| 158 | struct flow_dissector_key_ipv4_addrs v4addrs;
|
| 159 | struct flow_dissector_key_ipv6_addrs v6addrs;
|
| 160 | struct flow_dissector_key_tipc tipckey;
|
| 161 | };
|
| 162 | };
|
| 163 |
|
| 164 | |
| 165 | * struct flow_dissector_key_arp:
|
| 166 | * @sip: Sender IP address
|
| 167 | * @tip: Target IP address
|
| 168 | * @op: Operation
|
| 169 | * @sha: Sender hardware address
|
| 170 | * @tha: Target hardware address
|
| 171 |
|
| 172 | struct flow_dissector_key_arp {
|
| 173 | __u32 sip;
|
| 174 | __u32 tip;
|
| 175 | __u8 op;
|
| 176 | unsigned char sha[ETH_ALEN];
|
| 177 | unsigned char tha[ETH_ALEN];
|
| 178 | };
|
| 179 |
|
| 180 | |
| 181 | * struct flow_dissector_key_ports:
|
| 182 | * @ports: port numbers of Transport header
|
| 183 | * @src: source port number
|
| 184 | * @dst: destination port number
|
| 185 |
|
| 186 | struct flow_dissector_key_ports {
|
| 187 | union {
|
| 188 | __be32 ports;
|
| 189 | struct {
|
| 190 | __be16 src;
|
| 191 | __be16 dst;
|
| 192 | };
|
| 193 | };
|
| 194 | };
|
| 195 |
|
| 196 | |
| 197 | * struct flow_dissector_key_ports_range
|
| 198 | * @tp: port number from packet
|
| 199 | * @tp_min: min port number in range
|
| 200 | * @tp_max: max port number in range
|
| 201 |
|
| 202 | struct flow_dissector_key_ports_range {
|
| 203 | union {
|
| 204 | struct flow_dissector_key_ports tp;
|
| 205 | struct {
|
| 206 | struct flow_dissector_key_ports tp_min;
|
| 207 | struct flow_dissector_key_ports tp_max;
|
| 208 | };
|
| 209 | };
|
| 210 | };
|
| 211 |
|
| 212 | |
| 213 | * struct flow_dissector_key_icmp:
|
| 214 | * @type: ICMP type
|
| 215 | * @code: ICMP code
|
| 216 | * @id: Session identifier
|
| 217 |
|
| 218 | struct flow_dissector_key_icmp {
|
| 219 | struct {
|
| 220 | u8 type;
|
| 221 | u8 code;
|
| 222 | };
|
| 223 | u16 id;
|
| 224 | };
|
| 225 |
|
| 226 | |
| 227 | * struct flow_dissector_key_eth_addrs:
|
| 228 | * @src: source Ethernet address
|
| 229 | * @dst: destination Ethernet address
|
| 230 |
|
| 231 | struct flow_dissector_key_eth_addrs {
|
| 232 |
|
| 233 | unsigned char dst[ETH_ALEN];
|
| 234 | unsigned char src[ETH_ALEN];
|
| 235 | };
|
| 236 |
|
| 237 | |
| 238 | * struct flow_dissector_key_tcp:
|
| 239 | * @flags: flags
|
| 240 |
|
| 241 | struct flow_dissector_key_tcp {
|
| 242 | __be16 flags;
|
| 243 | };
|
| 244 |
|
| 245 | |
| 246 | * struct flow_dissector_key_ip:
|
| 247 | * @tos: tos
|
| 248 | * @ttl: ttl
|
| 249 |
|
| 250 | struct flow_dissector_key_ip {
|
| 251 | __u8 tos;
|
| 252 | __u8 ttl;
|
| 253 | };
|
| 254 |
|
| 255 | |
| 256 | * struct flow_dissector_key_meta:
|
| 257 | * @ingress_ifindex: ingress ifindex
|
| 258 | * @ingress_iftype: ingress interface type
|
| 259 | * @l2_miss: packet did not match an L2 entry during forwarding
|
| 260 |
|
| 261 | struct flow_dissector_key_meta {
|
| 262 | int ingress_ifindex;
|
| 263 | u16 ingress_iftype;
|
| 264 | u8 l2_miss;
|
| 265 | };
|
| 266 |
|
| 267 | |
| 268 | * struct flow_dissector_key_ct:
|
| 269 | * @ct_state: conntrack state after converting with map
|
| 270 | * @ct_mark: conttrack mark
|
| 271 | * @ct_zone: conntrack zone
|
| 272 | * @ct_labels: conntrack labels
|
| 273 |
|
| 274 | struct flow_dissector_key_ct {
|
| 275 | u16 ct_state;
|
| 276 | u16 ct_zone;
|
| 277 | u32 ct_mark;
|
| 278 | u32 ct_labels[4];
|
| 279 | };
|
| 280 |
|
| 281 | |
| 282 | * struct flow_dissector_key_hash:
|
| 283 | * @hash: hash value
|
| 284 |
|
| 285 | struct flow_dissector_key_hash {
|
| 286 | u32 hash;
|
| 287 | };
|
| 288 |
|
| 289 | |
| 290 | * struct flow_dissector_key_num_of_vlans:
|
| 291 | * @num_of_vlans: num_of_vlans value
|
| 292 |
|
| 293 | struct flow_dissector_key_num_of_vlans {
|
| 294 | u8 num_of_vlans;
|
| 295 | };
|
| 296 |
|
| 297 | |
| 298 | * struct flow_dissector_key_pppoe:
|
| 299 | * @session_id: pppoe session id
|
| 300 | * @ppp_proto: ppp protocol
|
| 301 | * @type: pppoe eth type
|
| 302 |
|
| 303 | struct flow_dissector_key_pppoe {
|
| 304 | __be16 session_id;
|
| 305 | __be16 ppp_proto;
|
| 306 | __be16 type;
|
| 307 | };
|
| 308 |
|
| 309 | |
| 310 | * struct flow_dissector_key_l2tpv3:
|
| 311 | * @session_id: identifier for a l2tp session
|
| 312 |
|
| 313 | struct flow_dissector_key_l2tpv3 {
|
| 314 | __be32 session_id;
|
| 315 | };
|
| 316 |
|
| 317 | |
| 318 | * struct flow_dissector_key_ipsec:
|
| 319 | * @spi: identifier for a ipsec connection
|
| 320 |
|
| 321 | struct flow_dissector_key_ipsec {
|
| 322 | __be32 spi;
|
| 323 | };
|
| 324 |
|
| 325 | |
| 326 | * struct flow_dissector_key_cfm
|
| 327 | * @mdl_ver: maintenance domain level (mdl) and cfm protocol version
|
| 328 | * @opcode: code specifying a type of cfm protocol packet
|
| 329 | *
|
| 330 | * See 802.1ag, ITU-T G.8013/Y.1731
|
| 331 | * 1 2
|
| 332 | * |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
|
| 333 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| 334 | * | mdl | version | opcode |
|
| 335 | * +-----+---------+-+-+-+-+-+-+-+-+
|
| 336 |
|
| 337 | struct flow_dissector_key_cfm {
|
| 338 | u8 mdl_ver;
|
| 339 | u8 opcode;
|
| 340 | };
|
| 341 |
|
| 342 | #define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)
|
| 343 | #define FLOW_DIS_CFM_MDL_MAX 7
|
| 344 |
|
| 345 | enum flow_dissector_key_id {
|
| 346 | FLOW_DISSECTOR_KEY_CONTROL,
|
| 347 | FLOW_DISSECTOR_KEY_BASIC,
|
| 348 | FLOW_DISSECTOR_KEY_IPV4_ADDRS,
|
| 349 | FLOW_DISSECTOR_KEY_IPV6_ADDRS,
|
| 350 | FLOW_DISSECTOR_KEY_PORTS,
|
| 351 | FLOW_DISSECTOR_KEY_PORTS_RANGE,
|
| 352 | FLOW_DISSECTOR_KEY_ICMP,
|
| 353 | FLOW_DISSECTOR_KEY_ETH_ADDRS,
|
| 354 | FLOW_DISSECTOR_KEY_TIPC,
|
| 355 | FLOW_DISSECTOR_KEY_ARP,
|
| 356 | FLOW_DISSECTOR_KEY_VLAN,
|
| 357 | FLOW_DISSECTOR_KEY_FLOW_LABEL,
|
| 358 | FLOW_DISSECTOR_KEY_GRE_KEYID,
|
| 359 | FLOW_DISSECTOR_KEY_MPLS_ENTROPY,
|
| 360 | FLOW_DISSECTOR_KEY_ENC_KEYID,
|
| 361 | FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
|
| 362 | FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
|
| 363 | FLOW_DISSECTOR_KEY_ENC_CONTROL,
|
| 364 | FLOW_DISSECTOR_KEY_ENC_PORTS,
|
| 365 | FLOW_DISSECTOR_KEY_MPLS,
|
| 366 | FLOW_DISSECTOR_KEY_TCP,
|
| 367 | FLOW_DISSECTOR_KEY_IP,
|
| 368 | FLOW_DISSECTOR_KEY_CVLAN,
|
| 369 | FLOW_DISSECTOR_KEY_ENC_IP,
|
| 370 | FLOW_DISSECTOR_KEY_ENC_OPTS,
|
| 371 | FLOW_DISSECTOR_KEY_META,
|
| 372 | FLOW_DISSECTOR_KEY_CT,
|
| 373 | FLOW_DISSECTOR_KEY_HASH,
|
| 374 | FLOW_DISSECTOR_KEY_NUM_OF_VLANS,
|
| 375 | FLOW_DISSECTOR_KEY_PPPOE,
|
| 376 | FLOW_DISSECTOR_KEY_L2TPV3,
|
| 377 | FLOW_DISSECTOR_KEY_CFM,
|
| 378 | FLOW_DISSECTOR_KEY_IPSEC,
|
| 379 |
|
| 380 | FLOW_DISSECTOR_KEY_MAX,
|
| 381 | };
|
| 382 |
|
| 383 | #define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
|
| 384 | #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)
|
| 385 | #define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)
|
| 386 | #define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP BIT(3)
|
| 387 |
|
| 388 | struct flow_dissector_key {
|
| 389 | enum flow_dissector_key_id key_id;
|
| 390 | size_t offset; |
| 391 | in target the struct
|
| 392 | };
|
| 393 |
|
| 394 | struct flow_dissector {
|
| 395 | unsigned long long used_keys;
|
| 396 |
|
| 397 | unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
|
| 398 | };
|
| 399 |
|
| 400 | struct flow_keys_basic {
|
| 401 | struct flow_dissector_key_control control;
|
| 402 | struct flow_dissector_key_basic basic;
|
| 403 | };
|
| 404 |
|
| 405 | struct flow_keys {
|
| 406 | struct flow_dissector_key_control control;
|
| 407 | #define FLOW_KEYS_HASH_START_FIELD basic
|
| 408 | struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
|
| 409 | struct flow_dissector_key_tags tags;
|
| 410 | struct flow_dissector_key_vlan vlan;
|
| 411 | struct flow_dissector_key_vlan cvlan;
|
| 412 | struct flow_dissector_key_keyid keyid;
|
| 413 | struct flow_dissector_key_ports ports;
|
| 414 | struct flow_dissector_key_icmp icmp;
|
| 415 |
|
| 416 | struct flow_dissector_key_addrs addrs;
|
| 417 | };
|
| 418 |
|
| 419 | #define FLOW_KEYS_HASH_OFFSET \
|
| 420 | offsetof(struct flow_keys, FLOW_KEYS_HASH_START_FIELD)
|
| 421 |
|
| 422 | __be32 flow_get_u32_src(const struct flow_keys *flow);
|
| 423 | __be32 flow_get_u32_dst(const struct flow_keys *flow);
|
| 424 |
|
| 425 | extern struct flow_dissector flow_keys_dissector;
|
| 426 | extern struct flow_dissector flow_keys_basic_dissector;
|
| 427 |
|
| 428 | |
| 429 | *
|
| 430 | * This structure is used to hold a digest of the full flow keys. This is a
|
| 431 | * larger "hash" of a flow to allow definitively matching specific flows where
|
| 432 | * the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
|
| 433 | * that it can be used in CB of skb (see sch_choke for an example).
|
| 434 |
|
| 435 | #define FLOW_KEYS_DIGEST_LEN 16
|
| 436 | struct flow_keys_digest {
|
| 437 | u8 data[FLOW_KEYS_DIGEST_LEN];
|
| 438 | };
|
| 439 |
|
| 440 | void make_flow_keys_digest(struct flow_keys_digest *digest,
|
| 441 | const struct flow_keys *flow);
|
| 442 |
|
| 443 | static inline bool flow_keys_have_l4(const struct flow_keys *keys)
|
| 444 | {
|
| 445 | return (keys->ports.ports || keys->tags.flow_label);
|
| 446 | }
|
| 447 |
|
| 448 | u32 flow_hash_from_keys(struct flow_keys *keys);
|
| 449 | u32 flow_hash_from_keys_seed(struct flow_keys *keys,
|
| 450 | const siphash_key_t *keyval);
|
| 451 | void skb_flow_get_icmp_tci(const struct sk_buff *skb,
|
| 452 | struct flow_dissector_key_icmp *key_icmp,
|
| 453 | const void *data, int thoff, int hlen);
|
| 454 |
|
| 455 | static inline bool dissector_uses_key(const struct flow_dissector *flow_dissector,
|
| 456 | enum flow_dissector_key_id key_id)
|
| 457 | {
|
| 458 | return flow_dissector->used_keys & (1ULL << key_id);
|
| 459 | }
|
| 460 |
|
| 461 | static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissector,
|
| 462 | enum flow_dissector_key_id key_id,
|
| 463 | void *target_container)
|
| 464 | {
|
| 465 | return ((char *)target_container) + flow_dissector->offset[key_id];
|
| 466 | }
|
| 467 |
|
| 468 | struct bpf_flow_dissector {
|
| 469 | struct bpf_flow_keys *flow_keys;
|
| 470 | const struct sk_buff *skb;
|
| 471 | const void *data;
|
| 472 | const void *data_end;
|
| 473 | };
|
| 474 |
|
| 475 | static inline void
|
| 476 | flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
|
| 477 | struct flow_dissector_key_basic *key_basic)
|
| 478 | {
|
| 479 | memset(key_control, 0, sizeof(*key_control));
|
| 480 | memset(key_basic, 0, sizeof(*key_basic));
|
| 481 | }
|
| 482 |
|
| 483 | #ifdef CONFIG_BPF_SYSCALL
|
| 484 | int flow_dissector_bpf_prog_attach_check(struct net *net,
|
| 485 | struct bpf_prog *prog);
|
| 486 | #endif
|
| 487 |
|
| 488 | #endif
|