aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/filter.txt13
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/uapi/linux/filter.h3
-rw-r--r--net/core/filter.c12
-rw-r--r--tools/net/bpf_exp.l1
-rw-r--r--tools/net/bpf_exp.y11
6 files changed, 39 insertions, 2 deletions
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index 81f940f4e884..82e1cb0b3da8 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -281,6 +281,7 @@ Possible BPF extensions are shown in the following table:
281 cpu raw_smp_processor_id() 281 cpu raw_smp_processor_id()
282 vlan_tci vlan_tx_tag_get(skb) 282 vlan_tci vlan_tx_tag_get(skb)
283 vlan_pr vlan_tx_tag_present(skb) 283 vlan_pr vlan_tx_tag_present(skb)
284 rand prandom_u32()
284 285
285These extensions can also be prefixed with '#'. 286These extensions can also be prefixed with '#'.
286Examples for low-level BPF: 287Examples for low-level BPF:
@@ -308,6 +309,18 @@ Examples for low-level BPF:
308 ret #-1 309 ret #-1
309 drop: ret #0 310 drop: ret #0
310 311
312** icmp random packet sampling, 1 in 4
313 ldh [12]
314 jne #0x800, drop
315 ldb [23]
316 jneq #1, drop
317 # get a random uint32 number
318 ld rand
319 mod #4
320 jneq #1, drop
321 ret #-1
322 drop: ret #0
323
311** SECCOMP filter example: 324** SECCOMP filter example:
312 325
313 ld [4] /* offsetof(struct seccomp_data, arch) */ 326 ld [4] /* offsetof(struct seccomp_data, arch) */
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 024fd03e5d18..759abf78dd61 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -223,6 +223,7 @@ enum {
223 BPF_S_ANC_VLAN_TAG, 223 BPF_S_ANC_VLAN_TAG,
224 BPF_S_ANC_VLAN_TAG_PRESENT, 224 BPF_S_ANC_VLAN_TAG_PRESENT,
225 BPF_S_ANC_PAY_OFFSET, 225 BPF_S_ANC_PAY_OFFSET,
226 BPF_S_ANC_RANDOM,
226}; 227};
227 228
228#endif /* __LINUX_FILTER_H__ */ 229#endif /* __LINUX_FILTER_H__ */
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h
index 8eb9ccaa5b48..253b4d42cf2b 100644
--- a/include/uapi/linux/filter.h
+++ b/include/uapi/linux/filter.h
@@ -130,7 +130,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
130#define SKF_AD_VLAN_TAG 44 130#define SKF_AD_VLAN_TAG 44
131#define SKF_AD_VLAN_TAG_PRESENT 48 131#define SKF_AD_VLAN_TAG_PRESENT 48
132#define SKF_AD_PAY_OFFSET 52 132#define SKF_AD_PAY_OFFSET 52
133#define SKF_AD_MAX 56 133#define SKF_AD_RANDOM 56
134#define SKF_AD_MAX 60
134#define SKF_NET_OFF (-0x100000) 135#define SKF_NET_OFF (-0x100000)
135#define SKF_LL_OFF (-0x200000) 136#define SKF_LL_OFF (-0x200000)
136 137
diff --git a/net/core/filter.c b/net/core/filter.c
index cd58614660cf..78a636e60a0b 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -643,6 +643,12 @@ static u64 __get_raw_cpu_id(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
643 return raw_smp_processor_id(); 643 return raw_smp_processor_id();
644} 644}
645 645
646/* note that this only generates 32-bit random numbers */
647static u64 __get_random_u32(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
648{
649 return (u64)prandom_u32();
650}
651
646/* Register mappings for user programs. */ 652/* Register mappings for user programs. */
647#define A_REG 0 653#define A_REG 0
648#define X_REG 7 654#define X_REG 7
@@ -779,6 +785,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
779 case SKF_AD_OFF + SKF_AD_NLATTR: 785 case SKF_AD_OFF + SKF_AD_NLATTR:
780 case SKF_AD_OFF + SKF_AD_NLATTR_NEST: 786 case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
781 case SKF_AD_OFF + SKF_AD_CPU: 787 case SKF_AD_OFF + SKF_AD_CPU:
788 case SKF_AD_OFF + SKF_AD_RANDOM:
782 /* arg1 = ctx */ 789 /* arg1 = ctx */
783 insn->code = BPF_ALU64 | BPF_MOV | BPF_X; 790 insn->code = BPF_ALU64 | BPF_MOV | BPF_X;
784 insn->a_reg = ARG1_REG; 791 insn->a_reg = ARG1_REG;
@@ -812,6 +819,9 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
812 case SKF_AD_OFF + SKF_AD_CPU: 819 case SKF_AD_OFF + SKF_AD_CPU:
813 insn->imm = __get_raw_cpu_id - __bpf_call_base; 820 insn->imm = __get_raw_cpu_id - __bpf_call_base;
814 break; 821 break;
822 case SKF_AD_OFF + SKF_AD_RANDOM:
823 insn->imm = __get_random_u32 - __bpf_call_base;
824 break;
815 } 825 }
816 break; 826 break;
817 827
@@ -1362,6 +1372,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
1362 ANCILLARY(VLAN_TAG); 1372 ANCILLARY(VLAN_TAG);
1363 ANCILLARY(VLAN_TAG_PRESENT); 1373 ANCILLARY(VLAN_TAG_PRESENT);
1364 ANCILLARY(PAY_OFFSET); 1374 ANCILLARY(PAY_OFFSET);
1375 ANCILLARY(RANDOM);
1365 } 1376 }
1366 1377
1367 /* ancillary operation unknown or unsupported */ 1378 /* ancillary operation unknown or unsupported */
@@ -1746,6 +1757,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
1746 [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, 1757 [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS,
1747 [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, 1758 [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
1748 [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, 1759 [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS,
1760 [BPF_S_ANC_RANDOM] = BPF_LD|BPF_B|BPF_ABS,
1749 [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN, 1761 [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN,
1750 [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND, 1762 [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND,
1751 [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND, 1763 [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND,
diff --git a/tools/net/bpf_exp.l b/tools/net/bpf_exp.l
index bf7be77ddd62..833a96611da6 100644
--- a/tools/net/bpf_exp.l
+++ b/tools/net/bpf_exp.l
@@ -92,6 +92,7 @@ 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"#"?("rand") { return K_RAND; }
95 96
96":" { return ':'; } 97":" { return ':'; }
97"," { return ','; } 98"," { return ','; }
diff --git a/tools/net/bpf_exp.y b/tools/net/bpf_exp.y
index d15efc989ef5..e6306c51c26f 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 59%token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF K_RAND
60 60
61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' 61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
62 62
@@ -164,6 +164,9 @@ ldb
164 | OP_LDB K_POFF { 164 | OP_LDB K_POFF {
165 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 165 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
166 SKF_AD_OFF + SKF_AD_PAY_OFFSET); } 166 SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
167 | OP_LDB K_RAND {
168 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
169 SKF_AD_OFF + SKF_AD_RANDOM); }
167 ; 170 ;
168 171
169ldh 172ldh
@@ -212,6 +215,9 @@ ldh
212 | OP_LDH K_POFF { 215 | OP_LDH K_POFF {
213 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 216 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
214 SKF_AD_OFF + SKF_AD_PAY_OFFSET); } 217 SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
218 | OP_LDH K_RAND {
219 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
220 SKF_AD_OFF + SKF_AD_RANDOM); }
215 ; 221 ;
216 222
217ldi 223ldi
@@ -265,6 +271,9 @@ ld
265 | OP_LD K_POFF { 271 | OP_LD K_POFF {
266 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 272 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
267 SKF_AD_OFF + SKF_AD_PAY_OFFSET); } 273 SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
274 | OP_LD K_RAND {
275 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
276 SKF_AD_OFF + SKF_AD_RANDOM); }
268 | OP_LD 'M' '[' number ']' { 277 | OP_LD 'M' '[' number ']' {
269 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } 278 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
270 | OP_LD '[' 'x' '+' number ']' { 279 | OP_LD '[' 'x' '+' number ']' {