mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-04 21:40:34 +00:00
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:
commit
e9625d6aea
3
README
3
README
@ -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/
|
||||
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
*/
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
7
ip/ip.c
7
ip/ip.c
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
*/
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
19
lib/utils.c
19
lib/utils.c
@ -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 "???";
|
||||
}
|
||||
|
@ -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),
|
||||
|
78
man/man8/devlink-resource.8
Normal file
78
man/man8/devlink-resource.8
Normal 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>
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
||||
|
21
misc/ss.c
21
misc/ss.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user