tc: pedit: add decrement operation

Implement a decrement operation for ttl and hoplimit.

Since this is just syntactic sugar, it goes that:

  tc filter add ... action pedit ex munge ip ttl dec ...
  tc filter add ... action pedit ex munge ip6 hoplimit dec ...

is just a more readable version of this:

  tc filter add ... action pedit ex munge ip ttl add 0xff ...
  tc filter add ... action pedit ex munge ip6 hoplimit add 0xff ...

This feature was suggested by some pseudo tc examples in Mellanox's
documentation[1], but wasn't present in neither their mlnx-iproute2
nor iproute2.

Tested with skip_sw on Mellanox ConnectX-6 Dx.

[1] https://docs.mellanox.com/pages/viewpage.action?pageId=47033989

v3:
   - Use dedicated flags argument in parse_cmd() (David Ahern)
   - Minor rewording of the man page

v2:
   - Fix whitespace issue (Stephen Hemminger)
   - Add to usage info in explain()

Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.st>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
Asbjørn Sloth Tønnesen 2021-06-18 16:06:35 +00:00 committed by David Ahern
parent bc5e8473aa
commit 2ff4761db4
5 changed files with 32 additions and 9 deletions

View File

@ -77,6 +77,7 @@ pedit - generic packet editor action
.IR VAL " | " .IR VAL " | "
.BR add .BR add
.IR VAL " | " .IR VAL " | "
.BR decrement " | "
.BR preserve " } [ " retain .BR preserve " } [ " retain
.IR RVAL " ]" .IR RVAL " ]"
@ -96,7 +97,7 @@ chosen automatically based on the header field size.
.B ex .B ex
Use extended pedit. Use extended pedit.
.I EXTENDED_LAYERED_OP .I EXTENDED_LAYERED_OP
and the add and the add/decrement
.I CMD_SPEC .I CMD_SPEC
are allowed only in this mode. are allowed only in this mode.
.TP .TP
@ -288,6 +289,11 @@ is defined by the size of the addressed header field in
.IR EXTENDED_LAYERED_OP . .IR EXTENDED_LAYERED_OP .
This operation is supported only for extended layered op. This operation is supported only for extended layered op.
.TP .TP
.BI decrement
Decrease the addressed data by one.
This operation is supported only for
.BR ip " " ttl " and " ip6 " " hoplimit "."
.TP
.B preserve .B preserve
Keep the addressed data as is. Keep the addressed data as is.
.TP .TP

View File

@ -41,7 +41,7 @@ static void explain(void)
"\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n" "\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n"
"\t\tNOTE: offval is byte offset, must be multiple of 4\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\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a shift value\n"
"\t\tCMD:= clear | invert | set <setval>| add <addval> | retain\n" "\t\tCMD:= clear | invert | set <setval> | add <addval> | decrement | retain\n"
"\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n" "\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n"
" \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n" " \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n"
"\tCONTROL:= reclassify | pipe | drop | continue | pass |\n" "\tCONTROL:= reclassify | pipe | drop | continue | pass |\n"
@ -360,15 +360,24 @@ int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
if (matches(*argv, "add") == 0) if (matches(*argv, "add") == 0)
tkey->cmd = TCA_PEDIT_KEY_EX_CMD_ADD; tkey->cmd = TCA_PEDIT_KEY_EX_CMD_ADD;
if (!sel->extended && tkey->cmd) { if (!sel->extended && tkey->cmd)
fprintf(stderr, goto non_ext_only_set_cmd;
"Non extended mode. only 'set' command is supported\n");
return -1;
}
NEXT_ARG(); NEXT_ARG();
if (parse_val(&argc, &argv, val, type)) if (parse_val(&argc, &argv, val, type))
return -1; return -1;
} else if (matches(*argv, "decrement") == 0) {
if ((flags & PEDIT_ALLOW_DEC) == 0) {
fprintf(stderr,
"decrement command is not supported for this field\n");
return -1;
}
if (!sel->extended)
goto non_ext_only_set_cmd;
tkey->cmd = TCA_PEDIT_KEY_EX_CMD_ADD;
*v = retain; /* decrement by overflow */
} else if (matches(*argv, "preserve") == 0) { } else if (matches(*argv, "preserve") == 0) {
retain = 0; retain = 0;
} else { } else {
@ -431,6 +440,10 @@ done:
*argv_p = argv; *argv_p = argv;
return res; return res;
non_ext_only_set_cmd:
fprintf(stderr,
"Non extended mode. only 'set' command is supported\n");
return -1;
} }
static int parse_offset(int *argc_p, char ***argv_p, struct m_pedit_sel *sel, static int parse_offset(int *argc_p, char ***argv_p, struct m_pedit_sel *sel,

View File

@ -39,6 +39,10 @@
#define PEDITKINDSIZ 16 #define PEDITKINDSIZ 16
enum m_pedit_flags {
PEDIT_ALLOW_DEC = 1<<0,
};
struct m_pedit_key { struct m_pedit_key {
__u32 mask; /* AND */ __u32 mask; /* AND */
__u32 val; /*XOR */ __u32 val; /*XOR */

View File

@ -68,7 +68,7 @@ parse_ip(int *argc_p, char ***argv_p,
if (strcmp(*argv, "ttl") == 0) { if (strcmp(*argv, "ttl") == 0) {
NEXT_ARG(); NEXT_ARG();
tkey->off = 8; tkey->off = 8;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0); res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, PEDIT_ALLOW_DEC);
goto done; goto done;
} }
if (strcmp(*argv, "protocol") == 0) { if (strcmp(*argv, "protocol") == 0) {

View File

@ -71,7 +71,7 @@ parse_ip6(int *argc_p, char ***argv_p,
if (strcmp(*argv, "hoplimit") == 0) { if (strcmp(*argv, "hoplimit") == 0) {
NEXT_ARG(); NEXT_ARG();
tkey->off = 7; tkey->off = 7;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0); res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, PEDIT_ALLOW_DEC);
goto done; goto done;
} }
if (strcmp(*argv, "traffic_class") == 0) { if (strcmp(*argv, "traffic_class") == 0) {