mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2024-11-16 14:35:34 +08:00
a2de651e64
In ingress and clsact qdisc TCA_OPTIONS are ignored, since it's parameterless. In tc, we add an empty addattr_l(... TCA_OPTIONS, NULL, 0) to the netlink message nevertheless. This has the side effect that when someone tries a 'tc qdisc replace' and already an existing such qdisc is present, tc fails with EINVAL here. Reason is that in the kernel, this invokes qdisc_change() when such requested qdisc is already present. When TCA_OPTIONS are passed to modify parameters, it looks whether qdisc implements .change() callback, and if not present (like in both cases here) it returns with error. Rather than adding an empty stub to the kernel that ignores TCA_OPTIONS again, just don't add TCA_OPTIONS to the netlink message in the first place. Before: # tc qdisc replace dev foo clsact # first try # tc qdisc replace dev foo clsact # second one RTNETLINK answers: Invalid argument After: # tc qdisc replace dev foo clsact # tc qdisc replace dev foo clsact # tc qdisc replace dev foo clsact Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
52 lines
1.1 KiB
C
52 lines
1.1 KiB
C
/*
|
|
* q_ingress.c INGRESS.
|
|
*
|
|
* This program is free software; you can redistribute 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: J Hadi Salim
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "utils.h"
|
|
#include "tc_util.h"
|
|
|
|
static void explain(void)
|
|
{
|
|
fprintf(stderr, "Usage: ... ingress\n");
|
|
}
|
|
|
|
static int ingress_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|
struct nlmsghdr *n)
|
|
{
|
|
while (argc > 0) {
|
|
if (strcmp(*argv, "handle") == 0) {
|
|
NEXT_ARG();
|
|
argc--; argv++;
|
|
} else {
|
|
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
|
explain();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ingress_print_opt(struct qdisc_util *qu, FILE *f,
|
|
struct rtattr *opt)
|
|
{
|
|
fprintf(f, "---------------- ");
|
|
return 0;
|
|
}
|
|
|
|
struct qdisc_util ingress_qdisc_util = {
|
|
.id = "ingress",
|
|
.parse_qopt = ingress_parse_opt,
|
|
.print_qopt = ingress_print_opt,
|
|
};
|