Merge branch 'iproute2-master' into next

Conflicts:
	misc/ss.c

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2019-02-22 18:50:39 -08:00
commit 9f78e995a8
18 changed files with 221 additions and 62 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
View File

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

View File

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

View File

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