Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
commit
09d8ce3db1
|
|
@ -109,6 +109,27 @@ struct rtnl_ctrl_data {
|
|||
|
||||
typedef int (*rtnl_filter_t)(struct nlmsghdr *n, void *);
|
||||
|
||||
/**
|
||||
* rtnl error handler called from
|
||||
* rtnl_dump_done()
|
||||
* rtnl_dump_error()
|
||||
*
|
||||
* Return value is a bitmask of the following values:
|
||||
* RTNL_LET_NLERR
|
||||
* error handled as usual
|
||||
* RTNL_SUPPRESS_NLMSG_DONE_NLERR
|
||||
* error in nlmsg_type == NLMSG_DONE will be suppressed
|
||||
* RTNL_SUPPRESS_NLMSG_ERROR_NLERR
|
||||
* error in nlmsg_type == NLMSG_ERROR will be suppressed
|
||||
* and nlmsg will be skipped
|
||||
* RTNL_SUPPRESS_NLERR - suppress error in both previous cases
|
||||
*/
|
||||
#define RTNL_LET_NLERR 0x01
|
||||
#define RTNL_SUPPRESS_NLMSG_DONE_NLERR 0x02
|
||||
#define RTNL_SUPPRESS_NLMSG_ERROR_NLERR 0x04
|
||||
#define RTNL_SUPPRESS_NLERR 0x06
|
||||
typedef int (*rtnl_err_hndlr_t)(struct nlmsghdr *n, void *);
|
||||
|
||||
typedef int (*rtnl_listen_filter_t)(struct rtnl_ctrl_data *,
|
||||
struct nlmsghdr *n, void *);
|
||||
|
||||
|
|
@ -118,6 +139,8 @@ typedef int (*nl_ext_ack_fn_t)(const char *errmsg, uint32_t off,
|
|||
struct rtnl_dump_filter_arg {
|
||||
rtnl_filter_t filter;
|
||||
void *arg1;
|
||||
rtnl_err_hndlr_t errhndlr;
|
||||
void *arg2;
|
||||
__u16 nc_flags;
|
||||
};
|
||||
|
||||
|
|
@ -126,6 +149,15 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth,
|
|||
void *arg, __u16 nc_flags);
|
||||
#define rtnl_dump_filter(rth, filter, arg) \
|
||||
rtnl_dump_filter_nc(rth, filter, arg, 0)
|
||||
int rtnl_dump_filter_errhndlr_nc(struct rtnl_handle *rth,
|
||||
rtnl_filter_t filter,
|
||||
void *arg1,
|
||||
rtnl_err_hndlr_t errhndlr,
|
||||
void *arg2,
|
||||
__u16 nc_flags);
|
||||
#define rtnl_dump_filter_errhndlr(rth, filter, farg, errhndlr, earg) \
|
||||
rtnl_dump_filter_errhndlr_nc(rth, filter, farg, errhndlr, earg, 0)
|
||||
|
||||
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
||||
struct nlmsghdr **answer)
|
||||
__attribute__((warn_unused_result));
|
||||
|
|
|
|||
15
ip/iproute.c
15
ip/iproute.c
|
|
@ -1735,6 +1735,18 @@ static int iproute_flush(int family, rtnl_filter_t filter_fn)
|
|||
}
|
||||
}
|
||||
|
||||
static int save_route_errhndlr(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
int err = -*(int *)NLMSG_DATA(n);
|
||||
|
||||
if (n->nlmsg_type == NLMSG_DONE &&
|
||||
filter.tb == RT_TABLE_MAIN &&
|
||||
err == ENOENT)
|
||||
return RTNL_SUPPRESS_NLMSG_DONE_NLERR;
|
||||
|
||||
return RTNL_LET_NLERR;
|
||||
}
|
||||
|
||||
static int iproute_list_flush_or_save(int argc, char **argv, int action)
|
||||
{
|
||||
int dump_family = preferred_family;
|
||||
|
|
@ -1947,7 +1959,8 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
|
|||
|
||||
new_json_obj(json);
|
||||
|
||||
if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
|
||||
if (rtnl_dump_filter_errhndlr(&rth, filter_fn, stdout,
|
||||
save_route_errhndlr, NULL) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,10 +268,12 @@ static int load_bpf_object(struct bpf_cfg_in *cfg)
|
|||
}
|
||||
|
||||
bpf_object__for_each_program(p, obj) {
|
||||
bool prog_to_attach = !prog && cfg->section &&
|
||||
!strcmp(get_bpf_program__section_name(p), cfg->section);
|
||||
|
||||
/* Only load the programs that will either be subsequently
|
||||
* attached or inserted into a tail call map */
|
||||
if (find_legacy_tail_calls(p, obj) < 0 && cfg->section &&
|
||||
strcmp(get_bpf_program__section_name(p), cfg->section)) {
|
||||
if (find_legacy_tail_calls(p, obj) < 0 && !prog_to_attach) {
|
||||
ret = bpf_program__set_autoload(p, false);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
|
@ -280,7 +282,8 @@ static int load_bpf_object(struct bpf_cfg_in *cfg)
|
|||
|
||||
bpf_program__set_type(p, cfg->type);
|
||||
bpf_program__set_ifindex(p, cfg->ifindex);
|
||||
if (!prog)
|
||||
|
||||
if (prog_to_attach)
|
||||
prog = p;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -718,7 +718,8 @@ int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n)
|
|||
return sendmsg(rth->fd, &msg, 0);
|
||||
}
|
||||
|
||||
static int rtnl_dump_done(struct nlmsghdr *h)
|
||||
static int rtnl_dump_done(struct nlmsghdr *h,
|
||||
const struct rtnl_dump_filter_arg *a)
|
||||
{
|
||||
int len = *(int *)NLMSG_DATA(h);
|
||||
|
||||
|
|
@ -728,11 +729,15 @@ static int rtnl_dump_done(struct nlmsghdr *h)
|
|||
}
|
||||
|
||||
if (len < 0) {
|
||||
errno = -len;
|
||||
|
||||
if (a->errhndlr && (a->errhndlr(h, a->arg2) & RTNL_SUPPRESS_NLMSG_DONE_NLERR))
|
||||
return 0;
|
||||
|
||||
/* check for any messages returned from kernel */
|
||||
if (nl_dump_ext_ack_done(h, len))
|
||||
return len;
|
||||
|
||||
errno = -len;
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case EOPNOTSUPP:
|
||||
|
|
@ -753,8 +758,9 @@ static int rtnl_dump_done(struct nlmsghdr *h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rtnl_dump_error(const struct rtnl_handle *rth,
|
||||
struct nlmsghdr *h)
|
||||
static int rtnl_dump_error(const struct rtnl_handle *rth,
|
||||
struct nlmsghdr *h,
|
||||
const struct rtnl_dump_filter_arg *a)
|
||||
{
|
||||
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
|
||||
|
|
@ -766,11 +772,16 @@ static void rtnl_dump_error(const struct rtnl_handle *rth,
|
|||
if (rth->proto == NETLINK_SOCK_DIAG &&
|
||||
(errno == ENOENT ||
|
||||
errno == EOPNOTSUPP))
|
||||
return;
|
||||
return -1;
|
||||
|
||||
if (a->errhndlr && (a->errhndlr(h, a->arg2) & RTNL_SUPPRESS_NLMSG_ERROR_NLERR))
|
||||
return 0;
|
||||
|
||||
if (!(rth->flags & RTNL_HANDLE_F_SUPPRESS_NLERR))
|
||||
perror("RTNETLINK answers");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __rtnl_recvmsg(int fd, struct msghdr *msg, int flags)
|
||||
|
|
@ -879,7 +890,7 @@ static int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|||
dump_intr = 1;
|
||||
|
||||
if (h->nlmsg_type == NLMSG_DONE) {
|
||||
err = rtnl_dump_done(h);
|
||||
err = rtnl_dump_done(h, a);
|
||||
if (err < 0) {
|
||||
free(buf);
|
||||
return -1;
|
||||
|
|
@ -890,9 +901,13 @@ static int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|||
}
|
||||
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
rtnl_dump_error(rth, h);
|
||||
free(buf);
|
||||
return -1;
|
||||
err = rtnl_dump_error(rth, h, a);
|
||||
if (err < 0) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
goto skip_it;
|
||||
}
|
||||
|
||||
if (!rth->dump_fp) {
|
||||
|
|
@ -928,12 +943,34 @@ skip_it:
|
|||
}
|
||||
|
||||
int rtnl_dump_filter_nc(struct rtnl_handle *rth,
|
||||
rtnl_filter_t filter,
|
||||
void *arg1, __u16 nc_flags)
|
||||
rtnl_filter_t filter,
|
||||
void *arg1, __u16 nc_flags)
|
||||
{
|
||||
const struct rtnl_dump_filter_arg a[2] = {
|
||||
{ .filter = filter, .arg1 = arg1, .nc_flags = nc_flags, },
|
||||
{ .filter = NULL, .arg1 = NULL, .nc_flags = 0, },
|
||||
const struct rtnl_dump_filter_arg a[] = {
|
||||
{
|
||||
.filter = filter, .arg1 = arg1,
|
||||
.nc_flags = nc_flags,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
return rtnl_dump_filter_l(rth, a);
|
||||
}
|
||||
|
||||
int rtnl_dump_filter_errhndlr_nc(struct rtnl_handle *rth,
|
||||
rtnl_filter_t filter,
|
||||
void *arg1,
|
||||
rtnl_err_hndlr_t errhndlr,
|
||||
void *arg2,
|
||||
__u16 nc_flags)
|
||||
{
|
||||
const struct rtnl_dump_filter_arg a[] = {
|
||||
{
|
||||
.filter = filter, .arg1 = arg1,
|
||||
.errhndlr = errhndlr, .arg2 = arg2,
|
||||
.nc_flags = nc_flags,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
return rtnl_dump_filter_l(rth, a);
|
||||
|
|
@ -1138,16 +1175,16 @@ int rtnl_listen(struct rtnl_handle *rtnl,
|
|||
char buf[16384];
|
||||
char cmsgbuf[BUFSIZ];
|
||||
|
||||
if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
|
||||
msg.msg_control = &cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
}
|
||||
|
||||
iov.iov_base = buf;
|
||||
while (1) {
|
||||
struct rtnl_ctrl_data ctrl;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) {
|
||||
msg.msg_control = &cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
}
|
||||
|
||||
iov.iov_len = sizeof(buf);
|
||||
status = recvmsg(rtnl->fd, &msg, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ flag is equivalent to the combination
|
|||
.B It doesn't work. Don't use it.
|
||||
|
||||
.TP
|
||||
.BI encaplim " ELIM"
|
||||
.BI encaplimit " ELIM"
|
||||
.RB ( " only IPv6 tunnels " )
|
||||
set a fixed encapsulation limit. Default is 4.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ skbmod - user-friendly packet editor action
|
|||
.SH SYNOPSIS
|
||||
.in +8
|
||||
.ti -8
|
||||
.BR tc " ... " "action skbmod " "{ [ " "set "
|
||||
.IR SETTABLE " ] [ "
|
||||
.BR tc " ... " "action skbmod " "{ " "set "
|
||||
.IR SETTABLE " | "
|
||||
.BI swap " SWAPPABLE"
|
||||
.RI " ] [ " CONTROL " ] [ "
|
||||
.RI " } [ " CONTROL " ] [ "
|
||||
.BI index " INDEX "
|
||||
] }
|
||||
]
|
||||
|
||||
.ti -8
|
||||
.IR SETTABLE " := "
|
||||
|
|
@ -25,6 +25,7 @@ skbmod - user-friendly packet editor action
|
|||
.IR SWAPPABLE " := "
|
||||
.B mac
|
||||
.ti -8
|
||||
|
||||
.IR CONTROL " := {"
|
||||
.BR reclassify " | " pipe " | " drop " | " shot " | " continue " | " pass " }"
|
||||
.SH DESCRIPTION
|
||||
|
|
@ -48,10 +49,7 @@ Change the source mac to the specified address.
|
|||
Change the ethertype to the specified value.
|
||||
.TP
|
||||
.BI mac
|
||||
Used to swap mac addresses. The
|
||||
.B swap mac
|
||||
directive is performed
|
||||
after any outstanding D/SMAC changes.
|
||||
Used to swap mac addresses.
|
||||
.TP
|
||||
.I CONTROL
|
||||
The following keywords allow to control how the tree of qdisc, classes,
|
||||
|
|
@ -128,9 +126,13 @@ tc filter add dev eth3 parent 1: protocol ip prio 10 \\
|
|||
.EE
|
||||
.RE
|
||||
|
||||
As mentioned above, the swap action will occur after any
|
||||
.B " smac/dmac "
|
||||
substitutions are executed, if they are present.
|
||||
However, trying to
|
||||
.B set
|
||||
and
|
||||
.B swap
|
||||
in a single
|
||||
.B skbmod
|
||||
command will cause undefined behavior.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR tc (8),
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
|
|||
__u64 rate64, prate64;
|
||||
__u64 pps64, ppsburst64;
|
||||
|
||||
print_string(PRINT_ANY, "kind", "%s", "police");
|
||||
print_string(PRINT_JSON, "kind", "%s", "police");
|
||||
if (arg == NULL)
|
||||
return 0;
|
||||
|
||||
|
|
@ -301,7 +301,8 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
|
|||
RTA_PAYLOAD(tb[TCA_POLICE_RATE64]) >= sizeof(rate64))
|
||||
rate64 = rta_getattr_u64(tb[TCA_POLICE_RATE64]);
|
||||
|
||||
print_uint(PRINT_ANY, "index", "\t index %u ", p->index);
|
||||
print_hex(PRINT_FP, NULL, " police 0x%x ", p->index);
|
||||
print_uint(PRINT_JSON, "index", NULL, p->index);
|
||||
tc_print_rate(PRINT_FP, NULL, "rate %s ", rate64);
|
||||
buffer = tc_calc_xmitsize(rate64, p->burst);
|
||||
print_size(PRINT_FP, NULL, "burst %s ", buffer);
|
||||
|
|
@ -342,12 +343,13 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
|
|||
print_string(PRINT_FP, NULL, " ", NULL);
|
||||
}
|
||||
|
||||
print_uint(PRINT_ANY, "overhead", "overhead %u ", p->rate.overhead);
|
||||
print_size(PRINT_ANY, "overhead", "overhead %s ", p->rate.overhead);
|
||||
linklayer = (p->rate.linklayer & TC_LINKLAYER_MASK);
|
||||
if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
|
||||
print_string(PRINT_ANY, "linklayer", "linklayer %s ",
|
||||
sprint_linklayer(linklayer, b2));
|
||||
print_int(PRINT_ANY, "ref", "ref %d ", p->refcnt);
|
||||
print_nl();
|
||||
print_int(PRINT_ANY, "ref", "\tref %d ", p->refcnt);
|
||||
print_int(PRINT_ANY, "bind", "bind %d ", p->bindcnt);
|
||||
if (show_stats) {
|
||||
if (tb[TCA_POLICE_TM]) {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,9 @@
|
|||
static void skbmod_explain(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage:... skbmod {[set <SETTABLE>] [swap <SWAPABLE>]} [CONTROL] [index INDEX]\n"
|
||||
"Usage:... skbmod { set <SETTABLE> | swap <SWAPPABLE> } [CONTROL] [index INDEX]\n"
|
||||
"where SETTABLE is: [dmac DMAC] [smac SMAC] [etype ETYPE]\n"
|
||||
"where SWAPABLE is: \"mac\" to swap mac addresses\n"
|
||||
"note: \"swap mac\" is done after any outstanding D/SMAC change\n"
|
||||
"where SWAPPABLE is: \"mac\" to swap mac addresses\n"
|
||||
"\tDMAC := 6 byte Destination MAC address\n"
|
||||
"\tSMAC := optional 6 byte Source MAC address\n"
|
||||
"\tETYPE := optional 16 bit ethertype\n"
|
||||
|
|
|
|||
Loading…
Reference in New Issue