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
178 __u32 pkt_type;178 __u32 pkt_type;
179 __u32 mark;179 __u32 mark;
180 __u32 queue_mapping;180 __u32 queue_mapping;
181 __u32 protocol;
182 __u32 vlan_present;
183 __u32 vlan_tci;
181};184};
182 185
183#endif /* _UAPI__LINUX_BPF_H__ */186#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
177 *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,177 *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
178 offsetof(struct sk_buff, queue_mapping));178 offsetof(struct sk_buff, queue_mapping));
179 break;179 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;
180 }209 }
181 210
182 return insn - insn_buf;211 return insn - insn_buf;
@@ -190,13 +219,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp, · 7 unmodified lines
190 219
191 switch (fp->k) {220 switch (fp->k) {
192 case SKF_AD_OFF + SKF_AD_PROTOCOL:221 case SKF_AD_OFF + SKF_AD_PROTOCOL:
193 BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);222 cnt = convert_skb_access(SKF_AD_PROTOCOL, BPF_REG_A, BPF_REG_CTX, insn);
194 223 insn += cnt - 1;
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);
200 break;224 break;
201 225
202 case SKF_AD_OFF + SKF_AD_PKTTYPE:226 case SKF_AD_OFF + SKF_AD_PKTTYPE:
@@ -242,22 +266,15 @@ static bool convert_bpf_extensions(struct sock_filter *fp, · 39 unmodified lines
242 break;266 break;
243 267
244 case SKF_AD_OFF + SKF_AD_VLAN_TAG:268 case SKF_AD_OFF + SKF_AD_VLAN_TAG:
245 case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:269 cnt = convert_skb_access(SKF_AD_VLAN_TAG,
246 BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);270 BPF_REG_A, BPF_REG_CTX, insn);
247 BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);271 insn += cnt - 1;
272 break;
248 273
249 /* A = *(u16 *) (CTX + offsetof(vlan_tci)) */274 case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
250 *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,275 cnt = convert_skb_access(SKF_AD_VLAN_TAG_PRESENT,
251 offsetof(struct sk_buff, vlan_tci));276 BPF_REG_A, BPF_REG_CTX, insn);
252 if (fp->k == SKF_AD_OFF + SKF_AD_VLAN_TAG) {277 insn += cnt - 1;
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 }
261 break;278 break;
262 279
263 case SKF_AD_OFF + SKF_AD_PAY_OFFSET:280 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
1215 1232
1216 case offsetof(struct __sk_buff, queue_mapping):1233 case offsetof(struct __sk_buff, queue_mapping):
1217 return convert_skb_access(SKF_AD_QUEUE, dst_reg, src_reg, insn);1234 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);
1218 }1246 }
1219 1247
1220 return insn - insn_buf;1248 return insn - insn_buf;
samples/bpf/test_verifier.c+9−0
@@ -658,6 +658,15 @@ static struct bpf_test tests[] = { · 657 unmodified lines
658 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,658 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
659 offsetof(struct __sk_buff, queue_mapping)),659 offsetof(struct __sk_buff, queue_mapping)),
660 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),660 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),
661 BPF_EXIT_INSN(),670 BPF_EXIT_INSN(),
662 },671 },
663 .result = ACCEPT,672 .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