diff mbox

[iproute,0/3] tc: pedit fixes

Message ID 1456917631-18447-1-git-send-email-phil@nwl.cc
State Superseded, archived
Delegated to: stephen hemminger
Headers show

Commit Message

Phil Sutter March 2, 2016, 11:20 a.m. UTC
While implementing an implementation example for a pedit man page, I
noticed several issues with the current code. The following patch
series addreses them.

In order to validate my changes, I implemented a simple unit tester.
It requires the following hack:

--------------------------8<-----------------------------------------
--------------------------8<-----------------------------------------

With this in place, the following simple shell script can be used to
check generated permutation values:

--------------------------8<-----------------------------------------
#!/bin/bash

run_tc() {
	echo "testing $@"
	eval "$(./tc/tc filter add dev bla123 parent root u32 \
		match u32 0 0 action pedit munge $@ 2>&1 | \
		grep -e '^\(mask\|val\|off\|at\|offmask\|shift\)=')"
}

prove() { # (oval, check, ooff)
	local oval=$1
	local check=$2
	local ooff=$3
	[[ $ooff -eq $off ]] || {
		echo "Wrong offset ($off instead of $ooff)"
		#exit 1
	}
	[[ $(((oval & mask) ^ val)) -eq $check ]] || {
		echo "failed for $oval, should be $check but is 0x$(echo "obase = 16; $(((oval & mask) ^ val))" | bc)"
		echo "mask=$mask"
		echo "val=$val"
		echo "off=$off"
		echo "at=$at"
		echo "offmask=$offmask"
		echo "shift=$shift"
		#exit 1
	}
}

run_tc ip df set 0
prove 0xffffffff 0xffbfffff 4
prove 0x00400000 0x00000000 4
prove 0xffbfffff 0xffbfffff 4
prove 0x00000000 0x00000000 4

run_tc ip df set 0x40
prove 0xffffffff 0xffffffff 4
prove 0x00400000 0x00400000 4
prove 0xffbfffff 0xffffffff 4
prove 0x00000000 0x00400000 4

run_tc ip df preserve
prove 0xffffffff 0xffffffff 4
prove 0x00400000 0x00400000 4
prove 0xffbfffff 0xffbfffff 4
prove 0x00000000 0x00000000 4

run_tc ip df invert
prove 0xffffffff 0xffbfffff 4
prove 0x00400000 0x00000000 4
prove 0xffbfffff 0xffffffff 4
prove 0x00000000 0x00400000 4

run_tc ip mf set 0x20
prove 0xfffff2ff 0xfffff2ff 4
prove 0x00203000 0x00203000 4
prove 0xfadfffff 0xfaffffff 4
prove 0x00000000 0x00200000 4

run_tc ip ihl set 0x04
prove 0xffffffff 0xfffffff4 0
prove 0x00000005 0x00000004 0
prove 0xfffffff0 0xfffffff4 0
prove 0x00000000 0x00000004 0

run_tc ip tos set 0
prove 0xffffffff 0xffff00ff 0
prove 0x00002300 0x00000000 0
prove 0xffff00ff 0xffff00ff 0
prove 0x00000000 0x00000000 0

run_tc ip tos set 17
prove 0xffffffff 0xffff11ff 0
prove 0x00002300 0x00001100 0
prove 0xffff00ff 0xffff11ff 0
prove 0x00000000 0x00001100 0

run_tc ip tos invert
prove 0xffffffff 0xffff00ff 0
prove 0x00002300 0x0000DC00 0
prove 0xffff00ff 0xffffffff 0
prove 0x00000000 0x0000ff00 0

run_tc ip tos preserve
prove 0xffffffff 0xffffffff 0
prove 0x00002300 0x00002300 0
prove 0xffff00ff 0xffff00ff 0
prove 0x00000000 0x00000000 0

run_tc ip tos clear
prove 0xffffffff 0xffff00ff 0
prove 0x00002300 0x00000000 0
prove 0xffff00ff 0xffff00ff 0
prove 0x00000000 0x00000000 0

run_tc ip dport set 0
prove 0xffffffff 0x0000ffff 20
prove 0x12340000 0x00000000 20
prove 0x0000ffff 0x0000ffff 20
prove 0x00000000 0x00000000 20

run_tc ip dport set 27374
prove 0xfffff22f 0xee6af22f 20
prove 0x12340010 0xee6a0010 20
prove 0xee6aff0f 0xee6aff0f 20
prove 0xee6a0000 0xee6a0000 20

