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
					
				
			
		
					 2 changed files with 19 additions and 0 deletions
				
			
		|  | @ -74,6 +74,8 @@ struct sock_fprog {	/* Required for SO_ATTACH_FILTER. */ | |||
| #define         BPF_LSH         0x60 | ||||
| #define         BPF_RSH         0x70 | ||||
| #define         BPF_NEG         0x80 | ||||
| #define		BPF_MOD		0x90 | ||||
| 
 | ||||
| #define         BPF_JA          0x00 | ||||
| #define         BPF_JEQ         0x10 | ||||
| #define         BPF_JGT         0x20 | ||||
|  | @ -196,6 +198,8 @@ enum { | |||
| 	BPF_S_ALU_MUL_K, | ||||
| 	BPF_S_ALU_MUL_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_X, | ||||
| 	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: | ||||
| 			A = reciprocal_divide(A, K); | ||||
| 			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: | ||||
| 			A &= X; | ||||
| 			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_X]  = BPF_S_ALU_MUL_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_X]  = BPF_S_ALU_AND_X, | ||||
| 		[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; | ||||
| 			ftest->k = reciprocal_value(ftest->k); | ||||
| 			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_LDX_MEM: | ||||
| 		case BPF_S_ST: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Eric Dumazet
				Eric Dumazet