filter: add MOD operation
Add a new ALU opcode, to compute a modulus.
Commit ffe06c17af
used an ancillary to implement XOR_X,
but here we reserve one of the available ALU opcode to implement both
MOD_X and MOD_K
Signed-off-by: Eric Dumazet <edumazet@google.com>
Suggested-by: George Bakos <gbakos@alpinista.org>
Cc: Jay Schulist <jschlst@samba.org>
Cc: Jiri Pirko <jpirko@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c6bb8136c9
commit
b6069a9570
|
@ -74,6 +74,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
|
||||||
#define BPF_LSH 0x60
|
#define BPF_LSH 0x60
|
||||||
#define BPF_RSH 0x70
|
#define BPF_RSH 0x70
|
||||||
#define BPF_NEG 0x80
|
#define BPF_NEG 0x80
|
||||||
|
#define BPF_MOD 0x90
|
||||||
|
|
||||||
#define BPF_JA 0x00
|
#define BPF_JA 0x00
|
||||||
#define BPF_JEQ 0x10
|
#define BPF_JEQ 0x10
|
||||||
#define BPF_JGT 0x20
|
#define BPF_JGT 0x20
|
||||||
|
@ -196,6 +198,8 @@ enum {
|
||||||
BPF_S_ALU_MUL_K,
|
BPF_S_ALU_MUL_K,
|
||||||
BPF_S_ALU_MUL_X,
|
BPF_S_ALU_MUL_X,
|
||||||
BPF_S_ALU_DIV_X,
|
BPF_S_ALU_DIV_X,
|
||||||
|
BPF_S_ALU_MOD_K,
|
||||||
|
BPF_S_ALU_MOD_X,
|
||||||
BPF_S_ALU_AND_K,
|
BPF_S_ALU_AND_K,
|
||||||
BPF_S_ALU_AND_X,
|
BPF_S_ALU_AND_X,
|
||||||
BPF_S_ALU_OR_K,
|
BPF_S_ALU_OR_K,
|
||||||
|
|
|
@ -167,6 +167,14 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
|
||||||
case BPF_S_ALU_DIV_K:
|
case BPF_S_ALU_DIV_K:
|
||||||
A = reciprocal_divide(A, K);
|
A = reciprocal_divide(A, K);
|
||||||
continue;
|
continue;
|
||||||
|
case BPF_S_ALU_MOD_X:
|
||||||
|
if (X == 0)
|
||||||
|
return 0;
|
||||||
|
A %= X;
|
||||||
|
continue;
|
||||||
|
case BPF_S_ALU_MOD_K:
|
||||||
|
A %= K;
|
||||||
|
continue;
|
||||||
case BPF_S_ALU_AND_X:
|
case BPF_S_ALU_AND_X:
|
||||||
A &= X;
|
A &= X;
|
||||||
continue;
|
continue;
|
||||||
|
@ -469,6 +477,8 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
|
||||||
[BPF_ALU|BPF_MUL|BPF_K] = BPF_S_ALU_MUL_K,
|
[BPF_ALU|BPF_MUL|BPF_K] = BPF_S_ALU_MUL_K,
|
||||||
[BPF_ALU|BPF_MUL|BPF_X] = BPF_S_ALU_MUL_X,
|
[BPF_ALU|BPF_MUL|BPF_X] = BPF_S_ALU_MUL_X,
|
||||||
[BPF_ALU|BPF_DIV|BPF_X] = BPF_S_ALU_DIV_X,
|
[BPF_ALU|BPF_DIV|BPF_X] = BPF_S_ALU_DIV_X,
|
||||||
|
[BPF_ALU|BPF_MOD|BPF_K] = BPF_S_ALU_MOD_K,
|
||||||
|
[BPF_ALU|BPF_MOD|BPF_X] = BPF_S_ALU_MOD_X,
|
||||||
[BPF_ALU|BPF_AND|BPF_K] = BPF_S_ALU_AND_K,
|
[BPF_ALU|BPF_AND|BPF_K] = BPF_S_ALU_AND_K,
|
||||||
[BPF_ALU|BPF_AND|BPF_X] = BPF_S_ALU_AND_X,
|
[BPF_ALU|BPF_AND|BPF_X] = BPF_S_ALU_AND_X,
|
||||||
[BPF_ALU|BPF_OR|BPF_K] = BPF_S_ALU_OR_K,
|
[BPF_ALU|BPF_OR|BPF_K] = BPF_S_ALU_OR_K,
|
||||||
|
@ -531,6 +541,11 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
ftest->k = reciprocal_value(ftest->k);
|
ftest->k = reciprocal_value(ftest->k);
|
||||||
break;
|
break;
|
||||||
|
case BPF_S_ALU_MOD_K:
|
||||||
|
/* check for division by zero */
|
||||||
|
if (ftest->k == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
break;
|
||||||
case BPF_S_LD_MEM:
|
case BPF_S_LD_MEM:
|
||||||
case BPF_S_LDX_MEM:
|
case BPF_S_LDX_MEM:
|
||||||
case BPF_S_ST:
|
case BPF_S_ST:
|
||||||
|
|
Loading…
Reference in New Issue