tc: B.W limits can now be specified in %.
Subsystems (3)
PATCH v4 1/1 tc: B.W limits can now be specified in %.
This patch adapts the tc command line interface to allow bandwidth limits to be specified as a percentage of the interface's capacity.
Adding this functionality requires passing the specified device string to each class/qdisc which changes the prototype for a couple of functions: the .parse_qopt and .parse_copt interfaces. The device string is a required parameter for tc-qdisc and tc-class, and when not specified, the kernel returns ENODEV. In this patch, if the user tries to specify a bandwidth percentage without naming the device, we return an error from userspace.
v2:
* Modified and moved int read_prop() from ip/iptuntap.c to lib/utils.c, to make it accessible to tc.
v3:
* Modified and moved int parse_percent() from tc/q_netem.c to ib/util.c for use in tc.
* Changed couple variable names in int parse_percent_rate().
* Handled showing error message when device speed is unknown.
* Updated man page to warn users that when specifying rates in %, tc only uses the current device speed and does not recalculate if it changes after.
During cases when properties (like device speed) are unknown, read_prop() assumes that if the property file can be opened but not read, it means that the property is unknown.
v4:
* int read_prop() in lib/utils.c was using strtoul() API, this was changed to strtol()
* 'const' quantifier was added to device string arguments in .parse_qopt and .parse_copt interface headers
Signed-off by: Nishanth Devarajan<[email protected]>
--- include/utils.h | 2 ++ ip/iptuntap.c | 32 --------------------------- lib/utils.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ man/man8/tc.8 | 5 ++++- tc/q_atm.c | 4 ++-- tc/q_cbq.c | 25 ++++++++++++++++----- tc/q_cbs.c | 2 +- tc/q_choke.c | 9 ++++++-- tc/q_clsact.c | 2 +- tc/q_codel.c | 2 +- tc/q_drr.c | 4 ++-- tc/q_dsmark.c | 4 ++-- tc/q_fifo.c | 2 +- tc/q_fq.c | 16 +++++++++++--- tc/q_fq_codel.c | 2 +- tc/q_gred.c | 9 ++++++-- tc/q_hfsc.c | 45 +++++++++++++++++++++++++------------- tc/q_hhf.c | 2 +- tc/q_htb.c | 18 +++++++++++---- tc/q_ingress.c | 2 +- tc/q_mqprio.c | 2 +- tc/q_multiq.c | 2 +- tc/q_netem.c | 23 ++++++------------- tc/q_pie.c | 2 +- tc/q_prio.c | 2 +- tc/q_qfq.c | 4 ++-- tc/q_red.c | 9 ++++++-- tc/q_rr.c | 2 +- tc/q_sfb.c | 2 +- tc/q_sfq.c | 2 +- tc/q_tbf.c | 16 +++++++++++--- tc/tc.c | 2 +- tc/tc_class.c | 2 +- tc/tc_qdisc.c | 2 +- tc/tc_util.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tc/tc_util.h | 7 ++++-- 36 files changed, 285 insertions(+), 112 deletions(-)
include/utils.h +2 -0
@@ -88,6 +88,8 @@ int get_prefix(inet_prefix *dst, char *arg, int family);int mask2bits (__u32 netmask);int get_addr_ila (__u64 *val,const char *arg); +int read_prop (const char *dev,char *prop,long *value); +int parse_percent (double *val,const char *str);int get_hex (char c);int get_integer (int *val,const char *arg,int base);int get_unsigned (unsigned *val,const char *arg,int base);
ip/iptuntap.c +0 -32
@@ -223,38 +223,6 @@ static int do_del(int argc, char **argv)return tap_del_ioctl (&ifr); } -static int read_prop (char *dev,char *prop,long *value) -{ -char fname[IFNAMSIZ +25 ], buf[80 ], *endp; -ssize_t len; -int fd; -long result; - -sprintf (fname,"/sys/class/net/%s/%s" , dev, prop); - fd =open (fname,O_RDONLY ); -if (fd <0 ) { -if (strcmp (prop,"tun_flags" )) -fprintf (stderr,"open %s: %s\n" , fname, -strerror (errno)); -return -1 ; - } - len =read (fd, buf,sizeof (buf)-1 ); -close (fd); -if (len <0 ) { -fprintf (stderr,"read %s: %s" , fname,strerror (errno)); -return -1 ; - } - - buf[len] =0 ; - result =strtol (buf, &endp,0 ); -if (*endp !='\n' ) { -fprintf (stderr,"Failed to parse %s\n" , fname); -return -1 ; - } - *value = result; -return 0 ; -} -static void print_flags (long flags) {if (flags &IFF_TUN )
lib/utils.c +68 -0
74 lines not on this page · raw message
man/man8/tc.8 +4 -1
@@ -443,7 +443,10 @@ see the man pages for individual qdiscs. RATES Bandwidths or rates. These parameters accept a floating point number, possibly followed by -a unit (both SI and IEC units supported). +either a unit (both SI and IEC units supported), or a float followed by a '%' +character to specify the rate as a percentage of the device's speed +(e.g. 5%, 99.5%). Warning: specifying the rate as a percentage means a fraction +of the current speed; if the speed changes, the value will not be recalculated. .RS .TP bit or a bare number
tc/q_atm.c +2 -2
@@ -26,7 +26,7 @@#define MAX_HDR_LEN 64 -static int atm_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int atm_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {if (argc) {fprintf (stderr,"Usage: atm\n" );
@@ -44,7 +44,7 @@ static void explain(void)static int atm_parse_class_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct sockaddr_atmsvc addr = {};struct atm_qos qos;
tc/q_cbq.c +20 -5
@@ -46,7 +46,7 @@ static void explain1(char *arg) } -static int cbq_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int cbq_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {struct tc_ratespec r = {};struct tc_cbq_lssopt lss = {};
@@ -62,7 +62,12 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlif (matches (*argv,"bandwidth" ) ==0 ||matches (*argv,"rate" ) ==0 ) {NEXT_ARG (); -if (get_rate (&r.rate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&r.rate, *argv, dev)) { +explain1 ("bandwidth" ); +return -1 ; + } + }else if (get_rate (&r.rate, *argv)) {explain1 ("bandwidth" );return -1 ; }
@@ -176,7 +181,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlreturn 0 ; } -static int cbq_parse_class_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int cbq_parse_class_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int wrr_ok =0 , fopt_ok =0 ;struct tc_ratespec r = {};
@@ -196,13 +201,23 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, strwhile (argc >0 ) {if (matches (*argv,"rate" ) ==0 ) {NEXT_ARG (); -if (get_rate (&r.rate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&r.rate, *argv, dev)) { +explain1 ("rate" ); +return -1 ; + } + }else if (get_rate (&r.rate, *argv)) {explain1 ("rate" );return -1 ; } }else if (matches (*argv,"bandwidth" ) ==0 ) {NEXT_ARG (); -if (get_rate (&bndw, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&bndw, *argv, dev)) { +explain1 ("bandwidth" ); +return -1 ; + } + }else if (get_rate (&bndw, *argv)) {explain1 ("bandwidth" );return -1 ; }
tc/q_cbs.c +1 -1
@@ -34,7 +34,7 @@ static void explain1(const char *arg, const char *val)fprintf (stderr,"cbs: illegal value for \"%s\": \"%s\"\n" , arg, val); } -static int cbs_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int cbs_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {struct tc_cbs_qopt opt = {};struct rtattr *tail;
tc/q_choke.c +7 -2
@@ -31,7 +31,7 @@ static void explain(void) }static int choke_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct tc_red_qopt opt = {};unsigned int burst =0 ;
@@ -53,7 +53,12 @@ static int choke_parse_opt(struct qdisc_util *qu, int argc, char **argv, } }else if (strcmp (*argv,"bandwidth" ) ==0 ) {NEXT_ARG (); -if (get_rate (&rate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&rate, *argv, dev)) { +fprintf (stderr,"Illegal \"bandwidth\"\n" ); +return -1 ; + } + }else if (get_rate (&rate, *argv)) {fprintf (stderr,"Illegal \"bandwidth\"\n" );return -1 ; }
tc/q_clsact.c +1 -1
@@ -10,7 +10,7 @@ static void explain(void) }static int clsact_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {if (argc >0 ) {fprintf (stderr,"What is \"%s\"?\n" , *argv);
tc/q_codel.c +1 -1
@@ -58,7 +58,7 @@ static void explain(void) }static int codel_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {unsigned int limit =0 ;unsigned int target =0 ;
tc/q_drr.c +2 -2
@@ -33,7 +33,7 @@ static void explain2(void) } -static int drr_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int drr_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {while (argc) {if (strcmp (*argv,"help" ) ==0 ) {
@@ -49,7 +49,7 @@ static int drr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl }static int drr_parse_class_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct rtattr *tail;__u32 tmp;
tc/q_dsmark.c +2 -2
@@ -25,7 +25,7 @@ static void explain(void)static int dsmark_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct rtattr *tail;__u16 ind;
@@ -84,7 +84,7 @@ static void explain_class(void)static int dsmark_parse_class_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct rtattr *tail;__u8 tmp;
tc/q_fifo.c +1 -1
@@ -27,7 +27,7 @@ static void explain(void)fprintf (stderr,"Usage: ... <[p|b]fifo | pfifo_head_drop> [ limit NUMBER ]\n" ); } -static int fifo_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int fifo_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int ok =0 ;struct tc_fifo_qopt opt = {};
tc/q_fq.c +13 -3
@@ -71,7 +71,7 @@ static unsigned int ilog2(unsigned int val) }static int fq_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {unsigned int plimit;unsigned int flow_plimit;
@@ -118,7 +118,12 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, } }else if (strcmp (*argv,"maxrate" ) ==0 ) {NEXT_ARG (); -if (get_rate (&maxrate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&maxrate, *argv, dev)) { +fprintf (stderr,"Illegal \"maxrate\"\n" ); +return -1 ; + } + }else if (get_rate (&maxrate, *argv)) {fprintf (stderr,"Illegal \"maxrate\"\n" );return -1 ; }
@@ -132,7 +137,12 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, set_low_rate_threshold = true; }else if (strcmp (*argv,"defrate" ) ==0 ) {NEXT_ARG (); -if (get_rate (&defrate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&defrate, *argv, dev)) { +fprintf (stderr,"Illegal \"defrate\"\n" ); +return -1 ; + } + }else if (get_rate (&defrate, *argv)) {fprintf (stderr,"Illegal \"defrate\"\n" );return -1 ; }
tc/q_fq_codel.c +1 -1
@@ -56,7 +56,7 @@ static void explain(void) }static int fq_codel_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {unsigned int limit =0 ;unsigned int flows =0 ;
tc/q_gred.c +7 -2
@@ -116,7 +116,7 @@ static int init_gred(struct qdisc_util *qu, int argc, char **argv,/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ -static int gred_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int gred_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int ok =0 ;struct tc_gred_qopt opt = {0 };
@@ -199,7 +199,12 @@ static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct n ok++; }else if (strcmp (*argv,"bandwidth" ) ==0 ) {NEXT_ARG (); -if (get_rate (&rate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&rate, *argv, dev)) { +fprintf (stderr,"Illegal \"bandwidth\"\n" ); +return -1 ; + } + }else if (get_rate (&rate, *argv)) {fprintf (stderr,"Illegal \"bandwidth\"\n" );return -1 ; }
tc/q_hfsc.c +30 -15
124 lines not on this page · raw message
tc/q_hhf.c +1 -1
@@ -25,7 +25,7 @@ static void explain(void) }static int hhf_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {unsigned int limit =0 ;unsigned int quantum =0 ;
tc/q_htb.c +14 -4
@@ -59,7 +59,7 @@ static void explain1(char *arg) } -static int htb_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int htb_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {unsigned int direct_qlen = ~0U ;struct tc_htb_glob opt = {
@@ -108,7 +108,7 @@ static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlreturn 0 ; } -static int htb_parse_class_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int htb_parse_class_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int ok =0 ;struct tc_htb_opt opt = {};
@@ -178,7 +178,12 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, strfprintf (stderr,"Double \"ceil\" spec\n" );return -1 ; } -if (get_rate64 (&ceil64, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate64 (&ceil64, *argv, dev)) { +explain1 ("ceil" ); +return -1 ; + } + }else if (get_rate64 (&ceil64, *argv)) {explain1 ("ceil" );return -1 ; }
@@ -189,7 +194,12 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, strfprintf (stderr,"Double \"rate\" spec\n" );return -1 ; } -if (get_rate64 (&rate64, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate64 (&rate64, *argv, dev)) { +explain1 ("rate" ); +return -1 ; + } + }else if (get_rate64 (&rate64, *argv)) {explain1 ("rate" );return -1 ; }
tc/q_ingress.c +1 -1
@@ -21,7 +21,7 @@ static void explain(void) }static int ingress_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {while (argc >0 ) {if (strcmp (*argv,"handle" ) ==0 ) {
tc/q_mqprio.c +1 -1
@@ -33,7 +33,7 @@ static void explain(void) }static int mqprio_parse_opt (struct qdisc_util *qu,int argc, -char **argv,struct nlmsghdr *n) +char **argv,struct nlmsghdr *n,const char *dev) {int idx;struct tc_mqprio_qopt opt = {
tc/q_multiq.c +1 -1
@@ -40,7 +40,7 @@ static void explain(void) }static int multiq_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct tc_multiq_qopt opt = {};
tc/q_netem.c +7 -16
@@ -59,20 +59,6 @@ static void set_percent(__u32 *percent, double per) *percent =rint (per *UINT32_MAX ); } -/* Parse either a fraction '.3' or percent '30% -* return: 0 = ok, -1 = error, 1 = out of range -*/ -static int parse_percent (double *val,const char *str) -{ -char *p; - - *val =strtod (str, &p) /100. ; -if (*p &&strcmp (p,"%" )) -return -1 ; - -return 0 ; -} -static int get_percent (__u32 *percent,const char *str) {double per;
@@ -167,7 +153,7 @@ static int get_ticks(__u32 *ticks, const char *str) }static int netem_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {int dist_size =0 ;struct rtattr *tail;
@@ -396,7 +382,12 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, }else if (matches (*argv,"rate" ) ==0 ) { ++present[TCA_NETEM_RATE ];NEXT_ARG (); -if (get_rate64 (&rate64, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate64 (&rate64, *argv, dev)) { +explain1 ("rate" ); +return -1 ; + } + }else if (get_rate64 (&rate64, *argv)) {explain1 ("rate" );return -1 ; }
tc/q_pie.c +1 -1
@@ -39,7 +39,7 @@ static void explain(void)#define BETA_MAX 32static int pie_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {unsigned int limit =0 ;unsigned int target =0 ;
tc/q_prio.c +1 -1
@@ -27,7 +27,7 @@ static void explain(void)fprintf (stderr,"Usage: ... prio bands NUMBER priomap P1 P2...[multiqueue]\n" ); } -static int prio_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int prio_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int pmap_mode =0 ;int idx =0 ;
tc/q_qfq.c +2 -2
@@ -35,7 +35,7 @@ static void explain_class(void) }static int qfq_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {if (argc >0 ) {if (matches (*argv,"help" ) !=0 )
@@ -48,7 +48,7 @@ static int qfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, }static int qfq_parse_class_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct rtattr *tail;__u32 tmp;
tc/q_red.c +7 -2
@@ -32,7 +32,7 @@ static void explain(void)fprintf (stderr," [ecn] [harddrop]\n" ); } -static int red_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int red_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {struct tc_red_qopt opt = {};unsigned int burst =0 ;
@@ -83,7 +83,12 @@ static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl } }else if (strcmp (*argv,"bandwidth" ) ==0 ) {NEXT_ARG (); -if (get_rate (&rate, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate (&rate, *argv, dev)) { +fprintf (stderr,"Illegal \"bandwidth\"\n" ); +return -1 ; + } + }else if (get_rate (&rate, *argv)) {fprintf (stderr,"Illegal \"bandwidth\"\n" );return -1 ; }
tc/q_rr.c +1 -1
@@ -28,7 +28,7 @@ static void explain(void) } -static int rr_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int rr_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int pmap_mode =0 ;int idx =0 ;
tc/q_sfb.c +1 -1
@@ -48,7 +48,7 @@ static int get_prob(__u32 *val, const char *arg) }static int sfb_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,const char *dev) {struct tc_sfb_qopt opt = { .rehash_interval =600 *1000 ,
tc/q_sfq.c +1 -1
@@ -34,7 +34,7 @@ static void explain(void)fprintf (stderr," [ ecn ] [ harddrop ]\n" ); } -static int sfq_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int sfq_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int ok =0 , red =0 ;struct tc_sfq_qopt_v1 opt = {};
tc/q_tbf.c +13 -3
@@ -35,7 +35,7 @@ static void explain1(const char *arg, const char *val) } -static int tbf_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int tbf_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {int ok =0 ;struct tc_tbf_qopt opt = {};
@@ -125,7 +125,12 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlfprintf (stderr,"tbf: duplicate \"rate\" specification\n" );return -1 ; } -if (get_rate64 (&rate64, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate64 (&rate64, *argv, dev)) { +explain1 ("rate" , *argv); +return -1 ; + } + }else if (get_rate64 (&rate64, *argv)) {explain1 ("rate" , *argv);return -1 ; }
@@ -136,7 +141,12 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlfprintf (stderr,"tbf: duplicate \"peakrate\" specification\n" );return -1 ; } -if (get_rate64 (&prate64, *argv)) { +if (strchr (*argv,'%' )) { +if (get_percent_rate64 (&prate64, *argv, dev)) { +explain1 ("peakrate" , *argv); +return -1 ; + } + }else if (get_rate64 (&prate64, *argv)) {explain1 ("peakrate" , *argv);return -1 ; }
tc/tc.c +1 -1
@@ -59,7 +59,7 @@ static int print_noqopt(struct qdisc_util *qu, FILE *f,return 0 ; } -static int parse_noqopt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) +static int parse_noqopt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n,const char *dev) {if (argc) {fprintf (stderr,"Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n" , qu->id, *argv);
tc/tc_class.c +1 -1
@@ -128,7 +128,7 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)fprintf (stderr,"Error: Qdisc \"%s\" is classless.\n" , k);return 1 ; } -if (q->parse_copt (q, argc, argv, &req.n)) +if (q->parse_copt (q, argc, argv, &req.n, d))return 1 ; }else {if (argc) {
tc/tc_qdisc.c +1 -1
@@ -140,7 +140,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)if (q) {if (q->parse_qopt) { -if (q->parse_qopt (q, argc, argv, &req.n)) +if (q->parse_qopt (q, argc, argv, &req.n, d))return 1 ; }else if (argc) {fprintf (stderr,"qdisc '%s' does not support option parsing\n" , k);
tc/tc_util.c +63 -0
69 lines not on this page · raw message
tc/tc_util.h +5 -2
@@ -24,14 +24,14 @@ struct qdisc_util {struct qdisc_util *next;const char *id;int (*parse_qopt)(struct qdisc_util *qu,int argc, -char **argv,struct nlmsghdr *n); +char **argv,struct nlmsghdr *n,const char *dev);int (*print_qopt)(struct qdisc_util *qu,FILE *f,struct rtattr *opt);int (*print_xstats)(struct qdisc_util *qu,FILE *f,struct rtattr *xstats);int (*parse_copt)(struct qdisc_util *qu,int argc, -char **argv,struct nlmsghdr *n); +char **argv,struct nlmsghdr *n,const char *dev);int (*print_copt)(struct qdisc_util *qu,FILE *f,struct rtattr *opt); };
@@ -66,9 +66,12 @@ const char *get_tc_lib(void);struct qdisc_util *get_qdisc_kind (const char *str);struct filter_util *get_filter_kind (const char *str); +int parse_percent_rate (char *rate,const char *str,const char *dev);int get_qdisc_handle (__u32 *h,const char *str);int get_rate (unsigned int *rate,const char *str); +int get_percent_rate (unsigned int *rate,const char *str,const char *dev);int get_rate64 (__u64 *rate,const char *str); +int get_percent_rate64 (__u64 *rate,const char *str,const char *dev);int get_size (unsigned int *size,const char *str);int get_size_and_cell (unsigned int *size,int *cell_log,char *str);int get_time (unsigned int *time,const char *str);
Signature · 1 line
1.9.1