diff options
author | Michal Sekletar <msekleta@redhat.com> | 2015-03-24 09:48:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-24 15:25:15 -0400 |
commit | 27cd5452476978283decb19e429e81fc6c71e74b (patch) | |
tree | a147d4576190e18580589e6faaf08e1b7050ef2d | |
parent | f6bb76cd4d8552bada1e454c291419f893e1af7b (diff) |
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>
-rw-r--r-- | Documentation/networking/filter.txt | 3 | ||||
-rw-r--r-- | include/linux/filter.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/bpf.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/filter.h | 3 | ||||
-rw-r--r-- | net/core/filter.c | 17 | ||||
-rw-r--r-- | tools/net/bpf_exp.l | 2 | ||||
-rw-r--r-- | tools/net/bpf_exp.y | 11 |
7 files changed, 35 insertions, 3 deletions
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index 9930ecfbb465..135581f015e1 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt | |||
@@ -280,7 +280,8 @@ Possible BPF extensions are shown in the following table: | |||
280 | rxhash skb->hash | 280 | rxhash skb->hash |
281 | cpu raw_smp_processor_id() | 281 | cpu raw_smp_processor_id() |
282 | vlan_tci skb_vlan_tag_get(skb) | 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 | rand prandom_u32() | 285 | rand prandom_u32() |
285 | 286 | ||
286 | These extensions can also be prefixed with '#'. | 287 | These extensions can also be prefixed with '#'. |
diff --git a/include/linux/filter.h b/include/linux/filter.h index 9ee8c67ea249..fa11b3a367be 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
@@ -454,6 +454,7 @@ static inline u16 bpf_anc_helper(const struct sock_filter *ftest) | |||
454 | BPF_ANCILLARY(VLAN_TAG_PRESENT); | 454 | BPF_ANCILLARY(VLAN_TAG_PRESENT); |
455 | BPF_ANCILLARY(PAY_OFFSET); | 455 | BPF_ANCILLARY(PAY_OFFSET); |
456 | BPF_ANCILLARY(RANDOM); | 456 | BPF_ANCILLARY(RANDOM); |
457 | BPF_ANCILLARY(VLAN_TPID); | ||
457 | } | 458 | } |
458 | /* Fallthrough. */ | 459 | /* Fallthrough. */ |
459 | default: | 460 | default: |
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 3dd314a45d0d..27dc4ec58840 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -182,6 +182,7 @@ struct __sk_buff { | |||
182 | __u32 protocol; | 182 | __u32 protocol; |
183 | __u32 vlan_present; | 183 | __u32 vlan_present; |
184 | __u32 vlan_tci; | 184 | __u32 vlan_tci; |
185 | __u32 vlan_proto; | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | #endif /* _UAPI__LINUX_BPF_H__ */ | 188 | #endif /* _UAPI__LINUX_BPF_H__ */ |
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h index 47785d5ecf17..34c7936ca114 100644 --- a/include/uapi/linux/filter.h +++ b/include/uapi/linux/filter.h | |||
@@ -77,7 +77,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ | |||
77 | #define SKF_AD_VLAN_TAG_PRESENT 48 | 77 | #define SKF_AD_VLAN_TAG_PRESENT 48 |
78 | #define SKF_AD_PAY_OFFSET 52 | 78 | #define SKF_AD_PAY_OFFSET 52 |
79 | #define SKF_AD_RANDOM 56 | 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 | #define SKF_NET_OFF (-0x100000) | 82 | #define SKF_NET_OFF (-0x100000) |
82 | #define SKF_LL_OFF (-0x200000) | 83 | #define SKF_LL_OFF (-0x200000) |
83 | 84 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 084eacc4d1d4..32f43c59908c 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -272,6 +272,16 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
272 | insn += cnt - 1; | 272 | insn += cnt - 1; |
273 | break; | 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 | case SKF_AD_OFF + SKF_AD_PAY_OFFSET: | 285 | case SKF_AD_OFF + SKF_AD_PAY_OFFSET: |
276 | case SKF_AD_OFF + SKF_AD_NLATTR: | 286 | case SKF_AD_OFF + SKF_AD_NLATTR: |
277 | case SKF_AD_OFF + SKF_AD_NLATTR_NEST: | 287 | 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, | |||
1226 | offsetof(struct sk_buff, protocol)); | 1236 | offsetof(struct sk_buff, protocol)); |
1227 | break; | 1237 | break; |
1228 | 1238 | ||
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 | |||
1229 | case offsetof(struct __sk_buff, mark): | 1246 | case offsetof(struct __sk_buff, mark): |
1230 | return convert_skb_access(SKF_AD_MARK, dst_reg, src_reg, insn); | 1247 | return convert_skb_access(SKF_AD_MARK, dst_reg, src_reg, insn); |
1231 | 1248 | ||
diff --git a/tools/net/bpf_exp.l b/tools/net/bpf_exp.l index 833a96611da6..c83af3fb77de 100644 --- a/tools/net/bpf_exp.l +++ b/tools/net/bpf_exp.l | |||
@@ -92,6 +92,8 @@ extern void yyerror(const char *str); | |||
92 | "#"?("cpu") { return K_CPU; } | 92 | "#"?("cpu") { return K_CPU; } |
93 | "#"?("vlan_tci") { return K_VLANT; } | 93 | "#"?("vlan_tci") { return K_VLANT; } |
94 | "#"?("vlan_pr") { return K_VLANP; } | 94 | "#"?("vlan_pr") { return K_VLANP; } |
95 | "#"?("vlan_avail") { return K_VLANP; } | ||
96 | "#"?("vlan_tpid") { return K_VLANTPID; } | ||
95 | "#"?("rand") { return K_RAND; } | 97 | "#"?("rand") { return K_RAND; } |
96 | 98 | ||
97 | ":" { return ':'; } | 99 | ":" { return ':'; } |
diff --git a/tools/net/bpf_exp.y b/tools/net/bpf_exp.y index e6306c51c26f..f8332749b44c 100644 --- a/tools/net/bpf_exp.y +++ b/tools/net/bpf_exp.y | |||
@@ -56,7 +56,7 @@ static void bpf_set_jmp_label(char *label, enum jmp_type type); | |||
56 | %token OP_LDXI | 56 | %token OP_LDXI |
57 | 57 | ||
58 | %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE | 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 | %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' | 61 | %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' |
62 | 62 | ||
@@ -167,6 +167,9 @@ ldb | |||
167 | | OP_LDB K_RAND { | 167 | | OP_LDB K_RAND { |
168 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | 168 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, |
169 | SKF_AD_OFF + SKF_AD_RANDOM); } | 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 | ldh | 175 | ldh |
@@ -218,6 +221,9 @@ ldh | |||
218 | | OP_LDH K_RAND { | 221 | | OP_LDH K_RAND { |
219 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | 222 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, |
220 | SKF_AD_OFF + SKF_AD_RANDOM); } | 223 | 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); } | ||
221 | ; | 227 | ; |
222 | 228 | ||
223 | ldi | 229 | ldi |
@@ -274,6 +280,9 @@ ld | |||
274 | | OP_LD K_RAND { | 280 | | OP_LD K_RAND { |
275 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | 281 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, |
276 | SKF_AD_OFF + SKF_AD_RANDOM); } | 282 | 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); } | ||
277 | | OP_LD 'M' '[' number ']' { | 286 | | OP_LD 'M' '[' number ']' { |
278 | bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } | 287 | bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } |
279 | | OP_LD '[' 'x' '+' number ']' { | 288 | | OP_LD '[' 'x' '+' number ']' { |