Merge branch 'iproute2-master' into next
Conflicts: misc/ss.c Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
9f78e995a8
|
|
@ -346,8 +346,7 @@ static int fdb_show(int argc, char **argv)
|
|||
if (rth.flags & RTNL_HANDLE_F_STRICT_CHK)
|
||||
rc = rtnl_neighdump_req(&rth, PF_BRIDGE, fdb_dump_filter);
|
||||
else
|
||||
rc = rtnl_linkdump_req_filter_fn(&rth, PF_BRIDGE,
|
||||
fdb_linkdump_filter);
|
||||
rc = rtnl_fdb_linkdump_req_filter_fn(&rth, fdb_linkdump_filter);
|
||||
if (rc < 0) {
|
||||
perror("Cannot send dump request");
|
||||
exit(1);
|
||||
|
|
|
|||
|
|
@ -4525,7 +4525,8 @@ static int dpipe_table_show(struct dpipe_ctx *ctx, struct nlattr *nl)
|
|||
size = mnl_attr_get_u32(nla_table[DEVLINK_ATTR_DPIPE_TABLE_SIZE]);
|
||||
counters_enabled = !!mnl_attr_get_u8(nla_table[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
|
||||
|
||||
resource_valid = !!nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID];
|
||||
resource_valid = nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID] &&
|
||||
ctx->resources;
|
||||
if (resource_valid) {
|
||||
table->resource_id = mnl_attr_get_u64(nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID]);
|
||||
table->resource_valid = true;
|
||||
|
|
@ -4641,12 +4642,9 @@ static int cmd_dpipe_table_show(struct dl *dl)
|
|||
dl_opts_put(nlh, dl);
|
||||
err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_resource_dump_cb,
|
||||
&resource_ctx);
|
||||
if (err) {
|
||||
pr_err("error get resources %s\n", strerror(resource_ctx.err));
|
||||
goto err_resource_dump;
|
||||
}
|
||||
if (!err)
|
||||
dpipe_ctx.resources = resource_ctx.resources;
|
||||
|
||||
dpipe_ctx.resources = resource_ctx.resources;
|
||||
flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_DPIPE_TABLE_GET, flags);
|
||||
dl_opts_put(nlh, dl);
|
||||
|
|
@ -4659,8 +4657,6 @@ static int cmd_dpipe_table_show(struct dl *dl)
|
|||
dpipe_ctx_fini(&dpipe_ctx);
|
||||
return 0;
|
||||
|
||||
err_resource_dump:
|
||||
resource_ctx_fini(&resource_ctx);
|
||||
err_resource_ctx_init:
|
||||
err_headers_get:
|
||||
dpipe_ctx_fini(&dpipe_ctx);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask)
|
|||
int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int fam,
|
||||
req_filter_fn_t fn)
|
||||
__attribute__((warn_unused_result));
|
||||
int rtnl_fdb_linkdump_req_filter_fn(struct rtnl_handle *rth,
|
||||
req_filter_fn_t filter_fn)
|
||||
__attribute__((warn_unused_result));
|
||||
int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask)
|
||||
__attribute__((warn_unused_result));
|
||||
int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req,
|
||||
|
|
|
|||
|
|
@ -137,15 +137,21 @@ enum {
|
|||
INET_DIAG_TCLASS,
|
||||
INET_DIAG_SKMEMINFO,
|
||||
INET_DIAG_SHUTDOWN,
|
||||
INET_DIAG_DCTCPINFO,
|
||||
INET_DIAG_PROTOCOL, /* response attribute only */
|
||||
|
||||
/*
|
||||
* Next extenstions cannot be requested in struct inet_diag_req_v2:
|
||||
* its field idiag_ext has only 8 bits.
|
||||
*/
|
||||
|
||||
INET_DIAG_DCTCPINFO, /* request as INET_DIAG_VEGASINFO */
|
||||
INET_DIAG_PROTOCOL, /* response attribute only */
|
||||
INET_DIAG_SKV6ONLY,
|
||||
INET_DIAG_LOCALS,
|
||||
INET_DIAG_PEERS,
|
||||
INET_DIAG_PAD,
|
||||
INET_DIAG_MARK,
|
||||
INET_DIAG_BBRINFO,
|
||||
INET_DIAG_CLASS_ID,
|
||||
INET_DIAG_MARK, /* only with CAP_NET_ADMIN */
|
||||
INET_DIAG_BBRINFO, /* request as INET_DIAG_VEGASINFO */
|
||||
INET_DIAG_CLASS_ID, /* request as INET_DIAG_TCLASS */
|
||||
INET_DIAG_MD5SIG,
|
||||
__INET_DIAG_MAX,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
|
|||
return;
|
||||
}
|
||||
|
||||
parse_rtattr_nested(vf, IFLA_VF_MAX, vfstats);
|
||||
parse_rtattr_nested(vf, IFLA_VF_STATS_MAX, vfstats);
|
||||
|
||||
if (is_json_context()) {
|
||||
open_json_object("stats");
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void iplink_usage(void)
|
|||
" [ trust { on | off} ] ]\n"
|
||||
" [ node_guid { eui64 } ]\n"
|
||||
" [ port_guid { eui64 } ]\n"
|
||||
" [ xdp { off |\n"
|
||||
" [ { xdp | xdpgeneric | xdpdrv | xdpoffload } { off |\n"
|
||||
" object FILE [ section NAME ] [ verbose ] |\n"
|
||||
" pinned FILE } ]\n"
|
||||
" [ master DEVICE ][ vrf NAME ]\n"
|
||||
|
|
|
|||
|
|
@ -1932,6 +1932,7 @@ static int iproute_get(int argc, char **argv)
|
|||
int fib_match = 0;
|
||||
int from_ok = 0;
|
||||
unsigned int mark = 0;
|
||||
bool address_found = false;
|
||||
|
||||
iproute_reset_filter(0);
|
||||
filter.cloned = 2;
|
||||
|
|
@ -2037,11 +2038,12 @@ static int iproute_get(int argc, char **argv)
|
|||
addattr_l(&req.n, sizeof(req),
|
||||
RTA_DST, &addr.data, addr.bytelen);
|
||||
req.r.rtm_dst_len = addr.bitlen;
|
||||
address_found = true;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (req.r.rtm_dst_len == 0) {
|
||||
if (!address_found) {
|
||||
fprintf(stderr, "need at least a destination address\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux/seg6_iptunnel.h>
|
||||
#include <linux/seg6_hmac.h>
|
||||
#include <linux/seg6_local.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tunnel.h>
|
||||
|
||||
static const char *format_encap_type(int type)
|
||||
{
|
||||
|
|
@ -294,6 +294,7 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap)
|
|||
static void print_encap_ip(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[LWTUNNEL_IP_MAX+1];
|
||||
__u16 flags;
|
||||
|
||||
parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
|
||||
|
||||
|
|
@ -318,6 +319,16 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap)
|
|||
if (tb[LWTUNNEL_IP_TOS])
|
||||
print_uint(PRINT_ANY, "tos",
|
||||
"tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
|
||||
|
||||
if (tb[LWTUNNEL_IP_FLAGS]) {
|
||||
flags = rta_getattr_u16(tb[LWTUNNEL_IP_FLAGS]);
|
||||
if (flags & TUNNEL_KEY)
|
||||
print_bool(PRINT_ANY, "key", "key ", true);
|
||||
if (flags & TUNNEL_CSUM)
|
||||
print_bool(PRINT_ANY, "csum", "csum ", true);
|
||||
if (flags & TUNNEL_SEQ)
|
||||
print_bool(PRINT_ANY, "seq", "seq ", true);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_encap_ila(FILE *fp, struct rtattr *encap)
|
||||
|
|
@ -354,6 +365,7 @@ static void print_encap_ila(FILE *fp, struct rtattr *encap)
|
|||
static void print_encap_ip6(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
|
||||
__u16 flags;
|
||||
|
||||
parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
|
||||
|
||||
|
|
@ -379,6 +391,16 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
|
|||
if (tb[LWTUNNEL_IP6_TC])
|
||||
print_uint(PRINT_ANY, "tc",
|
||||
"tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
|
||||
|
||||
if (tb[LWTUNNEL_IP6_FLAGS]) {
|
||||
flags = rta_getattr_u16(tb[LWTUNNEL_IP6_FLAGS]);
|
||||
if (flags & TUNNEL_KEY)
|
||||
print_bool(PRINT_ANY, "key", "key ", true);
|
||||
if (flags & TUNNEL_CSUM)
|
||||
print_bool(PRINT_ANY, "csum", "csum ", true);
|
||||
if (flags & TUNNEL_SEQ)
|
||||
print_bool(PRINT_ANY, "seq", "seq ", true);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_encap_bpf(FILE *fp, struct rtattr *encap)
|
||||
|
|
@ -777,9 +799,11 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
|
|||
int *argcp, char ***argvp)
|
||||
{
|
||||
int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
|
||||
int key_ok = 0, csum_ok = 0, seq_ok = 0;
|
||||
char **argv = *argvp;
|
||||
int argc = *argcp;
|
||||
int ret = 0;
|
||||
__u16 flags = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "id") == 0) {
|
||||
|
|
@ -827,6 +851,18 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
|
|||
if (get_u8(&ttl, *argv, 0))
|
||||
invarg("\"ttl\" value is invalid\n", *argv);
|
||||
ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
|
||||
} else if (strcmp(*argv, "key") == 0) {
|
||||
if (key_ok++)
|
||||
duparg2("key", *argv);
|
||||
flags |= TUNNEL_KEY;
|
||||
} else if (strcmp(*argv, "csum") == 0) {
|
||||
if (csum_ok++)
|
||||
duparg2("csum", *argv);
|
||||
flags |= TUNNEL_CSUM;
|
||||
} else if (strcmp(*argv, "seq") == 0) {
|
||||
if (seq_ok++)
|
||||
duparg2("seq", *argv);
|
||||
flags |= TUNNEL_SEQ;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -835,6 +871,9 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
|
|||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
ret = rta_addattr16(rta, len, LWTUNNEL_IP_FLAGS, flags);
|
||||
|
||||
/* argv is currently the first unparsed argument,
|
||||
* but the lwt_parse_encap() caller will move to the next,
|
||||
* so step back
|
||||
|
|
@ -927,9 +966,11 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
|
|||
int *argcp, char ***argvp)
|
||||
{
|
||||
int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
|
||||
int key_ok = 0, csum_ok = 0, seq_ok = 0;
|
||||
char **argv = *argvp;
|
||||
int argc = *argcp;
|
||||
int ret = 0;
|
||||
__u16 flags = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "id") == 0) {
|
||||
|
|
@ -979,6 +1020,18 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
|
|||
*argv);
|
||||
ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
|
||||
hoplimit);
|
||||
} else if (strcmp(*argv, "key") == 0) {
|
||||
if (key_ok++)
|
||||
duparg2("key", *argv);
|
||||
flags |= TUNNEL_KEY;
|
||||
} else if (strcmp(*argv, "csum") == 0) {
|
||||
if (csum_ok++)
|
||||
duparg2("csum", *argv);
|
||||
flags |= TUNNEL_CSUM;
|
||||
} else if (strcmp(*argv, "seq") == 0) {
|
||||
if (seq_ok++)
|
||||
duparg2("seq", *argv);
|
||||
flags |= TUNNEL_SEQ;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -987,6 +1040,9 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
|
|||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
ret = rta_addattr16(rta, len, LWTUNNEL_IP6_FLAGS, flags);
|
||||
|
||||
/* argv is currently the first unparsed argument,
|
||||
* but the lwt_parse_encap() caller will move to the next,
|
||||
* so step back
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ int print_rule(struct nlmsghdr *n, void *arg)
|
|||
} else if (frh->action == FR_ACT_NOP) {
|
||||
print_null(PRINT_ANY, "nop", "nop", NULL);
|
||||
} else if (frh->action != FR_ACT_TO_TBL) {
|
||||
print_string(PRINT_ANY, "to_tbl", "%s",
|
||||
print_string(PRINT_ANY, "action", "%s",
|
||||
rtnl_rtntype_n2a(frh->action, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2203,12 +2203,16 @@ static int bpf_btf_prep_type_data(struct bpf_elf_ctx *ctx)
|
|||
case BTF_KIND_ENUM:
|
||||
type_cur += var_len * sizeof(struct btf_enum);
|
||||
break;
|
||||
case BTF_KIND_FUNC_PROTO:
|
||||
type_cur += var_len * sizeof(struct btf_param);
|
||||
break;
|
||||
case BTF_KIND_TYPEDEF:
|
||||
case BTF_KIND_PTR:
|
||||
case BTF_KIND_FWD:
|
||||
case BTF_KIND_VOLATILE:
|
||||
case BTF_KIND_CONST:
|
||||
case BTF_KIND_RESTRICT:
|
||||
case BTF_KIND_FUNC:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Object has unknown BTF type: %u!\n", kind);
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int family,
|
|||
int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int family,
|
||||
req_filter_fn_t filter_fn)
|
||||
{
|
||||
if (family == AF_UNSPEC) {
|
||||
if (family == AF_UNSPEC || family == AF_PACKET) {
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct ifinfomsg ifm;
|
||||
|
|
@ -503,6 +503,29 @@ int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int family,
|
|||
return __rtnl_linkdump_req(rth, family);
|
||||
}
|
||||
|
||||
int rtnl_fdb_linkdump_req_filter_fn(struct rtnl_handle *rth,
|
||||
req_filter_fn_t filter_fn)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct ifinfomsg ifm;
|
||||
char buf[128];
|
||||
} req = {
|
||||
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
|
||||
.nlh.nlmsg_type = RTM_GETNEIGH,
|
||||
.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
|
||||
.nlh.nlmsg_seq = rth->dump = ++rth->seq,
|
||||
.ifm.ifi_family = PF_BRIDGE,
|
||||
};
|
||||
int err;
|
||||
|
||||
err = filter_fn(&req.nlh, sizeof(req));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return send(rth->fd, &req, sizeof(req), 0);
|
||||
}
|
||||
|
||||
int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask)
|
||||
{
|
||||
struct {
|
||||
|
|
@ -695,6 +718,8 @@ static int rtnl_recvmsg(int fd, struct msghdr *msg, char **answer)
|
|||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (len < 32768)
|
||||
len = 32768;
|
||||
buf = malloc(len);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "malloc error: not enough buffer\n");
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ Controls whether a given port will sync MAC addresses learned on device port to
|
|||
bridge FDB.
|
||||
|
||||
.TP
|
||||
.BR "flooding on " or " flooding off "
|
||||
.BR "flood on " or " flood off "
|
||||
Controls whether a given port will flood unicast traffic for which there is no FDB entry. By default this flag is on.
|
||||
|
||||
.TP
|
||||
|
|
@ -361,7 +361,7 @@ switch.
|
|||
|
||||
.TP
|
||||
.BR "mcast_flood on " or " mcast_flood off "
|
||||
Controls whether a given port will be flooded with multicast traffic for which there is no MDB entry. By default this flag is on.
|
||||
Controls whether a given port will flood multicast traffic for which there is no MDB entry. By default this flag is on.
|
||||
|
||||
.TP
|
||||
.BR "neigh_suppress on " or " neigh_suppress off "
|
||||
|
|
|
|||
|
|
@ -2183,7 +2183,7 @@ queries.
|
|||
option above.
|
||||
|
||||
.BR mcast_flood " { " on " | " off " }"
|
||||
- controls whether a given port will be flooded with multicast traffic for which there is no MDB entry.
|
||||
- controls whether a given port will flood multicast traffic for which there is no MDB entry.
|
||||
|
||||
.BI group_fwd_mask " MASK "
|
||||
- set the group forward mask. This is the bitmask that is applied to decide whether to forward incoming frames destined to link-local addresses, ie addresses of the form 01:80:C2:00:00:0X (defaults to 0, ie the bridge does not forward any link-local frames coming on this port).
|
||||
|
|
|
|||
|
|
@ -737,7 +737,8 @@ is a set of encapsulation attributes specific to the
|
|||
.B tos
|
||||
.IR TOS " ] ["
|
||||
.B ttl
|
||||
.IR TTL " ]"
|
||||
.IR TTL " ] [ "
|
||||
.BR key " ] [" csum " ] [ " seq " ] "
|
||||
.in -2
|
||||
.sp
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,23 @@ the pacing rate and max pacing rate
|
|||
a helper variable for TCP internal auto tuning socket receive buffer
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-tos
|
||||
Show ToS and priority information. Below fields may appear:
|
||||
.RS
|
||||
.P
|
||||
.TP
|
||||
.B tos
|
||||
IPv4 Type-of-Service byte
|
||||
.P
|
||||
.TP
|
||||
.B tclass
|
||||
IPv6 Traffic Class byte
|
||||
.P
|
||||
.TP
|
||||
.B class_id
|
||||
Class id set by net_cls cgroup. If class is zero this shows priority set by SO_PRIORITY.
|
||||
.RE
|
||||
.TP
|
||||
.B \-K, \-\-kill
|
||||
Attempts to forcibly close sockets. This option displays sockets that are
|
||||
successfully closed and silently skips sockets that the kernel does not support
|
||||
|
|
|
|||
105
misc/ss.c
105
misc/ss.c
|
|
@ -52,8 +52,17 @@
|
|||
#include <linux/tipc_netlink.h>
|
||||
#include <linux/tipc_sockets_diag.h>
|
||||
|
||||
/* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */
|
||||
#ifndef PF_VSOCK
|
||||
#define PF_VSOCK 40
|
||||
#endif
|
||||
#ifndef AF_VSOCK
|
||||
#define AF_VSOCK PF_VSOCK
|
||||
#endif
|
||||
|
||||
#define MAGIC_SEQ 123456
|
||||
#define BUF_CHUNK (1024 * 1024)
|
||||
#define BUF_CHUNK (1024 * 1024) /* Buffer chunk allocation size */
|
||||
#define BUF_CHUNKS_MAX 5 /* Maximum number of allocated buffer chunks */
|
||||
#define LEN_ALIGN(x) (((x) + 1) & ~1)
|
||||
|
||||
#define DIAG_REQUEST(_req, _r) \
|
||||
|
|
@ -111,6 +120,7 @@ static int show_header = 1;
|
|||
static int follow_events;
|
||||
static int sctp_ino;
|
||||
static int show_tipcinfo;
|
||||
static int show_tos;
|
||||
|
||||
enum col_id {
|
||||
COL_NETID,
|
||||
|
|
@ -176,6 +186,7 @@ static struct {
|
|||
struct buf_token *cur; /* Position of current token in chunk */
|
||||
struct buf_chunk *head; /* First chunk */
|
||||
struct buf_chunk *tail; /* Current chunk */
|
||||
int chunks; /* Number of allocated chunks */
|
||||
} buffer;
|
||||
|
||||
static const char *TCP_PROTO = "tcp";
|
||||
|
|
@ -946,6 +957,8 @@ static struct buf_chunk *buf_chunk_new(void)
|
|||
|
||||
new->end = buffer.cur->data;
|
||||
|
||||
buffer.chunks++;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
|
@ -1090,33 +1103,6 @@ static int field_is_last(struct column *f)
|
|||
return f - columns == COL_MAX - 1;
|
||||
}
|
||||
|
||||
static void field_next(void)
|
||||
{
|
||||
field_flush(current_field);
|
||||
|
||||
if (field_is_last(current_field))
|
||||
current_field = columns;
|
||||
else
|
||||
current_field++;
|
||||
}
|
||||
|
||||
/* Walk through fields and flush them until we reach the desired one */
|
||||
static void field_set(enum col_id id)
|
||||
{
|
||||
while (id != current_field - columns)
|
||||
field_next();
|
||||
}
|
||||
|
||||
/* Print header for all non-empty columns */
|
||||
static void print_header(void)
|
||||
{
|
||||
while (!field_is_last(current_field)) {
|
||||
if (!current_field->disabled)
|
||||
out("%s", current_field->header);
|
||||
field_next();
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the next available token in the buffer starting from the current token */
|
||||
static struct buf_token *buf_token_next(struct buf_token *cur)
|
||||
{
|
||||
|
|
@ -1142,6 +1128,7 @@ static void buf_free_all(void)
|
|||
free(tmp);
|
||||
}
|
||||
buffer.head = NULL;
|
||||
buffer.chunks = 0;
|
||||
}
|
||||
|
||||
/* Get current screen width, default to 80 columns if TIOCGWINSZ fails */
|
||||
|
|
@ -1304,6 +1291,40 @@ static void render(void)
|
|||
current_field = columns;
|
||||
}
|
||||
|
||||
/* Move to next field, and render buffer if we reached the maximum number of
|
||||
* chunks, at the last field in a line.
|
||||
*/
|
||||
static void field_next(void)
|
||||
{
|
||||
if (field_is_last(current_field) && buffer.chunks >= BUF_CHUNKS_MAX) {
|
||||
render();
|
||||
return;
|
||||
}
|
||||
|
||||
field_flush(current_field);
|
||||
if (field_is_last(current_field))
|
||||
current_field = columns;
|
||||
else
|
||||
current_field++;
|
||||
}
|
||||
|
||||
/* Walk through fields and flush them until we reach the desired one */
|
||||
static void field_set(enum col_id id)
|
||||
{
|
||||
while (id != current_field - columns)
|
||||
field_next();
|
||||
}
|
||||
|
||||
/* Print header for all non-empty columns */
|
||||
static void print_header(void)
|
||||
{
|
||||
while (!field_is_last(current_field)) {
|
||||
if (!current_field->disabled)
|
||||
out("%s", current_field->header);
|
||||
field_next();
|
||||
}
|
||||
}
|
||||
|
||||
static void sock_state_print(struct sockstat *s)
|
||||
{
|
||||
const char *sock_name;
|
||||
|
|
@ -3022,6 +3043,15 @@ static int inet_show_sock(struct nlmsghdr *nlh,
|
|||
}
|
||||
}
|
||||
|
||||
if (show_tos) {
|
||||
if (tb[INET_DIAG_TOS])
|
||||
out(" tos:%#x", rta_getattr_u8(tb[INET_DIAG_TOS]));
|
||||
if (tb[INET_DIAG_TCLASS])
|
||||
out(" tclass:%#x", rta_getattr_u8(tb[INET_DIAG_TCLASS]));
|
||||
if (tb[INET_DIAG_CLASS_ID])
|
||||
out(" class_id:%#x", rta_getattr_u32(tb[INET_DIAG_CLASS_ID]));
|
||||
}
|
||||
|
||||
if (show_mem || (show_tcpinfo && s->type != IPPROTO_UDP)) {
|
||||
out("\n\t");
|
||||
if (s->type == IPPROTO_SCTP)
|
||||
|
|
@ -3072,6 +3102,11 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
|
|||
req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
|
||||
}
|
||||
|
||||
if (show_tos) {
|
||||
req.r.idiag_ext |= (1<<(INET_DIAG_TOS-1));
|
||||
req.r.idiag_ext |= (1<<(INET_DIAG_TCLASS-1));
|
||||
}
|
||||
|
||||
iov[0] = (struct iovec){
|
||||
.iov_base = &req,
|
||||
.iov_len = sizeof(req)
|
||||
|
|
@ -3132,6 +3167,11 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
|
|||
req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
|
||||
}
|
||||
|
||||
if (show_tos) {
|
||||
req.r.idiag_ext |= (1<<(INET_DIAG_TOS-1));
|
||||
req.r.idiag_ext |= (1<<(INET_DIAG_TCLASS-1));
|
||||
}
|
||||
|
||||
iov[0] = (struct iovec){
|
||||
.iov_base = &req,
|
||||
.iov_len = sizeof(req)
|
||||
|
|
@ -4814,6 +4854,7 @@ static void _usage(FILE *dest)
|
|||
" -i, --info show internal TCP information\n"
|
||||
" --tipcinfo show internal tipc socket information\n"
|
||||
" -s, --summary show socket usage summary\n"
|
||||
" --tos show tos and priority information\n"
|
||||
" -b, --bpf show bpf filter socket information\n"
|
||||
" -E, --events continually display sockets as they are destroyed\n"
|
||||
" -Z, --context display process SELinux security contexts\n"
|
||||
|
|
@ -4918,8 +4959,10 @@ static int scan_state(const char *state)
|
|||
#define OPT_TIPCSOCK 257
|
||||
#define OPT_TIPCINFO 258
|
||||
|
||||
#define OPT_TOS 259
|
||||
|
||||
/* Values of 'x' are already used so a non-character is used */
|
||||
#define OPT_XDPSOCK 259
|
||||
#define OPT_XDPSOCK 260
|
||||
|
||||
static const struct option long_opts[] = {
|
||||
{ "numeric", 0, 0, 'n' },
|
||||
|
|
@ -4956,6 +4999,7 @@ static const struct option long_opts[] = {
|
|||
{ "contexts", 0, 0, 'z' },
|
||||
{ "net", 1, 0, 'N' },
|
||||
{ "tipcinfo", 0, 0, OPT_TIPCINFO},
|
||||
{ "tos", 0, 0, OPT_TOS },
|
||||
{ "kill", 0, 0, 'K' },
|
||||
{ "no-header", 0, 0, 'H' },
|
||||
{ "xdp", 0, 0, OPT_XDPSOCK},
|
||||
|
|
@ -5139,6 +5183,9 @@ int main(int argc, char *argv[])
|
|||
case OPT_TIPCINFO:
|
||||
show_tipcinfo = 1;
|
||||
break;
|
||||
case OPT_TOS:
|
||||
show_tos = 1;
|
||||
break;
|
||||
case 'K':
|
||||
current_filter.kill = 1;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ip.h>
|
||||
|
|
|
|||
18
tc/tc_util.c
18
tc/tc_util.c
|
|
@ -190,12 +190,13 @@ static const struct rate_suffix {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
static int parse_percent_rate(char *rate, const char *str, const char *dev)
|
||||
static int parse_percent_rate(char *rate, size_t len,
|
||||
const char *str, const char *dev)
|
||||
{
|
||||
long dev_mbit;
|
||||
int ret;
|
||||
double perc, rate_mbit;
|
||||
char *str_perc;
|
||||
double perc, rate_bit;
|
||||
char *str_perc = NULL;
|
||||
|
||||
if (!dev[0]) {
|
||||
fprintf(stderr, "No device specified; specify device to rate limit by percentage\n");
|
||||
|
|
@ -219,10 +220,10 @@ static int parse_percent_rate(char *rate, const char *str, const char *dev)
|
|||
return -1;
|
||||
}
|
||||
|
||||
rate_mbit = perc * dev_mbit;
|
||||
rate_bit = perc * dev_mbit * 1000 * 1000;
|
||||
|
||||
ret = snprintf(rate, 20, "%lf", rate_mbit);
|
||||
if (ret <= 0 || ret >= 20) {
|
||||
ret = snprintf(rate, len, "%lf", rate_bit);
|
||||
if (ret <= 0 || ret >= len) {
|
||||
fprintf(stderr, "Unable to parse calculated rate\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -230,6 +231,7 @@ static int parse_percent_rate(char *rate, const char *str, const char *dev)
|
|||
return 0;
|
||||
|
||||
malf:
|
||||
free(str_perc);
|
||||
fprintf(stderr, "Specified rate value could not be read or is malformed\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -238,7 +240,7 @@ int get_percent_rate(unsigned int *rate, const char *str, const char *dev)
|
|||
{
|
||||
char r_str[20];
|
||||
|
||||
if (parse_percent_rate(r_str, str, dev))
|
||||
if (parse_percent_rate(r_str, sizeof(r_str), str, dev))
|
||||
return -1;
|
||||
|
||||
return get_rate(rate, r_str);
|
||||
|
|
@ -248,7 +250,7 @@ int get_percent_rate64(__u64 *rate, const char *str, const char *dev)
|
|||
{
|
||||
char r_str[20];
|
||||
|
||||
if (parse_percent_rate(r_str, str, dev))
|
||||
if (parse_percent_rate(r_str, sizeof(r_str), str, dev))
|
||||
return -1;
|
||||
|
||||
return get_rate64(rate, r_str);
|
||||
|
|
|
|||
Loading…
Reference in New Issue