Merge branch 'iproute2-master' into iproute2-next

Conflicts:
	bridge/mdb.c

Updated bridge/bridge.c per removal of check_if_color_enabled by commit
1ca4341d2c ("color: disable color when json output is requested")

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2018-03-13 17:48:10 -07:00
commit e9625d6aea
40 changed files with 1016 additions and 130 deletions

3
README
View File

@ -1,5 +1,8 @@
This is a set of utilities for Linux networking.
Information:
https://wiki.linuxfoundation.org/networking/iproute2
Download:
http://www.kernel.org/pub/linux/utils/net/iproute2/

View File

@ -200,8 +200,8 @@ main(int argc, char **argv)
_SL_ = oneline ? "\\" : "\n";
if (json)
check_if_color_enabled();
if (color && !json)
enable_color();
if (batch_file)
return batch(batch_file);

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,8 @@
#include <libmnl/libmnl.h>
#include <linux/genetlink.h>
#include "libnetlink.h"
#include "utils.h"
#include "mnlg.h"
struct mnlg_socket {
@ -60,6 +62,39 @@ int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
}
static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
{
return MNL_CB_OK;
}
static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
{
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
/* Netlink subsystems returns the errno value with different signess */
if (err->error < 0)
errno = -err->error;
else
errno = err->error;
if (nl_dump_ext_ack(nlh, NULL))
return MNL_CB_ERROR;
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
}
static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
{
return MNL_CB_STOP;
}
static mnl_cb_t mnlg_cb_array[NLMSG_MIN_TYPE] = {
[NLMSG_NOOP] = mnlg_cb_noop,
[NLMSG_ERROR] = mnlg_cb_error,
[NLMSG_DONE] = mnlg_cb_stop,
[NLMSG_OVERRUN] = mnlg_cb_noop,
};
int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
{
int err;
@ -69,8 +104,9 @@ int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
MNL_SOCKET_BUFFER_SIZE);
if (err <= 0)
break;
err = mnl_cb_run(nlg->buf, err, nlg->seq, nlg->portid,
data_cb, data);
err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
data_cb, data, mnlg_cb_array,
ARRAY_SIZE(mnlg_cb_array));
} while (err > 0);
return err;
@ -220,6 +256,7 @@ struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
{
struct mnlg_socket *nlg;
struct nlmsghdr *nlh;
int one = 1;
int err;
nlg = malloc(sizeof(*nlg));
@ -234,6 +271,16 @@ struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
if (!nlg->nl)
goto err_mnl_socket_open;
err = mnl_socket_setsockopt(nlg->nl, NETLINK_CAP_ACK, &one,
sizeof(one));
if (err)
goto err_mnl_set_ack;
err = mnl_socket_setsockopt(nlg->nl, NETLINK_EXT_ACK, &one,
sizeof(one));
if (err)
goto err_mnl_set_ext_ack;
err = mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID);
if (err < 0)
goto err_mnl_socket_bind;
@ -258,6 +305,8 @@ struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
err_mnlg_socket_recv_run:
err_mnlg_socket_send:
err_mnl_socket_bind:
err_mnl_set_ext_ack:
err_mnl_set_ack:
mnl_socket_close(nlg->nl);
err_mnl_socket_open:
free(nlg->buf);

View File

@ -13,7 +13,6 @@ enum color_attr {
};
void enable_color(void);
void check_if_color_enabled(void);
void set_color_palette(void);
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
enum color_attr ifa_family_color(__u8 ifa_family);

View File

@ -1,14 +1,10 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
/*
* Simple streaming JSON writer
*
* This takes care of the annoying bits of JSON syntax like the commas
* after elements
*
* 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: Stephen Hemminger <stephen@networkplumber.org>
*/

View File

@ -109,6 +109,7 @@ int rtnl_send(struct rtnl_handle *rth, const void *buf, int)
__attribute__((warn_unused_result));
int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int)
__attribute__((warn_unused_result));
int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn);
int addattr(struct nlmsghdr *n, int maxlen, int type);
int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data);

