tc: B.W limits can now be specified in %
Subsystems (3)
PATCH 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.
For this purpose, we move int read_prop() from ip/iptuntap.c to lib/utils.c to make it accessible to tc.
Additionally, 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 return ENODEV. In this patch, if the user tries to specify a bandwidth percentage without naming the device, we return an error from userspace.
--- include/utils.h | 1 + ip/iptuntap.c | 32 -------------------------------- lib/utils.c | 32 ++++++++++++++++++++++++++++++++ man/man8/tc.8 | 4 +++- tc/q_atm.c | 2 +- tc/q_cbq.c | 25 ++++++++++++++++++++----- 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 | 9 +++++++-- 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 | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tc/tc_util.h | 8 ++++++-- 35 files changed, 237 insertions(+), 96 deletions(-)
include/utils.h +1 -0
@@ -87,6 +87,7 @@ 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 (char *dev,char *prop,long *value);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 +32 -0
@@ -39,6 +39,38 @@int timestamp_short; +int read_prop (char *dev,char *prop,long *value) +{ +char fname[41 ], 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 ; +} +int get_hex (char c) {if (c >='A' && c <='F' )
man/man8/tc.8 +3 -1
@@ -443,7 +443,9 @@ 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 '%' +character to specify the rate as a percentage of the device's speed +(e.g. 5%, 99.5%). .RS .TP bit or a bare number
tc/q_atm.c +1 -1
@@ -45,7 +45,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,char *dev) {struct sockaddr_atmsvc addr = {};struct atm_qos qos;
tc/q_cbq.c +20 -5
@@ -47,7 +47,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,char *dev) {struct tc_ratespec r = {};struct tc_cbq_lssopt lss = {};
@@ -63,7 +63,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 ; }
@@ -177,7 +182,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,char *dev) {int wrr_ok =0 , fopt_ok =0 ;struct tc_ratespec r = {};
@@ -197,13 +202,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_choke.c +7 -2
@@ -32,7 +32,7 @@ static void explain(void) }static int choke_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,char *dev) {struct tc_red_qopt opt = {};unsigned int burst =0 ;
@@ -54,7 +54,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,char *dev) {if (argc >0 ) {fprintf (stderr,"What is \"%s\"?\n" , *argv);
tc/q_codel.c +1 -1
@@ -59,7 +59,7 @@ static void explain(void) }static int codel_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,char *dev) {unsigned int limit =0 ;unsigned int target =0 ;
tc/q_drr.c +2 -2
@@ -34,7 +34,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,char *dev) {while (argc) {if (strcmp (*argv,"help" ) ==0 ) {
@@ -50,7 +50,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,char *dev) {struct rtattr *tail;__u32 tmp;
tc/q_dsmark.c +2 -2
@@ -26,7 +26,7 @@ static void explain(void)static int dsmark_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,char *dev) {struct rtattr *tail;__u16 ind;
@@ -85,7 +85,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,char *dev) {struct rtattr *tail;__u8 tmp;
tc/q_fifo.c +1 -1
@@ -28,7 +28,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,char *dev) {int ok =0 ;struct tc_fifo_qopt opt = {};
tc/q_fq.c +13 -3
@@ -72,7 +72,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,char *dev) {unsigned int plimit;unsigned int flow_plimit;
@@ -119,7 +119,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 ; }
@@ -133,7 +138,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
@@ -57,7 +57,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,char *dev) {unsigned int limit =0 ;unsigned int flows =0 ;
tc/q_gred.c +7 -2
@@ -117,7 +117,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,char *dev) {int ok =0 ;struct tc_gred_qopt opt = {0 };
@@ -200,7 +200,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
@@ -26,7 +26,7 @@ static void explain(void) }static int hhf_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,char *dev) {unsigned int limit =0 ;unsigned int quantum =0 ;
tc/q_htb.c +14 -4
@@ -60,7 +60,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,char *dev) {unsigned int direct_qlen = ~0U ;struct tc_htb_glob opt = {
@@ -109,7 +109,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,char *dev) {int ok =0 ;struct tc_htb_opt opt = {};
@@ -179,7 +179,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 ; }
@@ -190,7 +195,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,char *dev) {while (argc >0 ) {if (strcmp (*argv,"handle" ) ==0 ) {
tc/q_mqprio.c +1 -1
@@ -30,7 +30,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,char *dev) {int idx;struct tc_mqprio_qopt opt = {
tc/q_multiq.c +1 -1
@@ -41,7 +41,7 @@ static void explain(void) }static int multiq_parse_opt (struct qdisc_util *qu,int argc,char **argv, -struct nlmsghdr *n) +struct nlmsghdr *n,char *dev) {struct tc_multiq_qopt opt = {};
tc/q_netem.c +7 -2
@@ -170,7 +170,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,char *dev) {int dist_size =0 ;struct rtattr *tail;
@@ -399,7 +399,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
@@ -40,7 +40,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,char *dev) {unsigned int limit =0 ;unsigned int target =0 ;
tc/q_prio.c +1 -1
@@ -28,7 +28,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,char *dev) {int pmap_mode =0 ;int idx =0 ;
tc/q_qfq.c +2 -2
@@ -36,7 +36,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,char *dev) {if (argc >0 ) {if (matches (*argv,"help" ) !=0 )
@@ -49,7 +49,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,char *dev) {struct rtattr *tail;__u32 tmp;
tc/q_red.c +7 -2
@@ -33,7 +33,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,char *dev) {struct tc_red_qopt opt = {};unsigned int burst =0 ;
@@ -84,7 +84,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
@@ -29,7 +29,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,char *dev) {int pmap_mode =0 ;int idx =0 ;
tc/q_sfb.c +1 -1
@@ -49,7 +49,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,char *dev) {struct tc_sfb_qopt opt = { .rehash_interval =600 *1000 ,
tc/q_sfq.c +1 -1
@@ -35,7 +35,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,char *dev) {int ok =0 , red =0 ;struct tc_sfq_qopt_v1 opt = {};
tc/q_tbf.c +13 -3
@@ -36,7 +36,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,char *dev) {int ok =0 ;struct tc_tbf_qopt opt = {};
@@ -126,7 +126,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 ; }
@@ -137,7 +142,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
@@ -61,7 +61,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,char *dev) {if (argc) {fprintf (stderr,"Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n" , qu->id, *argv);
tc/tc_class.c +1 -1
@@ -129,7 +129,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
@@ -141,7 +141,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 +54 -0
60 lines not on this page · raw message
tc/tc_util.h +6 -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,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,char *dev);int (*print_copt)(struct qdisc_util *qu,FILE *f,struct rtattr *opt); };
@@ -66,9 +66,13 @@ 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 read_prop (char *dev,char *prop,long *value); +int parse_percent_rate (char *rate,const char *str,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,char *dev);int get_rate64 (__u64 *rate,const char *str); +int get_percent_rate64 (__u64 *rate,const char *str,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
Quoted 22 lines · On Sat, 28 Oct 2017 22:57:00 +0530 Nishanth Devarajan <[email protected]>…
lib/utils.c +21
-0+int read_prop (char *dev,char *prop,long *value) +{ +char fname[41 ], 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 ; + }
lib/utils.c line 72
Quoted 10 lines
lib/utils.c +10
-0+ + 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 ; +}
I know you copy and pasted this code, but it was already a mess.
1. It should use stdio (fopen/fgets)
2. It should not be looking for signed values (ie use strtoul)
3. It should not be special casing "tun_flags"
4. It needs to check for all possible parsing errors, with strtoul. (hint read strtoul man page for how errors are reported).