Re: [PATCH nft 2/3] src: Add support for concatenated set ranges

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 20 Nov 2019 13:53:08 +0100
Phil Sutter <phil@xxxxxx> wrote:

> On Wed, Nov 20, 2019 at 12:49:54PM +0100, Stefano Brivio wrote:
>
> > On Tue, 19 Nov 2019 23:12:38 +0100
> > Phil Sutter <phil@xxxxxx> wrote:
> [...]
>
> > So, the whole thing would look like (together with the other change
> > you suggest):
> > 
> > --
> > static int netlink_gen_concat_data_expr(const struct expr *i,
> > 					unsigned char *data)
> > {
> > 	if (i->etype == EXPR_RANGE) {
> > 		const struct expr *e;
> > 
> > 		if (i->flags & EXPR_F_INTERVAL_END)
> > 			e = i->right;
> > 		else
> > 			e = i->left;
> > 
> > 		return netlink_export_pad(data, e->value, e);
> > 	}
> > 
> > 	if (i->etype == EXPR_PREFIX) {
> > 		if (i->flags & EXPR_F_INTERVAL_END) {
> > 			int count;
> > 			mpz_t v;
> > 
> > 			mpz_init_bitmask(v, i->len - i->prefix_len);
> > 			mpz_add(v, i->prefix->value, v);
> > 			count = netlink_export_pad(data, v, i);
> > 			mpz_clear(v);
> > 			return count;
> > 		}
> > 
> > 		return netlink_export_pad(data, i->prefix->value, i);
> > 	}
> > 
> > 	assert(i->etype == EXPR_VALUE);
> > 
> > 	return netlink_export_pad(data, i->value, i);
> > }  
> 
> I would even:
> 
> | static int
> | netlink_gen_concat_data_expr(const struct expr *i, unsigned char *data)
> | {
> | 	mpz_t *valp = NULL;
> | 
> | 	switch (i->etype) {
> | 	case EXPR_RANGE:
> | 		i = (i->flags & EXPR_F_INTERVAL_END) ? i->right : i->left;
> | 		break;
> | 	case EXPR_PREFIX:
> | 		if (i->flags & EXPR_F_INTERVAL_END) {
> | 			int count;
> | 			mpz_t v;
> | 
> | 			mpz_init_bitmask(v, i->len - i->prefix_len);
> | 			mpz_add(v, i->prefix->value, v);
> | 			count = netlink_export_pad(data, v, i);
> | 			mpz_clear(v);
> | 			return count;
> | 		}
> | 		valp = &i->prefix->value;
> | 		break;
> | 	case EXPR_VALUE:
> | 		break;
> | 	default:
> | 		BUG("invalid expression type '%s' in set", expr_ops(i)->name);
> | 	}
> | 
> | 	return netlink_export_pad(data, valp ? *valp : i->value, i);
> | }
> 
> But that's up to you. :)

I think it's nicer with a switch and that BUG() is more helpful than a
random assert, but I personally find that ternary condition on valp a
bit difficult to follow.

I'd recycle most of your function without that -- it's actually shorter
and still makes it clear enough what gets fed to netlink_export_pad().

Oh, and by the way, at this point we need to check flags on the 'key'
expression.

> > static void netlink_gen_concat_data(const struct expr *expr,
> > 				    struct nft_data_linearize *nld)
> > {
> > 	unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
> > 	unsigned char data[len];
> > 	const struct expr *i;
> > 
> > 	memset(data, 0, len);
> > 
> > 	list_for_each_entry(i, &expr->expressions, list)
> > 		offset += netlink_gen_concat_data_expr(i, data + offset);
> > 
> > 	memcpy(nld->value, data, len);
> > 	nld->len = len;
> > }
> > --
> > 
> > Is that better?  
> 
> Looks great, thanks!
> 
> [...]
>
> > > So this is the fifth copy of the same piece of code. :(
> > > 
> > > Isn't there a better way to solve that?  
> > 
> > I couldn't think of any.  
> 
> I guess we would need an intermediate state which is 'multiton_rhs_expr
> DOT multiton_rhs_expr'. Might turn into a mess as well. :)

I just tried to add that, and kept losing myself in the middle of it.
It might be me, but it doesn't sound that promising when it comes to
readability later.

I guess we already have enough levels of indirection here -- I'd just
go with the compound_expr_alloc_or_add() you suggested.

> > > Intuitively, I would just:
> > > 
> > > | int tmp = len;
> > > | while (start != end && !(start & 1) && (end & 1) && tmp) {
> > > |	start >>= 1;
> > > |	end >>= 1;
> > > |	tmp--;
> > > | }
> > > | return (tmp && start == end) ? len - tmp : -1;
> > > 
> > > Is that slow when dealing with gmp?  
> > 
> > I don't think so, it also avoid copies and allocations, while shifting
> > and setting bits have comparable complexities. I'd go with the gmp
> > version of this.  

Actually, I need to preserve the original elements, so the two copies
are needed anyway -- other than that, I basically recycled your
function.

-- 
Stefano





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux