Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

filter: introduce SKF_AD_VLAN_TPID BPF extension

If vlan offloading takes place then vlan header is removed from frame
and its contents, both vlan_tci and vlan_proto, is available to user
space via TPACKET interface. However, only vlan_tci can be used in BPF
filters.

This commit introduces a new BPF extension. It makes possible to load
the value of vlan_proto (vlan TPID) to register A. Support for classic
BPF and eBPF is being added, analogous to skb->protocol.

Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Jiri Pirko <jpirko@redhat.com>

Signed-off-by: Michal Sekletar <msekleta@redhat.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Reviewed-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Michal Sekletar and committed by
David S. Miller
27cd5452 f6bb76cd

+35 -3
+2 -1
Documentation/networking/filter.txt
··· 280 280 rxhash skb->hash 281 281 cpu raw_smp_processor_id() 282 282 vlan_tci skb_vlan_tag_get(skb) 283 - vlan_pr skb_vlan_tag_present(skb) 283 + vlan_avail skb_vlan_tag_present(skb) 284 + vlan_tpid skb->vlan_proto 284 285 rand prandom_u32() 285 286 286 287 These extensions can also be prefixed with '#'.
+1
include/linux/filter.h
··· 454 454 BPF_ANCILLARY(VLAN_TAG_PRESENT); 455 455 BPF_ANCILLARY(PAY_OFFSET); 456 456 BPF_ANCILLARY(RANDOM); 457 + BPF_ANCILLARY(VLAN_TPID); 457 458 } 458 459 /* Fallthrough. */ 459 460 default:
+1
include/uapi/linux/bpf.h
··· 182 182 __u32 protocol; 183 183 __u32 vlan_present; 184 184 __u32 vlan_tci; 185 + __u32 vlan_proto; 185 186 }; 186 187 187 188 #endif /* _UAPI__LINUX_BPF_H__ */
+2 -1
include/uapi/linux/filter.h
··· 77 77 #define SKF_AD_VLAN_TAG_PRESENT 48 78 78 #define SKF_AD_PAY_OFFSET 52 79 79 #define SKF_AD_RANDOM 56 80 - #define SKF_AD_MAX 60 80 + #define SKF_AD_VLAN_TPID 60 81 + #define SKF_AD_MAX 64 81 82 #define SKF_NET_OFF (-0x100000) 82 83 #define SKF_LL_OFF (-0x200000) 83 84
+17
net/core/filter.c
··· 272 272 insn += cnt - 1; 273 273 break; 274 274 275 + case SKF_AD_OFF + SKF_AD_VLAN_TPID: 276 + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2); 277 + 278 + /* A = *(u16 *) (CTX + offsetof(vlan_proto)) */ 279 + *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX, 280 + offsetof(struct sk_buff, vlan_proto)); 281 + /* A = ntohs(A) [emitting a nop or swap16] */ 282 + *insn = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, 16); 283 + break; 284 + 275 285 case SKF_AD_OFF + SKF_AD_PAY_OFFSET: 276 286 case SKF_AD_OFF + SKF_AD_NLATTR: 277 287 case SKF_AD_OFF + SKF_AD_NLATTR_NEST: ··· 1234 1224 1235 1225 *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg, 1236 1226 offsetof(struct sk_buff, protocol)); 1227 + break; 1228 + 1229 + case offsetof(struct __sk_buff, vlan_proto): 1230 + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2); 1231 + 1232 + *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg, 1233 + offsetof(struct sk_buff, vlan_proto)); 1237 1234 break; 1238 1235 1239 1236 case offsetof(struct __sk_buff, mark):
+2
tools/net/bpf_exp.l
··· 92 92 "#"?("cpu") { return K_CPU; } 93 93 "#"?("vlan_tci") { return K_VLANT; } 94 94 "#"?("vlan_pr") { return K_VLANP; } 95 + "#"?("vlan_avail") { return K_VLANP; } 96 + "#"?("vlan_tpid") { return K_VLANTPID; } 95 97 "#"?("rand") { return K_RAND; } 96 98 97 99 ":" { return ':'; }
+10 -1
tools/net/bpf_exp.y
··· 56 56 %token OP_LDXI 57 57 58 58 %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE 59 - %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF K_RAND 59 + %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_VLANTPID K_POFF K_RAND 60 60 61 61 %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' 62 62 ··· 167 167 | OP_LDB K_RAND { 168 168 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 169 169 SKF_AD_OFF + SKF_AD_RANDOM); } 170 + | OP_LDB K_VLANTPID { 171 + bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 172 + SKF_AD_OFF + SKF_AD_VLAN_TPID); } 170 173 ; 171 174 172 175 ldh ··· 221 218 | OP_LDH K_RAND { 222 219 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 223 220 SKF_AD_OFF + SKF_AD_RANDOM); } 221 + | OP_LDH K_VLANTPID { 222 + bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 223 + SKF_AD_OFF + SKF_AD_VLAN_TPID); } 224 224 ; 225 225 226 226 ldi ··· 280 274 | OP_LD K_RAND { 281 275 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 282 276 SKF_AD_OFF + SKF_AD_RANDOM); } 277 + | OP_LD K_VLANTPID { 278 + bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 279 + SKF_AD_OFF + SKF_AD_VLAN_TPID); } 283 280 | OP_LD 'M' '[' number ']' { 284 281 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } 285 282 | OP_LD '[' 'x' '+' number ']' {