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 Link: https://lore.kernel.org/netdev/20241004101335.117711-1-daniel@xxxxxxxxxxxxx/ Signed-off-by: Jordan Rife <jordan@xxxxxxxx> --- ip/iplink_netkit.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/ip/iplink_netkit.c b/ip/iplink_netkit.c index 49550a2e..f2c6e699 100644 --- a/ip/iplink_netkit.c +++ b/ip/iplink_netkit.c @@ -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, -- 2.43.0