iproute2/tc/p_ip6.c
Asbjørn Sloth Tønnesen 2ff4761db4 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>
2021-06-26 04:45:19 +00:00

105 lines
2.3 KiB
C

/*
* p_ip6.c packet editor: IPV6 header
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: Amir Vadai <amir@vadai.me>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
#include "m_pedit.h"
static int
parse_ip6(int *argc_p, char ***argv_p,
struct m_pedit_sel *sel, struct m_pedit_key *tkey)
{
int res = -1;
int argc = *argc_p;
char **argv = *argv_p;
if (argc < 2)
return -1;
if (!sel->extended)
return -1;
tkey->htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6;
if (strcmp(*argv, "src") == 0) {
NEXT_ARG();
tkey->off = 8;
res = parse_cmd(&argc, &argv, 16, TIPV6, RU32, sel, tkey, 0);
goto done;
}
if (strcmp(*argv, "dst") == 0) {
NEXT_ARG();
tkey->off = 24;
res = parse_cmd(&argc, &argv, 16, TIPV6, RU32, sel, tkey, 0);
goto done;
}
if (strcmp(*argv, "flow_lbl") == 0) {
NEXT_ARG();
tkey->off = 0;
res = parse_cmd(&argc, &argv, 4, TU32, 0x0007ffff, sel, tkey, 0);
goto done;
}
if (strcmp(*argv, "payload_len") == 0) {
NEXT_ARG();
tkey->off = 4;
res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey, 0);
goto done;
}
if (strcmp(*argv, "nexthdr") == 0) {
NEXT_ARG();
tkey->off = 6;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
goto done;
}
if (strcmp(*argv, "hoplimit") == 0) {
NEXT_ARG();
tkey->off = 7;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, PEDIT_ALLOW_DEC);
goto done;
}
if (strcmp(*argv, "traffic_class") == 0) {
NEXT_ARG();
tkey->off = 1;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
/* Shift the field by 4 bits on success. */
if (!res) {
int nkeys = sel->sel.nkeys;
struct tc_pedit_key *key = &sel->keys[nkeys - 1];
key->mask = htonl(ntohl(key->mask) << 4 | 0xf);
key->val = htonl(ntohl(key->val) << 4);
}
goto done;
}
return -1;
done:
*argc_p = argc;
*argv_p = argv;
return res;
}
struct m_pedit_util p_pedit_ip6 = {
.id = "ip6",
.parse_peopt = parse_ip6,
};