diff mbox

[iproute2,net,3/8] tc/pedit: Introduce 'add' operation

Message ID 20170423125356.1298-4-amir@vadai.me
State Accepted, archived
Delegated to: stephen hemminger
Headers show

Commit Message

Amir Vadai April 23, 2017, 12:53 p.m. UTC
This command could be useful to increase/decrease fields value.

Signed-off-by: Amir Vadai <amir@vadai.me>
---
 man/man8/tc-pedit.8 | 13 ++++++++++++-
 tc/m_pedit.c        | 18 +++++++++++++++---
 2 files changed, 27 insertions(+), 4 deletions(-)

Comments

Jamal Hadi Salim April 23, 2017, 5:44 p.m. UTC | #1
Thanks for the excellent work.

On 17-04-23 08:53 AM, Amir Vadai wrote:
> This command could be useful to increase/decrease fields value.
>

Does this contradict the "retain" feature? Example rule to
retain the second nibble but set the first to 0xA
(essentially it X-ORs):
tc filter add dev lo parent ffff: protocol ip prio 10 \
u32 match ip dst 127.0.0.1/32 flowid 1:1 \
action pedit munge offset 0 u8 set 0x0A retain 0xF0

Mostly curious about hardware handling.

cheers,
jamal
Amir Vadai April 24, 2017, 7:52 a.m. UTC | #2
On Sun, Apr 23, 2017 at 01:44:51PM -0400, Jamal Hadi Salim wrote:
> 
> Thanks for the excellent work.
> 
> On 17-04-23 08:53 AM, Amir Vadai wrote:
> > This command could be useful to increase/decrease fields value.
> > 
> 
> Does this contradict the "retain" feature? Example rule to
> retain the second nibble but set the first to 0xA
> (essentially it X-ORs):
> tc filter add dev lo parent ffff: protocol ip prio 10 \
> u32 match ip dst 127.0.0.1/32 flowid 1:1 \
> action pedit munge offset 0 u8 set 0x0A retain 0xF0

You mean, for example increasing a single nible in an ipv4 address?
If so, then it should work:
# tc filter add dev veth0 parent ffff:  u32 \
    match ip dport 23 0xffff \
		action pedit ex \
		  munge ip src add 1.0.0.0 retain 0xff000000

# tc -s filter show dev veth0 parent ffff:
filter protocol all pref 49151 u32
filter protocol all pref 49151 u32 fh 801: ht divisor 1
filter protocol all pref 49151 u32 fh 801::800 order 2048 key ht 801 bkt 0 terminal flowid ???  (rule hit 0 success 0)
  match 00000017/0000ffff at 20 (success 0 )
	action order 1:  pedit action pass keys 1
 	 index 48 ref 1 bind 1 installed 1 sec used 1 sec
	 key #0  at ipv4+12: add 01000000 mask 00ffffff
 	Action statistics:
	Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
	backlog 0b 0p requeues 0

> 
> Mostly curious about hardware handling.
As to hardware handling, Or did the implementation so he will answer
better. AFAIK, current implementation doesn't allow partial field
setting/adding, so such a rule can't be offloaded. I think it is only to
make things simple and because there was no use case for that.
To my knowledge, hardware should support such thing if needed.

Amir

> 
> cheers,
> jamal
>
Or Gerlitz April 24, 2017, 11:04 a.m. UTC | #3
On Mon, Apr 24, 2017 at 10:52 AM, Amir Vadai <amir@vadai.me> wrote:
> On Sun, Apr 23, 2017 at 01:44:51PM -0400, Jamal Hadi Salim wrote:
>> Thanks for the excellent work.

sure, it's Amir, you know..

>> On 17-04-23 08:53 AM, Amir Vadai wrote:

>> Mostly curious about hardware handling.

> As to hardware handling, Or did the implementation so he will answer
> better. AFAIK, current implementation doesn't allow partial field
> setting/adding, so such a rule can't be offloaded. I think it is only to
> make things simple and because there was no use case for that.
> To my knowledge, hardware should support such thing if needed.

