History

bpf: allow BPF programs access 'protocol' and 'vlan_tci' fields

as a follow on to patch 70006af95515 ("bpf: allow eBPF access skb fields") this patch allows 'protocol' and 'vlan_tci' fields to be accessible from extended BPF programs. The usage of 'protocol', 'vlan_present' and 'vlan_tci' fields is the same as corresponding SKF_AD_PROTOCOL, SKF_AD_VLAN_TAG_PRESENT and SKF_AD_VLAN_TAG accesses in classic BPF.

Alexei Starovoitov committed 11 years ago

Commit c2497391 parent 9cf78673 files · +62 −22Browse files

Unified · Split

3 files
  1. include/uapi/linux/bpf.h +3 −0
  2. net/core/filter.c +50 −22
  3. samples/bpf/test_verifier.c +9 −0
include/uapi/linux/bpf.h+3−0
@@ -178,6 +178,9 @@ struct __sk_buff { · 177 unmodified lines
178178 __u32 pkt_type;
179179 __u32 mark;
180180 __u32 queue_mapping;
181+ __u32 protocol;
182+ __u32 vlan_present;
183+ __u32 vlan_tci;
181184 };
182185
183186 #endif /* _UAPI__LINUX_BPF_H__ */
net/core/filter.c+50−22
@@ -177,6 +177,35 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg, · 176 unmodified lines
177177 *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
178178 offsetof(struct sk_buff, queue_mapping));
179179 break;
180+
181+ case SKF_AD_PROTOCOL:
182+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
183+
184+ /* dst_reg = *(u16 *) (src_reg + offsetof(protocol)) */
185+ *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
186+ offsetof(struct sk_buff, protocol));
187+ /* dst_reg = ntohs(dst_reg) [emitting a nop or swap16] */
188+ *insn++ = BPF_ENDIAN(BPF_FROM_BE, dst_reg, 16);
189+ break;
190+
191+ case SKF_AD_VLAN_TAG:
192+ case SKF_AD_VLAN_TAG_PRESENT:
193+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
194+ BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
195+
196+ /* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
197+ *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
198+ offsetof(struct sk_buff, vlan_tci));
199+ if (skb_field == SKF_AD_VLAN_TAG) {
200+ *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg,
201+ ~VLAN_TAG_PRESENT);
202+ } else {
203+ /* dst_reg >>= 12 */
204+ *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 12);
205+ /* dst_reg &= 1 */
206+ *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
207+ }
208+ break;
180209 }
181210
182211 return insn - insn_buf;
@@ -190,13 +219,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp, · 7 unmodified lines
190219
191220 switch (fp->k) {
192221 case SKF_AD_OFF + SKF_AD_PROTOCOL:
193− BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
194−
195− /* A = *(u16 *) (CTX + offsetof(protocol)) */
196− *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
197− offsetof(struct sk_buff, protocol));
198− /* A = ntohs(A) [emitting a nop or swap16] */
199− *insn = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, 16);
222+ cnt = convert_skb_access(SKF_AD_PROTOCOL, BPF_REG_A, BPF_REG_CTX, insn);
223+ insn += cnt - 1;
200224 break;
201225
202226 case SKF_AD_OFF + SKF_AD_PKTTYPE:
@@ -242,22 +266,15 @@ static bool convert_bpf_extensions(struct sock_filter *fp, · 39 unmodified lines
242266 break;
243267
244268 case SKF_AD_OFF + SKF_AD_VLAN_TAG:
245− case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
246− BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
247− BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
269+ cnt = convert_skb_access(SKF_AD_VLAN_TAG,
270+ BPF_REG_A, BPF_REG_CTX, insn);
271+ insn += cnt - 1;
272+ break;
248273
249− /* A = *(u16 *) (CTX + offsetof(vlan_tci)) */
250− *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
251− offsetof(struct sk_buff, vlan_tci));
252− if (fp->k == SKF_AD_OFF + SKF_AD_VLAN_TAG) {
253− *insn = BPF_ALU32_IMM(BPF_AND, BPF_REG_A,
254− ~VLAN_TAG_PRESENT);
255− } else {
256− /* A >>= 12 */
257− *insn++ = BPF_ALU32_IMM(BPF_RSH, BPF_REG_A, 12);
258− /* A &= 1 */
259− *insn = BPF_ALU32_IMM(BPF_AND, BPF_REG_A, 1);
260− }
274+ case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
275+ cnt = convert_skb_access(SKF_AD_VLAN_TAG_PRESENT,
276+ BPF_REG_A, BPF_REG_CTX, insn);
277+ insn += cnt - 1;
261278 break;
262279
263280 case SKF_AD_OFF + SKF_AD_PAY_OFFSET:
@@ -1215,6 +1232,17 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off, · 951 unmodified lines
12151232
12161233 case offsetof(struct __sk_buff, queue_mapping):
12171234 return convert_skb_access(SKF_AD_QUEUE, dst_reg, src_reg, insn);
1235+
1236+ case offsetof(struct __sk_buff, protocol):
1237+ return convert_skb_access(SKF_AD_PROTOCOL, dst_reg, src_reg, insn);
1238+
1239+ case offsetof(struct __sk_buff, vlan_present):
1240+ return convert_skb_access(SKF_AD_VLAN_TAG_PRESENT,
1241+ dst_reg, src_reg, insn);
1242+
1243+ case offsetof(struct __sk_buff, vlan_tci):
1244+ return convert_skb_access(SKF_AD_VLAN_TAG,
1245+ dst_reg, src_reg, insn);
12181246 }
12191247
12201248 return insn - insn_buf;
samples/bpf/test_verifier.c+9−0
@@ -658,6 +658,15 @@ static struct bpf_test tests[] = { · 657 unmodified lines
658658 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
659659 offsetof(struct __sk_buff, queue_mapping)),
660660 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
661+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
662+ offsetof(struct __sk_buff, protocol)),
663+ BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
664+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
665+ offsetof(struct __sk_buff, vlan_present)),
666+ BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
667+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
668+ offsetof(struct __sk_buff, vlan_tci)),
669+ BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
661670 BPF_EXIT_INSN(),
662671 },
663672 .result = ACCEPT,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t