Skip to content

Commit 27cd545

Browse files
msekletardavem330
authored andcommitted
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 <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Jiri Pirko <[email protected]> Signed-off-by: Michal Sekletar <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f6bb76c commit 27cd545

7 files changed

Lines changed: 35 additions & 3 deletions

File tree

Documentation/networking/filter.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ Possible BPF extensions are shown in the following table:
280280
rxhash skb->hash
281281
cpu raw_smp_processor_id()
282282
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
284285
rand prandom_u32()
285286

286287
These extensions can also be prefixed with '#'.

include/linux/filter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ static inline u16 bpf_anc_helper(const struct sock_filter *ftest)
454454
BPF_ANCILLARY(VLAN_TAG_PRESENT);
455455
BPF_ANCILLARY(PAY_OFFSET);
456456
BPF_ANCILLARY(RANDOM);
457+
BPF_ANCILLARY(VLAN_TPID);
457458
}
458459
/* Fallthrough. */
459460
default:

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ struct __sk_buff {
182182
__u32 protocol;
183183
__u32 vlan_present;
184184
__u32 vlan_tci;
185+
__u32 vlan_proto;
185186
};
186187

187188
#endif /* _UAPI__LINUX_BPF_H__ */

include/uapi/linux/filter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
7777
#define SKF_AD_VLAN_TAG_PRESENT 48
7878
#define SKF_AD_PAY_OFFSET 52
7979
#define SKF_AD_RANDOM 56
80-
#define SKF_AD_MAX 60
80+
#define SKF_AD_VLAN_TPID 60
81+
#define SKF_AD_MAX 64
8182
#define SKF_NET_OFF (-0x100000)
8283
#define SKF_LL_OFF (-0x200000)
8384

net/core/filter.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
272272
insn += cnt - 1;
273273
break;
274274

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+
275285
case SKF_AD_OFF + SKF_AD_PAY_OFFSET:
276286
case SKF_AD_OFF + SKF_AD_NLATTR:
277287
case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
@@ -1226,6 +1236,13 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off,
12261236
offsetof(struct sk_buff, protocol));
12271237
break;
12281238

1239+
case offsetof(struct __sk_buff, vlan_proto):
1240+
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2);
1241+
1242+
*insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
1243+
offsetof(struct sk_buff, vlan_proto));
1244+
break;
1245+
12291246
case offsetof(struct __sk_buff, mark):
12301247
return convert_skb_access(SKF_AD_MARK, dst_reg, src_reg, insn);
12311248

tools/net/bpf_exp.l

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ extern void yyerror(const char *str);
9292
"#"?("cpu") { return K_CPU; }
9393
"#"?("vlan_tci") { return K_VLANT; }
9494
"#"?("vlan_pr") { return K_VLANP; }
95+
"#"?("vlan_avail") { return K_VLANP; }
96+
"#"?("vlan_tpid") { return K_VLANTPID; }
9597
"#"?("rand") { return K_RAND; }
9698

9799
":" { return ':'; }

tools/net/bpf_exp.y

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void bpf_set_jmp_label(char *label, enum jmp_type type);
5656
%token OP_LDXI
5757

5858
%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
6060

6161
%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
6262

@@ -167,6 +167,9 @@ ldb
167167
| OP_LDB K_RAND {
168168
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
169169
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); }
170173
;
171174

172175
ldh
@@ -218,6 +221,9 @@ ldh
218221
| OP_LDH K_RAND {
219222
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
220223
SKF_AD_OFF + SKF_AD_RANDOM); }
224+
| OP_LDH K_VLANTPID {
225+
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
226+
SKF_AD_OFF + SKF_AD_VLAN_TPID); }
221227
;
222228

223229
ldi
@@ -274,6 +280,9 @@ ld
274280
| OP_LD K_RAND {
275281
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
276282
SKF_AD_OFF + SKF_AD_RANDOM); }
283+
| OP_LD K_VLANTPID {
284+
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
285+
SKF_AD_OFF + SKF_AD_VLAN_TPID); }
277286
| OP_LD 'M' '[' number ']' {
278287
bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
279288
| OP_LD '[' 'x' '+' number ']' {

0 commit comments

Comments
 (0)