View File

@ -108,6 +108,11 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
n->pprev = &h->first;
}
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos ; pos = pos->next)

View File

@ -172,6 +172,7 @@ int main(int argc, char **argv)
{
char *basename;
char *batch_file = NULL;
int color = 0;
basename = strrchr(argv[0], '/');
if (basename == NULL)
@ -271,7 +272,7 @@ int main(int argc, char **argv)
}
rcvbuf = size;
} else if (matches(opt, "-color") == 0) {
enable_color();
++color;
} else if (matches(opt, "-help") == 0) {
usage();
} else if (matches(opt, "-netns") == 0) {
@ -291,8 +292,8 @@ int main(int argc, char **argv)
_SL_ = oneline ? "\\" : "\n";
if (json)
check_if_color_enabled();
if (color && !json)
enable_color();
if (batch_file)
return batch(batch_file);

View File

@ -416,10 +416,10 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
}
if (vf_tx_rate->rate)
print_int(PRINT_ANY,
"tx_rate",
", tx rate %d (Mbps)",
vf_tx_rate->rate);
print_uint(PRINT_ANY,
"tx_rate",
", tx rate %u (Mbps)",
vf_tx_rate->rate);
if (vf[IFLA_VF_RATE]) {
struct ifla_vf_rate *vf_rate = RTA_DATA(vf[IFLA_VF_RATE]);
@ -428,14 +428,14 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
if (is_json_context()) {
open_json_object("rate");
print_int(PRINT_JSON, "max_tx", NULL, max_tx);
print_int(PRINT_ANY, "min_tx", NULL, min_tx);
print_uint(PRINT_JSON, "max_tx", NULL, max_tx);
print_uint(PRINT_ANY, "min_tx", NULL, min_tx);
close_json_object();
} else {
if (max_tx)
fprintf(fp, ", max_tx_rate %dMbps", max_tx);
fprintf(fp, ", max_tx_rate %uMbps", max_tx);
if (min_tx)
fprintf(fp, ", min_tx_rate %dMbps", min_tx);
fprintf(fp, ", min_tx_rate %uMbps", min_tx);
}
}

View File

@ -275,8 +275,9 @@ static int nl_get_ll_addr_len(unsigned int dev_index)
return -1;
}
len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
free(answer);
return RTA_PAYLOAD(tb[IFLA_ADDRESS]);
return len;
}
static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp,

View File

@ -2039,6 +2039,7 @@ static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) {
fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n",
ioff);
fprintf(stderr, " - Current section: %s\n", data_relo->sec_name);
if (ioff < num_insns &&
insns[ioff].code == (BPF_JMP | BPF_CALL))
fprintf(stderr, " - Try to annotate functions with always_inline attribute!\n");

View File