run_tc ip dport invert
prove 0xffffffff 0x0000ffff 20
prove 0x12340000 0xEDCB0000 20
prove 0x00000000 0xffff0000 20

run_tc ip dport preserve
prove 0xffffffff 0xffffffff 20
prove 0x12340000 0x12340000 20
prove 0xee6affff 0xee6affff 20
prove 0xee6a0000 0xee6a0000 20

run_tc ip dport clear
prove 0xffff3fff 0x00003fff 20
prove 0x12340030 0x00000030 20
prove 0xee6af1ff 0x0000f1ff 20
prove 0x00000000 0x00000000 20


run_tc ip src set 0.0.0.0
prove 0xffff3fff 0x00000000 12
prove 0x12340030 0x00000000 12
prove 0xee6af1ff 0x00000000 12
prove 0x00000000 0x00000000 12

run_tc ip src set 1.2.3.4
prove 0xffff3fff 0x01020304 12
prove 0x12340030 0x01020304 12
prove 0xee6af1ff 0x01020304 12
prove 0x00000000 0x01020304 12

run_tc ip src clear
prove 0xffff3fff 0x00000000 12
prove 0x12340030 0x00000000 12
prove 0xee6af1ff 0x00000000 12
prove 0x00000000 0x00000000 12

run_tc ip src preserve
prove 0xffff3fff 0xffff3fff 12
prove 0x12340030 0x12340030 12
prove 0xee6af1ff 0xee6af1ff 12
prove 0x00000000 0x00000000 12

run_tc ip src invert
prove 0xffff3fff 0x0000c000 12
prove 0x12340030 0xedcbffcf 12
prove 0xee6af1ff 0x11950e00 12
prove 0x00000000 0xffffffff 12
--------------------------8<-----------------------------------------

Phil Sutter (3):
  tc: pedit: Fix layered op parsing
  tc: pedit: Fix parse_cmd()
  tc: pedit: Fix retain value for ihl adjustments

 tc/m_pedit.c | 24 ++++++++----------------
 tc/p_ip.c    |  2 +-
 2 files changed, 9 insertions(+), 17 deletions(-)

Comments

stephen hemminger March 2, 2016, 5:54 p.m. UTC | #1
On Wed, 2 Mar 2016 11:20:31 +0000
Phil Sutter <phil@nwl.cc> wrote:

> +		res = parse_cmd(&argc, &argv, 1, TU32,0x0f,sel,tkey);
>  		goto done;
Please add whitespace after ,
Jamal Hadi Salim March 3, 2016, 2:21 p.m. UTC | #2
On 16-03-02 12:54 PM, Stephen Hemminger wrote:
> On Wed, 2 Mar 2016 11:20:31 +0000
> Phil Sutter <phil@nwl.cc> wrote:
>
>> +		res = parse_cmd(&argc, &argv, 1, TU32,0x0f,sel,tkey);
>>   		goto done;
> Please add whitespace after ,
>

There are a few whitespace issues in that code that would be nice to fix
given the cleanup opportunity.
The patches look good to me. Phil, maybe get rid of that comment at the
top which was worrying about endianness. I think you fixed it.

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

Your tests in patch 0 are nice and could go in tests/ directory.
I can send you some of the basic tests i run via the kernel; they look
something of the form:

#
#RFC
#dst MAC starts at -14
#src MAC at -8
#ethertype at -2
#
#
tc filter add dev eth0 parent ffff: protocol ip prio 10 u32 \
match ip src 192.168.1.10/32 flowid 1:2 \
action pedit munge offset -14 u16 set 0x0000 \
munge offset -12 u32 set 0x00010100 \
munge offset -8 u32 set 0x0aaf0100 \
munge offset -4 u32 set 0x0008ec06 pipe \
action mirred egress redirect dev eth1
#
#

These would of course require more of a larger setup to vet
and running tcpdump to check the correct bytes are being
modified.

cheers,
jamal
Jamal Hadi Salim March 3, 2016, 2:28 p.m. UTC | #3
Phil, there is one thing i noticed in your patch - dont think
it is a big deal but you are doing htons on an int
(instead of u16).

cheers,
jamal

On 16-03-03 09:21 AM, Jamal Hadi Salim wrote:
> On 16-03-02 12:54 PM, Stephen Hemminger wrote:
>> On Wed, 2 Mar 2016 11:20:31 +0000
>> Phil Sutter <phil@nwl.cc> wrote:
>>
>>> +        res = parse_cmd(&argc, &argv, 1, TU32,0x0f,sel,tkey);
>>>           goto done;
>> Please add whitespace after ,
>>
>
> There are a few whitespace issues in that code that would be nice to fix
> given the cleanup opportunity.
> The patches look good to me. Phil, maybe get rid of that comment at the
> top which was worrying about endianness. I think you fixed it.
>
> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
>
> Your tests in patch 0 are nice and could go in tests/ directory.
> I can send you some of the basic tests i run via the kernel; they look
> something of the form:
>
> #
> #RFC
> #dst MAC starts at -14
> #src MAC at -8
> #ethertype at -2
> #
> #
> tc filter add dev eth0 parent ffff: protocol ip prio 10 u32 \
> match ip src 192.168.1.10/32 flowid 1:2 \
> action pedit munge offset -14 u16 set 0x0000 \
> munge offset -12 u32 set 0x00010100 \
> munge offset -8 u32 set 0x0aaf0100 \
> munge offset -4 u32 set 0x0008ec06 pipe \
> action mirred egress redirect dev eth1
> #
> #
>
> These would of course require more of a larger setup to vet
> and running tcpdump to check the correct bytes are being
> modified.
>
> cheers,
> jamal
Phil Sutter March 3, 2016, 2:32 p.m. UTC | #4
Hi,

On Thu, Mar 03, 2016 at 09:21:23AM -0500, Jamal Hadi Salim wrote:
> On 16-03-02 12:54 PM, Stephen Hemminger wrote:
> > On Wed, 2 Mar 2016 11:20:31 +0000
> > Phil Sutter <phil@nwl.cc> wrote:
> >
> >> +		res = parse_cmd(&argc, &argv, 1, TU32,0x0f,sel,tkey);
> >>   		goto done;
> > Please add whitespace after ,
> >
> 
> There are a few whitespace issues in that code that would be nice to fix
> given the cleanup opportunity.

In v2, I added a separate patch which makes that file conform to
checkpatch.pl (used the --fix-inplace option and tweaked the output a
bit). So that should be fine already.

> The patches look good to me. Phil, maybe get rid of that comment at the
> top which was worrying about endianness. I think you fixed it.

I'm not so sure. The kernel explicitly takes care to get the bit
ordering right:

| struct iphdr
|   {
| #if __BYTE_ORDER == __LITTLE_ENDIAN
|     unsigned int ihl:4;
|     unsigned int version:4;
| #elif __BYTE_ORDER == __BIG_ENDIAN
|     unsigned int version:4;
|     unsigned int ihl:4;
| #else
| # error "Please fix <bits/endian.h>"
| #endif

act_pedit though just mangles the whole byte as-is, and if that was
correct, we would not have to go that extra mile in struct iphdr, or do
we?

> Your tests in patch 0 are nice and could go in tests/ directory.
> I can send you some of the basic tests i run via the kernel; they look
> something of the form:
> 
> #
> #RFC
> #dst MAC starts at -14
> #src MAC at -8
> #ethertype at -2
> #
> #
> tc filter add dev eth0 parent ffff: protocol ip prio 10 u32 \
> match ip src 192.168.1.10/32 flowid 1:2 \
> action pedit munge offset -14 u16 set 0x0000 \
> munge offset -12 u32 set 0x00010100 \
> munge offset -8 u32 set 0x0aaf0100 \
> munge offset -4 u32 set 0x0008ec06 pipe \
> action mirred egress redirect dev eth1
> #
> #
> 
> These would of course require more of a larger setup to vet
> and running tcpdump to check the correct bytes are being
> modified.

Since I am lazy, I wanted to have as much automation as possible while
testing. Therefore I just assumed that act_pedit does the right thing
all the time, and iproute just has to feed it correct values. Given the
scope of this patch, this is also completely sufficient. Of course, the
tests/ directory would benefit more from a full test. But since
automation then becomes tricky, I'm not sure it makes much sense to
deliberately write code for that.

Thanks for the review,

Phil
Phil Sutter March 3, 2016, 2:54 p.m. UTC | #5
On Thu, Mar 03, 2016 at 09:28:27AM -0500, Jamal Hadi Salim wrote:
> Phil, there is one thing i noticed in your patch - dont think
> it is a big deal but you are doing htons on an int
> (instead of u16).

Indeed, I totally overlooked that. Does not look like there's an easy
fix though, as all tc_pedit_key fields are u32. OTOH htons() will cast
to u16 first, therefore cutting off any higher bits. Looks like the code
does the right thing anyway, and the test results fortify that.

Do you see a cleaner way to implement this? Otherwise I would vote for
leaving it as a little surprise to future readers. ;)

Cheers, Phil
Jamal Hadi Salim March 7, 2016, 11:21 a.m. UTC | #6
On 16-03-03 09:32 AM, Phil Sutter wrote:
> Hi,
>

>
>> The patches look good to me. Phil, maybe get rid of that comment at the
>> top which was worrying about endianness. I think you fixed it.
>
> I'm not so sure. The kernel explicitly takes care to get the bit
> ordering right:
>
[..]
> act_pedit though just mangles the whole byte as-is, and if that was
> correct, we would not have to go that extra mile in struct iphdr, or do
> we?
>

I meant in general - the note to say that there are endianes issues
should go.


>> These would of course require more of a larger setup to vet
>> and running tcpdump to check the correct bytes are being
>> modified.
>

Indeed - That is how i normally would test. It is more complex.
Your scheme is good - but will not catch a kernel bug.

> Since I am lazy, I wanted to have as much automation as possible while
> testing. Therefore I just assumed that act_pedit does the right thing
> all the time,

famous last words ;->

> and iproute just has to feed it correct values. Given the
> scope of this patch, this is also completely sufficient. Of course, the
> tests/ directory would benefit more from a full test. But since
> automation then becomes tricky, I'm not sure it makes much sense to
> deliberately write code for that.
>

Your test is still useful and i think should go into the tests dir.

cheers,
jamal

> Thanks for the review,
>
> Phil
>
Phil Sutter March 7, 2016, 12:57 p.m. UTC | #7
Hi,

On Mon, Mar 07, 2016 at 06:21:17AM -0500, Jamal Hadi Salim wrote:
> On 16-03-03 09:32 AM, Phil Sutter wrote:
> >> The patches look good to me. Phil, maybe get rid of that comment at the
> >> top which was worrying about endianness. I think you fixed it.
> >
> > I'm not so sure. The kernel explicitly takes care to get the bit
> > ordering right:
> >
> [..]
> > act_pedit though just mangles the whole byte as-is, and if that was
> > correct, we would not have to go that extra mile in struct iphdr, or do
> > we?
> >
> 
> I meant in general - the note to say that there are endianes issues
> should go.

Sorry, I didn't get that yet: To me it looks as if on a big-endian
system, the code will actually change the Version field instead of IHL.
Probably the proof of the pudding is in the eating, so I'll try to get
access to a big-endian system for testing.

> >> These would of course require more of a larger setup to vet
> >> and running tcpdump to check the correct bytes are being
> >> modified.
> >
> 
> Indeed - That is how i normally would test. It is more complex.
> Your scheme is good - but will not catch a kernel bug.

Sure. OTOH the algorithm in act_pedit is not overly complex. Plus,
fixing one side only prevents accidental workarounds of other side's
bugs.

> > Since I am lazy, I wanted to have as much automation as possible while
> > testing. Therefore I just assumed that act_pedit does the right thing
> > all the time,
> 
> famous last words ;->

:)

> > and iproute just has to feed it correct values. Given the
> > scope of this patch, this is also completely sufficient. Of course, the
> > tests/ directory would benefit more from a full test. But since
> > automation then becomes tricky, I'm not sure it makes much sense to
> > deliberately write code for that.
> >
> 
> Your test is still useful and i think should go into the tests dir.

OK, I'll give it a thought.

Thanks, Phil
diff mbox

Patch

--- a/tc/m_pedit.c
+++ b/tc/m_pedit.c
@@ -513,6 +513,12 @@  parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, stru
                }
        }
 
+       fprintf(stderr, "mask=0x%x\n", sel.keys[0].mask);
+       fprintf(stderr, "val=0x%x\n", sel.keys[0].val);
+       fprintf(stderr, "off=0x%x\n", sel.keys[0].off);
+       fprintf(stderr, "at=0x%x\n", sel.keys[0].at);
+       fprintf(stderr, "offmask=0x%x\n", sel.keys[0].offmask);
+       fprintf(stderr, "shift=0x%x\n", sel.keys[0].shift);
        tail = NLMSG_TAIL(n);
        addattr_l(n, MAX_MSG, tca_id, NULL, 0);
        addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS,&sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_pedit_key));