yeah (currently no partial setting) and yeah (in the future yes, will
support partial setting of offset into
field and partial length to set from there) and no for partial addition.

The reason we decided to disallow partial addition in the FW API was
what do you do with the carry, e.g you
add a value to the 2nd nibble of IP address and there are carry bits,
where do you take them? this becomes
even more ugly if you are dealing with mac addresses. I guess once
there's use case for partial add offload,
we will revisit that.

Or.
diff mbox

Patch

diff --git a/man/man8/tc-pedit.8 b/man/man8/tc-pedit.8
index 761d5c8ee2d5..6bba741956f1 100644
--- a/man/man8/tc-pedit.8
+++ b/man/man8/tc-pedit.8
@@ -43,6 +43,8 @@  pedit - generic packet editor action
 .IR CMD_SPEC " := {"
 .BR clear " | " invert " | " set
 .IR VAL " | "
+.BR add
+.IR VAL " | "
 .BR preserve " } [ " retain
 .IR RVAL " ]"
 
@@ -63,7 +65,9 @@  only for IPv4 headers.
 .B ex
 Use extended pedit.
 .I EXTENDED_LAYERED_OP
-is allowed only in this mode.
+and the add
+.I CMD_SPEC
+are allowed only in this mode.
 .TP
 .BI offset " OFFSET " "\fR{ \fBu32 \fR| \fBu16 \fR| \fBu8 \fR}"
 Specify the offset at which to change data.
@@ -173,6 +177,13 @@  keywords in
 or the size of the addressed header field in
 .IR LAYERED_OP .
 .TP
+.BI add " VAL"
+Add the addressed data by a specific value. The size of
+.I VAL
+is defined by the size of the addressed header field in
+.IR EXTENDED_LAYERED_OP .
+This operation is supported only for extended layered op.
+.TP
 .B preserve
 Keep the addressed data as is.
 .TP
diff --git a/tc/m_pedit.c b/tc/m_pedit.c
index a26fd3e5bc5e..7af074a5a97c 100644
--- a/tc/m_pedit.c
+++ b/tc/m_pedit.c
@@ -41,7 +41,7 @@  static void explain(void)
 		"\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n"
 		"\t\tNOTE: offval is byte offset, must be multiple of 4\n"
 		"\t\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a shift value\n"
-		"\t\tCMD:= clear | invert | set <setval>| retain\n"
+		"\t\tCMD:= clear | invert | set <setval>| add <addval> | retain\n"
 		"\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n"
 		" \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n"
 		"\tCONTROL:= reclassify | pipe | drop | continue | pass\n"
@@ -276,7 +276,16 @@  int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
 
 	if (matches(*argv, "invert") == 0) {
 		val = mask = o;
-	} else if (matches(*argv, "set") == 0) {
+	} else if (matches(*argv, "set") == 0 ||
+		   matches(*argv, "add") == 0) {
+		if (matches(*argv, "add") == 0)
+			tkey->cmd = TCA_PEDIT_KEY_EX_CMD_ADD;
+
+		if (!sel->extended && tkey->cmd) {
+			fprintf(stderr, "Non extended mode. only 'set' command is supported\n");
+			return -1;
+		}
+
 		NEXT_ARG();
 		if (parse_val(&argc, &argv, &val, type))
 			return -1;
@@ -690,9 +699,11 @@  int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
 		for (i = 0; i < sel->nkeys; i++, key++) {
 			enum pedit_header_type htype =
 				TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK;
+			enum pedit_cmd cmd = TCA_PEDIT_KEY_EX_CMD_SET;
 
 			if (keys_ex) {
 				htype = key_ex->htype;
+				cmd = key_ex->cmd;
 
 				key_ex++;
 			}
@@ -703,7 +714,8 @@  int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
 
 			print_pedit_location(f, htype, key->off);
 
-			fprintf(f, ": val %08x mask %08x",
+			fprintf(f, ": %s %08x mask %08x",
+				cmd ? "add" : "val",
 				(unsigned int)ntohl(key->val),
 				(unsigned int)ntohl(key->mask));
 		}