@ -92,14 +92,6 @@ void set_color_palette(void)
is_dark_bg = 1;
}
void check_if_color_enabled(void)
{
if (color_is_enabled) {
fprintf(stderr, "Option \"-json\" conflicts with \"-color\".\n");
exit(1);
}
}
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
{
int ret = 0;

View File

@ -1,14 +1,10 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
/*
* Simple streaming JSON writer
*
* This takes care of the annoying bits of JSON syntax like the commas
* after elements
*
* 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: Stephen Hemminger <stephen@networkplumber.org>
*/

View File

@ -65,7 +65,7 @@ static int err_attr_cb(const struct nlattr *attr, void *data)
}
/* dump netlink extended ack error message */
static int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
{
struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
@ -120,7 +120,7 @@ static int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
#warning "libmnl required for error support"
/* No extended error ack without libmnl */
static int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
{
return 0;
}
@ -670,8 +670,9 @@ next:
free(buf);
if (h->nlmsg_seq == seq)
return 0;
else
else if (i < iovlen)
goto next;
return 0;
}
if (rtnl->proto != NETLINK_SOCK_DIAG &&

View File

@ -7,6 +7,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <sys/statvfs.h>
#include <fcntl.h>
#include <dirent.h>
#include <limits.h>
@ -46,6 +47,8 @@ int netns_switch(char *name)
{
char net_path[PATH_MAX];
int netns;
unsigned long mountflags = 0;
struct statvfs fsstat;
snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
netns = open(net_path, O_RDONLY | O_CLOEXEC);
@ -73,12 +76,25 @@ int netns_switch(char *name)
strerror(errno));
return -1;
}
/* Mount a version of /sys that describes the network namespace */
if (umount2("/sys", MNT_DETACH) < 0) {
fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
if (statvfs("/sys", &fsstat) < 0) {
fprintf(stderr, "could not stat /sys (not mounted?): %s\n",strerror(errno));
return -1;
}
if (mount(name, "/sys", "sysfs", 0, NULL) < 0) {
if (fsstat.f_flag & ST_RDONLY) {
/* If /sys is not writable (e.g. in a container), we can't
* unmount the old /sys instance, but we can still mount a new
* read-only instance over it. */
mountflags = MS_RDONLY;
} else {
if (umount2("/sys", MNT_DETACH) < 0) {
fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
return -1;
}
}
if (mount(name, "/sys", "sysfs", mountflags, NULL) < 0) {
fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno));
return -1;
}

View File

@ -1010,6 +1010,25 @@ const char *rt_addr_n2a_r(int af, int len,
}
case AF_PACKET:
return ll_addr_n2a(addr, len, ARPHRD_VOID, buf, buflen);
case AF_BRIDGE:
{
const union {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} *sa = addr;
switch (sa->sa.sa_family) {
case AF_INET:
return inet_ntop(AF_INET, &sa->sin.sin_addr,
buf, buflen);
case AF_INET6:
return inet_ntop(AF_INET6, &sa->sin6.sin6_addr,
buf, buflen);
}
/* fallthrough */
}
default:
return "???";
}

View File

@ -42,6 +42,10 @@ devlink-dev \- devlink device configuration
.BR "devlink dev eswitch show"
.IR DEV
.ti -8
.BR "devlink dev reload"
.IR DEV
.SH "DESCRIPTION"
.SS devlink dev show - display devlink device attributes
@ -94,6 +98,12 @@ Set eswitch encapsulation support
.I enable
- Enable encapsulation support
.SS devlink dev reload - perform hot reload of the driver.
.PP
.I "DEV"
- Specifies the devlink device to reload.
.SH "EXAMPLES"
.PP
devlink dev show
@ -114,6 +124,11 @@ Shows the eswitch mode of specified devlink device.
devlink dev eswitch set pci/0000:01:00.0 mode switchdev
.RS 4
Sets the eswitch mode of specified devlink device to switchdev.
.RE
.PP
devlink dev reload pci/0000:01:00.0
.RS 4
Performs hot reload of specified devlink device.
.SH SEE ALSO
.BR devlink (8),

View File

