aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-09-07 18:03:35 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-10 15:44:56 -0400
commitb6069a95706ca5738be3f5d90fd286cbd13ac695 (patch)
tree8d3d2f11385265b3a0a7d03f07d98752b694ed14 /net/core
parentc6bb8136c95ce16545f8c4028e958c0ee6c86f23 (diff)
filter: add MOD operation
Add a new ALU opcode, to compute a modulus. Commit ffe06c17afbbb 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>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/filter.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 907efd27ec77..fbe3a8d12570 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -167,6 +167,14 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
167 case BPF_S_ALU_DIV_K: 167 case BPF_S_ALU_DIV_K:
168 A = reciprocal_divide(A, K); 168 A = reciprocal_divide(A, K);
169 continue; 169 continue;
170 case BPF_S_ALU_MOD_X:
171 if (X == 0)
172 return 0;
173 A %= X;
174 continue;
175 case BPF_S_ALU_MOD_K:
176 A %= K;
177 continue;
170 case BPF_S_ALU_AND_X: 178 case BPF_S_ALU_AND_X:
171 A &= X; 179 A &= X;
172 continue; 180 continue;
@@ -469,6 +477,8 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
469 [BPF_ALU|BPF_MUL|BPF_K] = BPF_S_ALU_MUL_K, 477 [BPF_ALU|BPF_MUL|BPF_K] = BPF_S_ALU_MUL_K,
470 [BPF_ALU|BPF_MUL|BPF_X] = BPF_S_ALU_MUL_X, 478 [BPF_ALU|BPF_MUL|BPF_X] = BPF_S_ALU_MUL_X,
471 [BPF_ALU|BPF_DIV|BPF_X] = BPF_S_ALU_DIV_X, 479 [BPF_ALU|BPF_DIV|BPF_X] = BPF_S_ALU_DIV_X,
480 [BPF_ALU|BPF_MOD|BPF_K] = BPF_S_ALU_MOD_K,
481 [BPF_ALU|BPF_MOD|BPF_X] = BPF_S_ALU_MOD_X,
472 [BPF_ALU|BPF_AND|BPF_K] = BPF_S_ALU_AND_K, 482 [BPF_ALU|BPF_AND|BPF_K] = BPF_S_ALU_AND_K,
473 [BPF_ALU|BPF_AND|BPF_X] = BPF_S_ALU_AND_X, 483 [BPF_ALU|BPF_AND|BPF_X] = BPF_S_ALU_AND_X,
474 [BPF_ALU|BPF_OR|BPF_K] = BPF_S_ALU_OR_K, 484 [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)
531 return -EINVAL; 541 return -EINVAL;
532 ftest->k = reciprocal_value(ftest->k); 542 ftest->k = reciprocal_value(ftest->k);
533 break; 543 break;
544 case BPF_S_ALU_MOD_K:
545 /* check for division by zero */
546 if (ftest->k == 0)
547 return -EINVAL;
548 break;
534 case BPF_S_LD_MEM: 549 case BPF_S_LD_MEM:
535 case BPF_S_LDX_MEM: 550 case BPF_S_LDX_MEM:
536 case BPF_S_ST: 551 case BPF_S_ST: