aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Sekletar <msekleta@redhat.com>2015-03-24 09:48:41 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-24 15:25:15 -0400
commit27cd5452476978283decb19e429e81fc6c71e74b (patch)
treea147d4576190e18580589e6faaf08e1b7050ef2d
parentf6bb76cd4d8552bada1e454c291419f893e1af7b (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.txt3
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/uapi/linux/bpf.h1
-rw-r--r--include/uapi/linux/filter.h3
-rw-r--r--net/core/filter.c17
-rw-r--r--tools/net/bpf_exp.l2
-rw-r--r--tools/net/bpf_exp.y11
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
286These extensions can also be prefixed with '#'. 287These 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
172ldh 175ldh
@@ -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
223ldi 229ldi
@@ -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 ']' {