@ -0,0 +1,78 @@
.TH DEVLINK\-RESOURCE 8 "11 Feb 2018" "iproute2" "Linux"
.SH NAME
devlink-resource \- devlink device resource configuration
.SH SYNOPSIS
.sp
.ad l
.in +8
.ti -8
.B devlink
.RI "[ " OPTIONS " ]"
.B resource
.RI " { " COMMAND " | "
.BR help " }"
.sp
.ti -8
.IR OPTIONS " := { "
\fB\-v\fR[\fIerbose\fR] }
.ti -8
.B devlink resource show
.IR DEV
.ti -8
.B devlink resource help
.ti -8
.BR "devlink resource set"
.IR DEV
.BI path " RESOURCE_PATH"
.BI size " RESOURCE_SIZE"
.SH "DESCRIPTION"
.SS devlink resource show - display devlink device's resosources
.PP
.I "DEV"
- specifies the devlink device to show.
.in +4
Format is:
.in +2
BUS_NAME/BUS_ADDRESS
.SS devlink resource set - sets resource size of specific resource
.PP
.I "DEV"
- specifies the devlink device.
.TP
.BI path " RESOURCE_PATH"
Resource's path.
.TP
.BI size " RESOURCE_SIZE"
The new resource's size.
.SH "EXAMPLES"
.PP
devlink resource show pci/0000:01:00.0
.RS 4
Shows the resources of the specified devlink device.
.RE
.PP
devlink resource set pci/0000:01:00.0 /kvd/linear 98304
.RS 4
Sets the size of the specified resource for the specified devlink device.
.SH SEE ALSO
.BR devlink (8),
.BR devlink-port (8),
.BR devlink-sb (8),
.BR devlink-monitor (8),
.br
.SH AUTHOR
Arkadi Sharshevsky <arkadis@mellanox.com>

View File

@ -103,6 +103,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
.BR devlink-port (8),
.BR devlink-monitor (8),
.BR devlink-sb (8),
.BR devlink-resource (8),
.br
.SH REPORTING BUGS

View File

@ -14,6 +14,10 @@ CLS_NAME ] [
UDS_FILE ] [
.B verbose
] [
.B direct-action
|
.B da
] [
.B skip_hw
|
.B skip_sw
@ -141,6 +145,11 @@ if set, it will dump the eBPF verifier output, even if loading the eBPF
program was successful. By default, only on error, the verifier log is
being emitted to the user.
.SS direct-action | da
instructs eBPF classifier to not invoke external TC actions, instead use the
TC actions return codes (\fBTC_ACT_OK\fR, \fBTC_ACT_SHOT\fR etc.) for
classifiers.
.SS skip_hw | skip_sw
hardware offload control flags. By default TC will try to offload
filters to hardware if possible.

View File

@ -81,13 +81,21 @@ tc \- show / manipulate traffic control settings
.B filter show block
\fIBLOCK_INDEX\fR
.P
.B tc
.RI "[ " OPTIONS " ]"
.B monitor [ file
\fIFILENAME\fR
.B ]
.P
.ti 8
.IR OPTIONS " := {"
\fB[ -force ] -b\fR[\fIatch\fR] \fB[ filename ] \fR|
\fB[ \fB-n\fR[\fIetns\fR] name \fB] \fR|
\fB[ \fB-nm \fR| \fB-nam\fR[\fIes\fR] \fB] \fR|
\fB[ \fR{ \fB-cf \fR| \fB-c\fR[\fIonf\fR] \fR} \fB[ filename ] \fB] \fR}
\fB[ \fR{ \fB-cf \fR| \fB-c\fR[\fIonf\fR] \fR} \fB[ filename ] \fB] \fR
\fB[ -t\fR[imestamp\fR] \fB\] \fR| \fB[ -t\fR[short\fR] \fB]\fR }
.ti 8
.IR FORMAT " := {"
@ -617,6 +625,17 @@ link
Only available for qdiscs and performs a replace where the node
must exist already.
.SH MONITOR
The\fB\ tc\fR\ utility can monitor events generated by the kernel such as
adding/deleting qdiscs, filters or actions, or modifying existing ones.
The following command is available for\fB\ monitor\fR\ :
.TP
\fBfile\fR
If the file option is given, the \fBtc\fR does not listen to kernel events, but opens
the given file and dumps its contents. The file has to be in binary
format and contain netlink messages.
.SH OPTIONS
.TP
@ -654,6 +673,16 @@ to
specifies path to the config file. This option is used in conjunction with other options (e.g.
.BR -nm ")."
.TP
.BR "\-t", " \-timestamp"
When\fB\ tc monitor\fR\ runs, print timestamp before the event message in format:
Timestamp: <Day> <Month> <DD> <hh:mm:ss> <YYYY> <usecs> usec
.TP
.BR "\-ts", " \-tshort"
When\fB\ tc monitor\fR\ runs, prints short timestamp before the event message in format:
[<YYYY>-<MM>-<DD>T<hh:mm:ss>.<ms>]
.SH FORMAT
The show command has additional formatting options:

View File

@ -239,6 +239,7 @@ struct filter {
uint64_t families;
struct ssfilter *f;
bool kill;
struct rtnl_handle *rth_for_killing;
};
#define FAMILY_MASK(family) ((uint64_t)1 << (family))
@ -1196,10 +1197,15 @@ newline:
/* Render buffered output with spacing and delimiters, then free up buffers */
static void render(int screen_width)
{
struct buf_token *token = (struct buf_token *)buffer.head->data;
struct buf_token *token;
int printed, line_started = 0;
struct column *f;
if (!buffer.head)
return;
token = (struct buf_token *)buffer.head->data;
/* Ensure end alignment of last token, it wasn't necessarily flushed */
buffer.tail->end += buffer.cur->len % 2;
@ -4265,6 +4271,7 @@ static int generic_show_sock(const struct sockaddr_nl *addr,
switch (r->sdiag_family) {
case AF_INET:
case AF_INET6:
inet_arg.rth = inet_arg.f->rth_for_killing;
return show_one_inet_sock(addr, nlh, &inet_arg);
case AF_UNIX:
return unix_show_sock(addr, nlh, arg);
@ -4283,7 +4290,7 @@ static int handle_follow_request(struct filter *f)
{
int ret = 0;
int groups = 0;
struct rtnl_handle rth;
struct rtnl_handle rth, rth2;
if (f->families & FAMILY_MASK(AF_INET) && f->dbs & (1 << TCP_DB))
groups |= 1 << (SKNLGRP_INET_TCP_DESTROY - 1);
@ -4303,10 +4310,20 @@ static int handle_follow_request(struct filter *f)
rth.dump = 0;
rth.local.nl_pid = 0;
if (f->kill) {
if (rtnl_open_byproto(&rth2, groups, NETLINK_SOCK_DIAG)) {
rtnl_close(&rth);
return -1;
}
f->rth_for_killing = &rth2;
}
if (rtnl_dump_filter(&rth, generic_show_sock, f))
ret = -1;
rtnl_close(&rth);
if (f->rth_for_killing)
rtnl_close(f->rth_for_killing);
return ret;
}

View File

@ -395,8 +395,10 @@ static int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data)
comm = get_task_name(pid);
}
if (rd_check_is_filtered(rd, "pid", pid))
if (rd_check_is_filtered(rd, "pid", pid)) {
free(comm);
continue;
}
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
/* discard const from mnl_attr_get_str */

View File

@ -365,7 +365,7 @@ tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts)
return tc_print_action_flush(f, tb[0]);
open_json_array(PRINT_JSON, "actions");
for (i = 0; i < tot_acts; i++) {
for (i = 0; i <= tot_acts; i++) {
if (tb[i]) {
open_json_object(NULL);
print_uint(PRINT_ANY, "order",

View File

@ -128,7 +128,6 @@ opt_bpf:
parse_action_control_dflt(&argc, &argv, &parm.action,
false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {

View File

@ -82,7 +82,6 @@ parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
}
parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {

View File

@ -124,7 +124,6 @@ parse_csum(struct action_util *a, int *argc_p,
}
parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_OK);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {

View File

@ -87,12 +87,10 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
if (argc < 0)
return -1;
if (matches(*argv, "gact") != 0 &&
parse_action_control(&argc, &argv, &p.action, false) == -1) {
if (!matches(*argv, "gact"))
NEXT_ARG_FWD();
if (parse_action_control(&argc, &argv, &p.action, false))
usage(); /* does not return */
}
NEXT_ARG_FWD();
#ifdef CONFIG_GACT_PROB
if (argc > 0) {
@ -113,7 +111,6 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p,
if (parse_action_control(&argc, &argv,
&pp.paction, false) == -1)
usage();
NEXT_ARG_FWD();
if (get_u16(&pp.pval, *argv, 10)) {
fprintf(stderr,
"Illegal probability val 0x%x\n",

View File

@ -159,7 +159,6 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -103,6 +103,7 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
while (argc > 0) {
if (matches(*argv, "action") == 0) {
NEXT_ARG();
break;
} else if (!egress && matches(*argv, "egress") == 0) {
egress = 1;
@ -200,10 +201,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
}
if (p.eaction == TCA_EGRESS_MIRROR || p.eaction == TCA_INGRESS_MIRROR) {
if (p.eaction == TCA_EGRESS_MIRROR || p.eaction == TCA_INGRESS_MIRROR)
parse_action_control(&argc, &argv, &p.action, false);
NEXT_ARG_FWD();
}
if (argc) {
if (iok && matches(*argv, "index") == 0) {

View File

@ -116,7 +116,6 @@ parse_nat(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct
parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_OK);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -672,7 +672,6 @@ int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
parse_action_control_dflt(&argc, &argv, &sel.sel.action, false, TC_ACT_OK);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -150,15 +150,18 @@ int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
matches(*argv, "shot") == 0 ||
matches(*argv, "continue") == 0 ||
matches(*argv, "pass") == 0 ||
matches(*argv, "ok") == 0 ||
matches(*argv, "pipe") == 0 ||
matches(*argv, "goto") == 0) {
if (parse_action_control(&argc, &argv, &p.action, false))
return -1;
if (!parse_action_control(&argc, &argv, &p.action, false))
goto action_ctrl_ok;
return -1;
} else if (strcmp(*argv, "conform-exceed") == 0) {
NEXT_ARG();
if (parse_action_control_slash(&argc, &argv, &p.action,
&presult, true))
return -1;
if (!parse_action_control_slash(&argc, &argv, &p.action,
&presult, true))
goto action_ctrl_ok;
return -1;
} else if (matches(*argv, "overhead") == 0) {
NEXT_ARG();
if (get_u16(&overhead, *argv, 10)) {
@ -174,8 +177,9 @@ int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
} else {
break;
}
NEXT_ARG_FWD();
action_ctrl_ok:
ok++;
argc--; argv++;
}
if (!ok)

View File

@ -100,7 +100,6 @@ static int parse_sample(struct action_util *a, int *argc_p, char ***argv_p,
parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -123,7 +123,6 @@ parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
parse_action_control_dflt(&argc, &argv, &sel.action,
false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -124,7 +124,6 @@ static int parse_skbmod(struct action_util *a, int *argc_p, char ***argv_p,
parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -174,7 +174,6 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
parse_action_control_dflt(&argc, &argv, &parm.action,
false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -131,7 +131,6 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
parse_action_control_dflt(&argc, &argv, &parm.action,
false, TC_ACT_PIPE);
NEXT_ARG_FWD();
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();

View File

@ -599,6 +599,7 @@ static int __parse_action_control(int *argc_p, char ***argv_p, int *result_p,
}
result |= jump_cnt;
}
NEXT_ARG_FWD();
*argc_p = argc;
*argv_p = argv;
*result_p = result;
@ -695,8 +696,8 @@ out:
int parse_action_control_slash(int *argc_p, char ***argv_p,
int *result1_p, int *result2_p, bool allow_num)
{
int result1, result2, argc = *argc_p;
char **argv = *argv_p;
int result1, result2;
char *p = strchr(*argv, '/');
if (!p)
@ -715,6 +716,9 @@ int parse_action_control_slash(int *argc_p, char ***argv_p,
*result1_p = result1;
*result2_p = result2;
NEXT_ARG_FWD();
*argc_p = argc;
*argv_p = argv;
return 0;
}