ip: link: netkit: Support scrub options

Add "scrub" option to configure IFLA_NETKIT_SCRUB and
IFLA_NETKIT_PEER_SCRUB when setting up a link. Add "scrub" and
"peer scrub" to device details as well when printing.

$ sudo ./ip/ip link add jordan type netkit scrub default peer scrub none
$ ./ip/ip -details link show jordan
43: jordan@nk0: <BROADCAST,MULTICAST,NOARP,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff promiscuity 0 allmulti 0 minmtu 68 maxmtu 65535
    netkit mode l3 type primary policy forward peer policy forward scrub default peer scrub none numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 524280 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536

v2->v3: Updated man page.
v1->v2: Added some spaces around "scrub SCRUB" in the help message.

Link: https://lore.kernel.org/netdev/20241004101335.117711-1-daniel@iogearbox.net/

Signed-off-by: Jordan Rife <jordan@jrife.io>
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
Jordan Rife
2025-02-26 09:06:13 -08:00
committed by David Ahern
parent aca230f0f5
commit 3eddcf2dfc
2 changed files with 60 additions and 1 deletions

View File

@@ -24,13 +24,19 @@ static const char * const netkit_policy_strings[] = {
[NETKIT_DROP] = "blackhole",
};
static const char * const netkit_scrub_strings[] = {
[NETKIT_SCRUB_NONE] = "none",
[NETKIT_SCRUB_DEFAULT] = "default",
};
static void explain(struct link_util *lu, FILE *f)
{
fprintf(f,
"Usage: ... %s [ mode MODE ] [ POLICY ] [ peer [ POLICY <options> ] ]\n"
"Usage: ... %s [ mode MODE ] [ POLICY ] [ scrub SCRUB ] [ peer [ POLICY <options> ] ]\n"
"\n"
"MODE: l3 | l2\n"
"POLICY: forward | blackhole\n"
"SCRUB: default | none\n"
"(first values are the defaults if nothing is specified)\n"
"\n"
"To get <options> type 'ip link add help'.\n",
@@ -91,6 +97,23 @@ static int netkit_parse_opt(struct link_util *lu, int argc, char **argv,
if (seen_peer)
duparg("peer", *(argv + 1));
seen_peer = true;
} else if (strcmp(*argv, "scrub") == 0) {
int attr_name = seen_peer ?
IFLA_NETKIT_PEER_SCRUB :
IFLA_NETKIT_SCRUB;
enum netkit_scrub scrub;
NEXT_ARG();
if (strcmp(*argv, "none") == 0) {
scrub = NETKIT_SCRUB_NONE;
} else if (strcmp(*argv, "default") == 0) {
scrub = NETKIT_SCRUB_DEFAULT;
} else {
fprintf(stderr, "Error: scrub must be either \"none\" or \"default\"\n");
return -1;
}
addattr32(n, 1024, attr_name, scrub);
} else {
char *type = NULL;
@@ -144,6 +167,15 @@ static const char *netkit_print_mode(__u32 mode)
return netkit_mode_strings[mode] ? : inv;
}
static const char *netkit_print_scrub(enum netkit_scrub scrub)
{
const char *inv = "UNKNOWN";
if (scrub >= ARRAY_SIZE(netkit_scrub_strings))
return inv;
return netkit_scrub_strings[scrub] ? : inv;
}
static void netkit_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
@@ -172,6 +204,18 @@ static void netkit_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
print_string(PRINT_ANY, "peer_policy", "peer policy %s ",
netkit_print_policy(policy));
}
if (tb[IFLA_NETKIT_SCRUB]) {
enum netkit_scrub scrub = rta_getattr_u32(tb[IFLA_NETKIT_SCRUB]);
print_string(PRINT_ANY, "scrub", "scrub %s ",
netkit_print_scrub(scrub));
}
if (tb[IFLA_NETKIT_PEER_SCRUB]) {
enum netkit_scrub scrub = rta_getattr_u32(tb[IFLA_NETKIT_PEER_SCRUB]);
print_string(PRINT_ANY, "peer_scrub", "peer scrub %s ",
netkit_print_scrub(scrub));
}
}
static void netkit_print_help(struct link_util *lu,

View File

@@ -882,10 +882,14 @@ the following additional arguments are supported:
[
.BI mode " MODE "
] [
.BI scrub " SCRUB "
] [
.I "POLICY "
] [
.BR peer
[
.BI scrub " SCRUB "
] [
.I "POLICY "
] [
.I "NAME "
@@ -898,6 +902,17 @@ the following additional arguments are supported:
- specifies the operation mode of the netkit device with "l3" and "l2"
as possible values. Default option is "l3".
.sp
.BI scrub " SCRUB"
- specifies the scrub behavior of the netkit device with "default" and
"none" as possible values. With "default" the device zeroes the
skb->{mark,priority} fields before invoking the attached BPF program
when its peer device resides in a different network namespace. With
"none" the device leaves clearing skb->{mark,priority} up to the BPF
program. Default option is "default". Specifying scrub before the peer
option refers to the primary device, after the peer option refers to
the peer device.
.sp
.I "POLICY"
- specifies the default device policy when no BPF programs are attached