Efficient use of Dummynet pipes in IPFW

Ian Smith smithi at nimnet.asn.au
Mon Sep 19 21:05:33 PDT 2005


On Mon, 19 Sep 2005, Brett Glass wrote:

 > At 10:20 AM 9/19/2005, Luigi Rizzo wrote:
 > 
 > >original
 > >
 > >        ipfw add 1000 dosomething cond1 cond2 cond3 cond4 cond5 ... condN
 > >
 > >negated:
 > >
 > >        ipfw add 1000 skipto 1001 cond1 cond2 cond3 cond4 cond5 ... condN
 > >        ipfw add 1000 dosomething
 > 
 > This doesn't work, because you must transform cond1 && cond2 && cond3...
 > into multiple rules that implement ~(cond1 || cond2 || cond3...). So,

.. later corrected? to ..

 > I should have said that you must implement !(!cond1 || !cond2 || !cond3...).

That would be silly, either way.  It does work.  You started off saying:

| Unfortunately, because IPFW doesn't have a "not" that can cover the
| "and" of all the conditions in the rule -- that is, you can't say
| "not (ip from A to any in via fxp1)" -- it's very difficult to do
| this with a single rule containing a "skipto" action. What's more,
| there's no "resume at" clause available in IPFW that would change
| where a packet was reinjected, and no such thing as a "come from" [..]

So what Luigi says is absolutely correct for that desired negation.  No,
you can't do it with a SINGLE rule; it is low level, consider it RISC.

 > you'd need do do the following:
 > 
 > ipfw add 1000 skipto 1001 not cond1
 > ipfw add 1000 skipto 1001 not cond2
 > ... (N rules total)
 > ipfw add 1000 skipto 1001 not condN
 > ipfw add 1000 dosomething
 > ipfw add 1000 skipto 5000 // Where to resume on success
 > ipfw add 1001 // Jump target; implemented in IPFW as "count ip from any to any"

1000 skipto 1001 cond1 cond2 cond3 .. # ie (cond1 AND cond2 AND ..)
1000 dosomethingsuchasyourpipe        # performed on NOT (cond1 AND ...)
1000 skipto 5000 ip from any to any   # your 'resume after pipe' ..

rule 1001, your 'jump target' will just be your next test, or the next
rule can be any number rule >= 1001.  So there's extra no cost for it.

And as Luigi pointed out, skipto is fast.

 > The other way to do it is via "spaghetti rules:"
 > 
 > ipfw add 1000 skipto 1002 cond1 cond2 cond3 cond4 cond5 ... condN
 > ipfw add 1001 skipto 1003
 > ipfw add 1002 dosomething
 > ipfw add 1002 skipto 5000 // Where to resume on success
 > ipfw add 1003 // Jump target; implemented inside IPFW as "count ip from any to any"

Spaghetti like that is just not needed.  See above.

 > Or you can do the entire pattern match twice:
 > 
 > ipfw add 1000 dosomething cond1 cond2 cond3 cond4 cond5 ... condN
 > ipfw add 1000 skipto 5000 cond1 cond2 cond3 cond4 cond5 ... condN

I can't see your desire to save ONE rule is worth trying to convince
somebody ELSE to tackle the code for a feature only you seem to want.

And if lots of similar rulesets are needed, write a script or use the
preprocessor as suggested (the latter's beyond me, but not the former)

cheers, Ian



More information about the freebsd-net mailing list