forked from mirrors/linux
		
	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_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 a new issue