Merge branch 'main' into next

Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
David Ahern 2021-08-04 09:24:12 -06:00
commit 09d8ce3db1
8 changed files with 130 additions and 42 deletions

View File

@ -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));

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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),

View File

@ -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]) {

View File

@ -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"