]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
Merge /tmp/iproute2
authorStephen Hemminger <stephen@networkplumber.org>
Tue, 24 Sep 2013 17:17:18 +0000 (10:17 -0700)
committerStephen Hemminger <stephen@networkplumber.org>
Tue, 24 Sep 2013 17:17:18 +0000 (10:17 -0700)
28 files changed:
include/SNAPSHOT.h
include/linux/fib_rules.h
include/linux/if_bridge.h
include/linux/if_link.h
include/linux/if_tun.h
include/linux/pkt_sched.h
include/linux/tcp.h
ip/iplink_macvlan.c
ip/ipmonitor.c
ip/ipnetns.c
ip/iproute.c
ip/iprule.c
ip/iptunnel.c
ip/ipxfrm.c
ip/link_iptnl.c
man/man8/bridge.8
man/man8/ip-route.8.in
man/man8/ip-rule.8
tc/Makefile
tc/m_police.c
tc/q_cbq.c
tc/q_fq.c [new file with mode: 0644]
tc/q_htb.c
tc/q_tbf.c
tc/tc_core.c
tc/tc_qdisc.c
tc/tc_util.c
tc/tc_util.h

index 63b857de04a517ebe6c6b99803e284ce41a4a2f7..8f896b78a3e36592b03c61234f6955c1309f130c 100644 (file)
@@ -1 +1 @@
-static const char SNAPSHOT[] = "130716";
+static const char SNAPSHOT[] = "130903";
index 51da65b68b8501cb2d25fe0064c2c6ff65e3d4e6..2b82d7e30974f93b9a93afc2fdf5c9137492043d 100644 (file)
@@ -44,8 +44,8 @@ enum {
        FRA_FWMARK,     /* mark */
        FRA_FLOW,       /* flow/class id */
        FRA_UNUSED6,
-       FRA_UNUSED7,
-       FRA_UNUSED8,
+       FRA_SUPPRESS_IFGROUP,
+       FRA_SUPPRESS_PREFIXLEN,
        FRA_TABLE,      /* Extended table id */
        FRA_FWMASK,     /* mask for netfilter mark */
        FRA_OIFNAME,
index d37e53c370546a6ff1ea7cbd4d2dd794c0deb6f1..d2de4e67ff9f67cabaafd0659c785045db927e93 100644 (file)
@@ -14,6 +14,7 @@
 #define _LINUX_IF_BRIDGE_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 #define SYSFS_BRIDGE_ATTR      "bridge"
 #define SYSFS_BRIDGE_FDB       "brforward"
@@ -88,7 +89,7 @@ struct __port_info {
 };
 
 struct __fdb_entry {
-       __u8 mac_addr[6];
+       __u8 mac_addr[ETH_ALEN];
        __u8 port_no;
        __u8 is_local;
        __u32 ageing_timer_value;
index d07aecaaf86921915c22ffa7919411974f49cd30..ee4f2ba95e4213502cef9407b4ce24774ca8589c 100644 (file)
@@ -143,6 +143,7 @@ enum {
        IFLA_NUM_TX_QUEUES,
        IFLA_NUM_RX_QUEUES,
        IFLA_CARRIER,
+       IFLA_PHYS_PORT_ID,
        __IFLA_MAX
 };
 
@@ -311,6 +312,8 @@ enum {
        IFLA_VXLAN_L2MISS,
        IFLA_VXLAN_L3MISS,
        IFLA_VXLAN_PORT,        /* destination port */
+       IFLA_VXLAN_GROUP6,
+       IFLA_VXLAN_LOCAL6,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
index dc13de35d88d4f5884a7e281fb10117f997f13a1..75cc8ace88756283a8f19a2b830e9133e82564c4 100644 (file)
@@ -56,6 +56,8 @@
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
 #define TUNSETQUEUE  _IOW('T', 217, int)
+#define TUNSETIFINDEX  _IOW('T', 218, unsigned int)
+#define TUNGETFILTER _IOR('T', 219, struct sock_fprog)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001
 #define IFF_DETACH_QUEUE 0x0400
 /* read-only flag */
 #define IFF_PERSIST    0x0800
+#define IFF_NOFILTER   0x1000
+
+/* Socket options */
+#define TUN_TX_TIMESTAMP 1
 
 /* Features for GSO (TUNSETOFFLOAD). */
 #define TUN_F_CSUM     0x01    /* You can hand me unchecksummed packets. */
index dbd71b0c7d8c93edbc80ae50ad7223db3665f00a..9b829134d42243bdfc6816f9272b75ea82c9b934 100644 (file)
@@ -73,9 +73,17 @@ struct tc_estimator {
 #define TC_H_ROOT      (0xFFFFFFFFU)
 #define TC_H_INGRESS    (0xFFFFFFF1U)
 
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
 struct tc_ratespec {
        unsigned char   cell_log;
-       unsigned char   __reserved;
+       __u8            linklayer; /* lower 4 bits */
        unsigned short  overhead;
        short           cell_align;
        unsigned short  mpu;
@@ -736,4 +744,45 @@ struct tc_fq_codel_xstats {
        };
 };
 
+/* FQ */
+
+enum {
+       TCA_FQ_UNSPEC,
+
+       TCA_FQ_PLIMIT,          /* limit of total number of packets in queue */
+
+       TCA_FQ_FLOW_PLIMIT,     /* limit of packets per flow */
+
+       TCA_FQ_QUANTUM,         /* RR quantum */
+
+       TCA_FQ_INITIAL_QUANTUM,         /* RR quantum for new flow */
+
+       TCA_FQ_RATE_ENABLE,     /* enable/disable rate limiting */
+
+       TCA_FQ_FLOW_DEFAULT_RATE,/* for sockets with unspecified sk_rate,
+                                 * use the following rate
+                                 */
+
+       TCA_FQ_FLOW_MAX_RATE,   /* per flow max rate */
+
+       TCA_FQ_BUCKETS_LOG,     /* log2(number of buckets) */
+       __TCA_FQ_MAX
+};
+
+#define TCA_FQ_MAX     (__TCA_FQ_MAX - 1)
+
+struct tc_fq_qd_stats {
+       __u64   gc_flows;
+       __u64   highprio_packets;
+       __u64   tcp_retrans;
+       __u64   throttled;
+       __u64   flows_plimit;
+       __u64   pkts_too_long;
+       __u64   allocation_errors;
+       __s64   time_next_delayed_flow;
+       __u32   flows;
+       __u32   inactive_flows;
+       __u32   throttled_flows;
+       __u32   pad;
+};
 #endif
index 1eb04d354d6fd3f0e8cbfc867cb9e4d1b0379ca1..8df6bd7f4555092d896e952be7cbd62f21cda9b3 100644 (file)
@@ -111,6 +111,7 @@ enum {
 #define TCP_REPAIR_OPTIONS     22
 #define TCP_FASTOPEN           23      /* Enable FastOpen on listeners */
 #define TCP_TIMESTAMP          24
+#define TCP_NOTSENT_LOWAT      25      /* limit number of unsent bytes in write queue */
 
 struct tcp_repair_opt {
        __u32   opt_code;
index 5b4b868b36ae2413974853869d37736d2a4ca182..ec5110657e31d0cd05b7c80d8390430b1c4e7899 100644 (file)
@@ -79,7 +79,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
            RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
                return;
 
-       mode = rta_getattr_u32(tb[IFLA_VLAN_ID]);
+       mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
        fprintf(f, " mode %s ",
                  mode == MACVLAN_MODE_PRIVATE ? "private"
                : mode == MACVLAN_MODE_VEPA    ? "vepa"
index 489539044b6a112376ba61f6789ce8426dcc57ee..70f2a7adbae1f1c00ca1774919e3b250b44fe489 100644 (file)
@@ -36,7 +36,6 @@ static void usage(void)
        exit(-1);
 }
 
-
 static int accept_msg(const struct sockaddr_nl *who,
                      struct nlmsghdr *n, void *arg)
 {
@@ -88,6 +87,13 @@ static int accept_msg(const struct sockaddr_nl *who,
        }
        if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
            n->nlmsg_type == RTM_GETNEIGH) {
+               if (preferred_family) {
+                       struct ndmsg *r = NLMSG_DATA(n);
+
+                       if (r->ndm_family != preferred_family)
+                               return 0;
+               }
+
                if (prefix_banner)
                        fprintf(fp, "[NEIGH]");
                print_neigh(who, n, arg);
index c8a47920539c7b1e355f496e8ba6acba8e25ebbe..89dda3ffd138b320437f4d9f86b23b718a52d7f6 100644 (file)
@@ -205,11 +205,15 @@ static int netns_exec(int argc, char **argv)
                                exit(1);
                        }
 
-                       /* If child failed, propagate status */
-                       if (WIFEXITED(status))
-                               exit(WEXITSTATUS(status));
+                       if (WIFEXITED(status)) {
+                               /* ip must return the status of the child,
+                                * but do_cmd() will add a minus to this,
+                                * so let's add another one here to cancel it.
+                                */
+                               return -WEXITSTATUS(status);
+                       }
 
-                       return 0;
+                       exit(1);
                }
        }
 
index b069f1e0627696ebce4c86b5543072238299afca..25a56d1f5f12226d7b8ce185eed047c15ffb6a74 100644 (file)
@@ -63,7 +63,7 @@ static void usage(void)
        fprintf(stderr, "       ip route restore\n");
        fprintf(stderr, "       ip route showdump\n");
        fprintf(stderr, "       ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
-       fprintf(stderr, "                            [ oif STRING ]  [ tos TOS ]\n");
+       fprintf(stderr, "                            [ oif STRING ] [ tos TOS ]\n");
        fprintf(stderr, "                            [ mark NUMBER ]\n");
        fprintf(stderr, "       ip route { add | del | change | append | replace } ROUTE\n");
        fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n");
@@ -76,7 +76,7 @@ static void usage(void)
        fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
        fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
        fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
-       fprintf(stderr, "           [ rtt TIME ] [ rttvar TIME ] [reordering NUMBER ]\n");
+       fprintf(stderr, "           [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
        fprintf(stderr, "           [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");
        fprintf(stderr, "           [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n");
        fprintf(stderr, "           [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n");
index a5fcd432a6bd11a4c50f3b678f9c7fa08e783a62..d934f67da2e6c255c4a47f282dfc5566ff53ad80 100644 (file)
@@ -39,6 +39,9 @@ static void usage(void)
        fprintf(stderr, "          [ prohibit | reject | unreachable ]\n");
        fprintf(stderr, "          [ realms [SRCREALM/]DSTREALM ]\n");
        fprintf(stderr, "          [ goto NUMBER ]\n");
+       fprintf(stderr, "          SUPPRESSOR\n");
+       fprintf(stderr, "SUPPRESSOR := [ suppress_prefixlength NUMBER ]\n");
+       fprintf(stderr, "              [ suppress_ifgroup DEVGROUP ]\n");
        fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n");
        exit(-1);
 }
@@ -153,9 +156,24 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        }
 
        table = rtm_get_table(r, tb);
-       if (table)
+       if (table) {
                fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
 
+               if (tb[FRA_SUPPRESS_PREFIXLEN]) {
+                       int pl = rta_getattr_u32(tb[FRA_SUPPRESS_PREFIXLEN]);
+                       if (pl != -1) {
+                               fprintf(fp, "suppress_prefixlength %d ", pl);
+                       }
+               }
+               if (tb[FRA_SUPPRESS_IFGROUP]) {
+                       int group = rta_getattr_u32(tb[FRA_SUPPRESS_IFGROUP]);
+                       if (group != -1) {
+                               SPRINT_BUF(b1);
+                               fprintf(fp, "suppress_ifgroup %s ", rtnl_group_n2a(group, b1, sizeof(b1)));
+                       }
+               }
+       }
+
        if (tb[FRA_FLOW]) {
                __u32 to = rta_getattr_u32(tb[FRA_FLOW]);
                __u32 from = to>>16;
@@ -310,6 +328,20 @@ static int iprule_modify(int cmd, int argc, char **argv)
                                addattr32(&req.n, sizeof(req), FRA_TABLE, tid);
                        }
                        table_ok = 1;
+               } else if (matches(*argv, "suppress_prefixlength") == 0 ||
+                          strcmp(*argv, "sup_pl") == 0) {
+                       int pl;
+                       NEXT_ARG();
+                       if (get_s32(&pl, *argv, 0) || pl < 0)
+                               invarg("suppress_prefixlength value is invalid\n", *argv);
+                       addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, pl);
+               } else if (matches(*argv, "suppress_ifgroup") == 0 ||
+                          strcmp(*argv, "sup_group") == 0) {
+                       NEXT_ARG();
+                       int group;
+                       if (rtnl_group_a2n(&group, *argv))
+                               invarg("Invalid \"suppress_ifgroup\" value\n", *argv);
+                       addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, group);
                } else if (strcmp(*argv, "dev") == 0 ||
                           strcmp(*argv, "iif") == 0) {
                        NEXT_ARG();
index 43f858556465ada0003a8753f3c43f83b27d14a9..40186d3d4d57c2fd33fb8e62fc0b2ae286622469 100644 (file)
@@ -280,7 +280,7 @@ static int do_add(int cmd, int argc, char **argv)
                return -1;
 
        if (p.iph.ttl && p.iph.frag_off == 0) {
-               fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
+               fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
                return -1;
        }
 
index 0a3a9fb6117e60c9be747ede1e66f928a953857c..411d9d5363ecb240b4475b0eee9f66c78a965f52 100644 (file)
@@ -856,7 +856,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
                if (flags)
                        fprintf(fp, "%x", flags);
        }
-       if (show_stats > 0 || tb[XFRMA_SA_EXTRA_FLAGS]) {
+       if (show_stats > 0 && tb[XFRMA_SA_EXTRA_FLAGS]) {
                __u32 extra_flags = *(__u32 *)RTA_DATA(tb[XFRMA_SA_EXTRA_FLAGS]);
 
                fprintf(fp, "extra_flag ");
index 394254d81642a0b4d15e62ed4170c61fe68f04c4..d5324f8ec5445257a520b45f29e77374127d6525 100644 (file)
@@ -233,7 +233,7 @@ get_failed:
        }
 
        if (ttl && pmtudisc == 0) {
-               fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
+               fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
                exit(-1);
        }
 
index 66678b5b83eabd784aeb5e2a9dd47e9b129921f9..9a34804f11b7994af6fc38591b27fae32537300e 100644 (file)
@@ -13,7 +13,7 @@ bridge \- show / manipulate bridge addresses and devices
 
 .ti -8
 .IR OBJECT " := { "
-.BR link " | " fdb " | " vlan " | " monitor " }"
+.BR link " | " fdb " | " mdb " | " vlan " | " monitor " }"
 .sp
 
 .ti -8
@@ -64,6 +64,21 @@ bridge \- show / manipulate bridge addresses and devices
 .B  dev
 .IR DEV " ]"
 
+.ti -8
+.BR "bridge mdb" " { " add " | " del " } "
+.B  dev
+.IR DEV
+.B port
+.IR PORT
+.B grp
+.IR GROUP " [ "
+.BR permanent " | " temp " ]"
+
+.ti -8
+.BR "bridge mdb show " [ "
+.B  dev
+.IR DEV " ]"
+
 .ti -8
 .BR "bridge vlan" " { " add " | " del " } "
 .B  dev
@@ -79,7 +94,7 @@ bridge \- show / manipulate bridge addresses and devices
 .IR DEV " ]"
 
 .ti -8
-.BR "bridge monitor" " [ " all " | " neigh " | " link " ]"
+.BR "bridge monitor" " [ " all " | " neigh " | " link " | " mdb " ]"
 
 .SH OPTIONS
 
@@ -109,6 +124,10 @@ As a rule, the information is statistics or some time values.
 .B fdb 
 - Forwarding Database entry.
 
+.TP
+.B mdb
+- Multicast group database entry.
+
 .TP
 .B vlan
 - VLAN filter list.
@@ -326,6 +345,69 @@ With the
 option, the command becomes verbose.  It prints out the last updated
 and last used time for each entry.
 
+.SH bridge mdb - multicast group database management
+
+.B mdb
+objects contain known IP multicast group addresses on a link.
+
+.P
+The corresponding commands display mdb entries, add new entries,
+and delete old ones.
+
+.SS bridge mdb add - add a new multicast group database entry
+
+This command creates a new mdb entry.
+
+.TP
+.BI dev " DEV"
+the interface where this group address is associated.
+
+.TP
+.BI port " PORT"
+the port whose link is known to have members of this multicast group.
+
+.TP
+.BI grp " GROUP"
+the IP multicast group address whose members reside on the link connected to
+the port.
+
+.B permanent
+- the mdb entry is permanent
+.sp
+
+.B temp
+- the mdb entry is temporary (default)
+.sp
+
+.in -8
+.SS bridge mdb delete - delete a multicast group database entry
+This command removes an existing mdb entry.
+
+.PP
+The arguments are the same as with
+.BR "bridge mdb add" .
+
+.SS bridge mdb show - list multicast group database entries
+
+This command displays the current multicast group membership table. The table
+is populated by IGMP and MLD snooping in the bridge driver automatically. It
+can be altered by
+.B bridge mdb add
+and
+.B bridge mdb del
+commands manually too.
+
+.TP
+.BI dev " DEV"
+the interface only whose entries should be listed. Default is to list all
+bridge interfaces.
+
+.PP
+With the
+.B -details
+option, the command becomes verbose.  It prints out the ports known to have
+a connected router.
+
 .SH bridge vlan - VLAN filter list
 
 .B vlan
@@ -395,7 +477,7 @@ command is the first in the command line and then the object list follows:
 .I OBJECT-LIST
 is the list of object types that we want to monitor.
 It may contain
-.BR link ",  and " fdb "."
+.BR link ",  " fdb ", and " mdb "."
 If no
 .B file
 argument is given,
index 7191bce482ba33e97b923a390262f5c1aff42617..79bc7f108544077012dcf89a9c64feed73798fae 100644 (file)
@@ -97,6 +97,8 @@ replace " } "
 .IR TIME " ] [ "
 .B  rttvar
 .IR TIME " ] [ "
+.B  reordering
+.IR NUMBER " ] [ "
 .B  window
 .IR NUMBER " ] [ "
 .B  cwnd
@@ -110,7 +112,7 @@ replace " } "
 .B  initcwnd
 .IR NUMBER " ] [ "
 .B  initrwnd
-.IR NUMBER " ]"
+.IR NUMBER " ] [ "
 .B  quickack
 .IR BOOL " ]"
 
index 36e46f1bcb3674af6a80a876aa4958678ee50eea..62df3b0b6bc6b5554e49890f9b0ae8f2592a7f43 100644 (file)
@@ -43,6 +43,14 @@ ip-rule \- routing policy database management
 .IR ADDRESS " ] [ "
 .BR prohibit " | " reject " | " unreachable " ] [ " realms
 .RI "[" SRCREALM "/]" DSTREALM " ]"
+.I  SUPPRESSOR
+
+.ti -8
+.IR SUPPRESSOR " := [ "
+.B  suppress_prefixlength
+.IR NUMBER " ] [ "
+.B  suppress_ifgroup
+.IR GROUP " ]"
 
 .ti -8
 .IR TABLE_ID " := [ "
@@ -216,6 +224,15 @@ The options preference and order are synonyms with priority.
 the routing table identifier to lookup if the rule selector matches.
 It is also possible to use lookup instead of table.
 
+.TP
+.BI suppress_prefixlength " NUMBER"
+reject routing decisions that have a prefix length of NUMBER or less.
+
+.TP
+.BI suppress_ifgroup " GROUP"
+reject routing decisions that use a device belonging to the interface
+group GROUP.
+
 .TP
 .BI realms " FROM/TO"
 Realms to select if the rule matched and the routing table lookup
index f26e76468457151546b6d3e523a3578500c69e6f..1eeabd8c89c57b2b77c71dfd55bd20aeafb262ab 100644 (file)
@@ -50,6 +50,7 @@ TCMODULES += em_meta.o
 TCMODULES += q_mqprio.o
 TCMODULES += q_codel.o
 TCMODULES += q_fq_codel.o
+TCMODULES += q_fq.o
 
 ifeq ($(TC_CONFIG_IPSET), y)
   ifeq ($(TC_CONFIG_XT), y)
index 53cbefcf8a99351d45e77d7b74923f19387f037d..300287e948ac60a077243dc6ee50e2fe62ae1553 100644 (file)
@@ -322,9 +322,11 @@ int
 print_police(struct action_util *a, FILE *f, struct rtattr *arg)
 {
        SPRINT_BUF(b1);
+       SPRINT_BUF(b2);
        struct tc_police *p;
        struct rtattr *tb[TCA_POLICE_MAX+1];
        unsigned buffer;
+       unsigned int linklayer;
 
        if (arg == NULL)
                return 0;
@@ -360,6 +362,9 @@ print_police(struct action_util *a, FILE *f, struct rtattr *arg)
        } else
                fprintf(f, " ");
        fprintf(f, "overhead %ub ", p->rate.overhead);
+       linklayer = (p->rate.linklayer & TC_LINKLAYER_MASK);
+       if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
+               fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
        fprintf(f, "\nref %d bind %d\n",p->refcnt, p->bindcnt);
 
        return 0;
index 3c5e72c143a86eebeec3d3d103d335dbc3e43c63..d76600ccd6620b7a62e68cd244ebeb5ef5ffc4c7 100644 (file)
@@ -442,7 +442,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
        struct tc_cbq_wrropt *wrr = NULL;
        struct tc_cbq_fopt *fopt = NULL;
        struct tc_cbq_ovl *ovl = NULL;
+       unsigned int linklayer;
        SPRINT_BUF(b1);
+       SPRINT_BUF(b2);
 
        if (opt == NULL)
                return 0;
@@ -486,6 +488,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
                char buf[64];
                print_rate(buf, sizeof(buf), r->rate);
                fprintf(f, "rate %s ", buf);
+               linklayer = (r->linklayer & TC_LINKLAYER_MASK);
+               if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
+                       fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
                if (show_details) {
                        fprintf(f, "cell %ub ", 1<<r->cell_log);
                        if (r->mpu)
diff --git a/tc/q_fq.c b/tc/q_fq.c
new file mode 100644 (file)
index 0000000..c1f658e
--- /dev/null
+++ b/tc/q_fq.c
@@ -0,0 +1,279 @@
+/*
+ * Fair Queue
+ *
+ *  Copyright (C) 2013 Eric Dumazet <edumazet@google.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+       fprintf(stderr, "Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]\n");
+       fprintf(stderr, "              [ quantum BYTES ] [ initial_quantum BYTES ]\n");
+       fprintf(stderr, "              [ maxrate RATE  ] [ buckets NUMBER ]\n");
+       fprintf(stderr, "              [ [no]pacing ]\n");
+}
+
+static unsigned int ilog2(unsigned int val)
+{
+       unsigned int res = 0;
+
+       val--;
+       while (val) {
+               res++;
+               val >>= 1;
+       }
+       return res;
+}
+
+static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
+                       struct nlmsghdr *n)
+{
+       unsigned int plimit = ~0U;
+       unsigned int flow_plimit = ~0U;
+       unsigned int quantum = ~0U;
+       unsigned int initial_quantum = ~0U;
+       unsigned int buckets = 0;
+       unsigned int maxrate = ~0U;
+       unsigned int defrate = ~0U;
+       int pacing = -1;
+       struct rtattr *tail;
+
+       while (argc > 0) {
+               if (strcmp(*argv, "limit") == 0) {
+                       NEXT_ARG();
+                       if (get_unsigned(&plimit, *argv, 0)) {
+                               fprintf(stderr, "Illegal \"limit\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "flow_limit") == 0) {
+                       NEXT_ARG();
+                       if (get_unsigned(&flow_plimit, *argv, 0)) {
+                               fprintf(stderr, "Illegal \"flow_limit\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "buckets") == 0) {
+                       NEXT_ARG();
+                       if (get_unsigned(&buckets, *argv, 0)) {
+                               fprintf(stderr, "Illegal \"buckets\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "maxrate") == 0) {
+                       NEXT_ARG();
+                       if (get_rate(&maxrate, *argv)) {
+                               fprintf(stderr, "Illegal \"maxrate\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "defrate") == 0) {
+                       NEXT_ARG();
+                       if (get_rate(&defrate, *argv)) {
+                               fprintf(stderr, "Illegal \"defrate\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "quantum") == 0) {
+                       NEXT_ARG();
+                       if (get_unsigned(&quantum, *argv, 0)) {
+                               fprintf(stderr, "Illegal \"quantum\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "initial_quantum") == 0) {
+                       NEXT_ARG();
+                       if (get_unsigned(&initial_quantum, *argv, 0)) {
+                               fprintf(stderr, "Illegal \"initial_quantum\"\n");
+                               return -1;
+                       }
+               } else if (strcmp(*argv, "pacing") == 0) {
+                       pacing = 1;
+               } else if (strcmp(*argv, "nopacing") == 0) {
+                       pacing = 0;
+               } else if (strcmp(*argv, "help") == 0) {
+                       explain();
+                       return -1;
+               } else {
+                       fprintf(stderr, "What is \"%s\"?\n", *argv);
+                       explain();
+                       return -1;
+               }
+               argc--; argv++;
+       }
+
+       tail = NLMSG_TAIL(n);
+       addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+       if (buckets) {
+               unsigned int log = ilog2(buckets);
+
+               addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG,
+                         &log, sizeof(log));
+       }
+       if (plimit != ~0U)
+               addattr_l(n, 1024, TCA_FQ_PLIMIT,
+                         &plimit, sizeof(plimit));
+       if (flow_plimit != ~0U)
+               addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT,
+                         &flow_plimit, sizeof(flow_plimit));
+       if (quantum != ~0U)
+               addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum));
+       if (initial_quantum != ~0U)
+               addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM,
+                         &initial_quantum, sizeof(initial_quantum));
+       if (pacing != -1)
+               addattr_l(n, 1024, TCA_FQ_RATE_ENABLE,
+                         &pacing, sizeof(pacing));
+       if (maxrate != ~0U)
+               addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE,
+                         &maxrate, sizeof(maxrate));
+       if (defrate != ~0U)
+               addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE,
+                         &defrate, sizeof(defrate));
+       tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+       return 0;
+}
+
+static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+       struct rtattr *tb[TCA_FQ_MAX + 1];
+       unsigned int plimit, flow_plimit;
+       unsigned int buckets_log;
+       int pacing;
+       unsigned int rate, quantum;
+       SPRINT_BUF(b1);
+
+       if (opt == NULL)
+               return 0;
+
+       parse_rtattr_nested(tb, TCA_FQ_MAX, opt);
+
+       if (tb[TCA_FQ_PLIMIT] &&
+           RTA_PAYLOAD(tb[TCA_FQ_PLIMIT]) >= sizeof(__u32)) {
+               plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]);
+               fprintf(f, "limit %up ", plimit);
+       }
+       if (tb[TCA_FQ_FLOW_PLIMIT] &&
+           RTA_PAYLOAD(tb[TCA_FQ_FLOW_PLIMIT]) >= sizeof(__u32)) {
+               flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]);
+               fprintf(f, "flow_limit %up ", flow_plimit);
+       }
+       if (tb[TCA_FQ_BUCKETS_LOG] &&
+           RTA_PAYLOAD(tb[TCA_FQ_BUCKETS_LOG]) >= sizeof(__u32)) {
+               buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]);
+               fprintf(f, "buckets %u ", 1U << buckets_log);
+       }
+       if (tb[TCA_FQ_RATE_ENABLE] &&
+           RTA_PAYLOAD(tb[TCA_FQ_RATE_ENABLE]) >= sizeof(int)) {
+               pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]);
+               if (pacing == 0)
+                       fprintf(f, "nopacing ");
+       }
+       if (tb[TCA_FQ_QUANTUM] &&
+           RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) {
+               quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]);
+               fprintf(f, "quantum %u ", quantum);
+       }
+       if (tb[TCA_FQ_INITIAL_QUANTUM] &&
+           RTA_PAYLOAD(tb[TCA_FQ_INITIAL_QUANTUM]) >= sizeof(__u32)) {
+               quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+               fprintf(f, "initial_quantum %u ", quantum);
+       }
+       if (tb[TCA_FQ_FLOW_MAX_RATE] &&
+           RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) {
+               rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]);
+
+               if (rate != ~0U)
+                       fprintf(f, "maxrate %s ", sprint_rate(rate, b1));
+       }
+       if (tb[TCA_FQ_FLOW_DEFAULT_RATE] &&
+           RTA_PAYLOAD(tb[TCA_FQ_FLOW_DEFAULT_RATE]) >= sizeof(__u32)) {
+               rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
+
+               if (rate != 0)
+                       fprintf(f, "defrate %s ", sprint_rate(rate, b1));
+       }
+
+       return 0;
+}
+
+static int fq_print_xstats(struct qdisc_util *qu, FILE *f,
+                          struct rtattr *xstats)
+{
+       struct tc_fq_qd_stats *st;
+
+       if (xstats == NULL)
+               return 0;
+
+       if (RTA_PAYLOAD(xstats) < sizeof(*st))
+               return -1;
+
+       st = RTA_DATA(xstats);
+
+       fprintf(f, "  %u flows (%u inactive, %u throttled)",
+               st->flows, st->inactive_flows, st->throttled_flows);
+
+       if (st->time_next_delayed_flow > 0)
+               fprintf(f, ", next packet delay %llu ns", st->time_next_delayed_flow);
+
+       fprintf(f, "\n  %llu gc, %llu highprio",
+               st->gc_flows, st->highprio_packets);
+
+       if (st->tcp_retrans)
+               fprintf(f, ", %llu retrans", st->tcp_retrans);
+
+       fprintf(f, ", %llu throttled", st->throttled);
+
+       if (st->flows_plimit)
+               fprintf(f, ", %llu flows_plimit", st->flows_plimit);
+
+       if (st->pkts_too_long || st->allocation_errors)
+               fprintf(f, "\n  %llu too long pkts, %llu alloc errors\n",
+                       st->pkts_too_long, st->allocation_errors);
+
+       return 0;
+}
+
+struct qdisc_util fq_qdisc_util = {
+       .id             = "fq",
+       .parse_qopt     = fq_parse_opt,
+       .print_qopt     = fq_print_opt,
+       .print_xstats   = fq_print_xstats,
+};
index 9321c0ada2bc780ac622a70ecfae2648becdb40f..6737ddb0c0c6d67f5546326c7243f84f25ef86e5 100644 (file)
 static void explain(void)
 {
        fprintf(stderr, "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
+               "                      [direct_qlen P]\n"
                " default  minor id of class to which unclassified packets are sent {0}\n"
                " r2q      DRR quantums are computed as rate in Bps/r2q {10}\n"
                " debug    string of 16 numbers each 0-3 {0}\n\n"
+               " direct_qlen  Limit of the direct queue {in packets}\n"
                "... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]\n"
                "                      [prio P] [slot S] [pslot PS]\n"
                "                      [ceil R2] [cburst B2] [mtu MTU] [quantum Q]\n"
@@ -108,6 +110,7 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
        unsigned mtu;
        unsigned short mpu = 0;
        unsigned short overhead = 0;
+       unsigned int direct_qlen = ~0U;
        unsigned int linklayer  = LINKLAYER_ETHERNET; /* Assume ethernet */
        struct rtattr *tail;
 
@@ -125,6 +128,11 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                        if (get_u32(&mtu, *argv, 10)) {
                                explain1("mtu"); return -1;
                        }
+               } else if (matches(*argv, "direct_qlen") == 0) {
+                       NEXT_ARG();
+                       if (get_u32(&direct_qlen, *argv, 10)) {
+                               explain1("direct_qlen"); return -1;
+                       }
                } else if (matches(*argv, "mpu") == 0) {
                        NEXT_ARG();
                        if (get_u16(&mpu, *argv, 10)) {
@@ -230,6 +238,9 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
        opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
 
        tail = NLMSG_TAIL(n);
+       if (direct_qlen != ~0U)
+               addattr_l(n, 1024, TCA_HTB_DIRECT_QLEN,
+                         &direct_qlen, sizeof(direct_qlen));
        addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
        addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
        addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
@@ -240,18 +251,20 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
 
 static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
-       struct rtattr *tb[TCA_HTB_RTAB+1];
+       struct rtattr *tb[TCA_HTB_MAX + 1];
        struct tc_htb_opt *hopt;
        struct tc_htb_glob *gopt;
        double buffer,cbuffer;
+       unsigned int linklayer;
        SPRINT_BUF(b1);
        SPRINT_BUF(b2);
        SPRINT_BUF(b3);
+       SPRINT_BUF(b4);
 
        if (opt == NULL)
                return 0;
 
-       parse_rtattr_nested(tb, TCA_HTB_RTAB, opt);
+       parse_rtattr_nested(tb, TCA_HTB_MAX, opt);
 
        if (tb[TCA_HTB_PARMS]) {
                hopt = RTA_DATA(tb[TCA_HTB_PARMS]);
@@ -268,6 +281,9 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
                buffer = tc_calc_xmitsize(hopt->rate.rate, hopt->buffer);
                fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1));
                cbuffer = tc_calc_xmitsize(hopt->ceil.rate, hopt->cbuffer);
+               linklayer = (hopt->rate.linklayer & TC_LINKLAYER_MASK);
+               if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
+                       fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b4));
                if (show_details) {
                        fprintf(f, "burst %s/%u mpu %s overhead %s ",
                                sprint_size(buffer, b1),
@@ -297,6 +313,12 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
                if (show_details)
                        fprintf(f," ver %d.%d",gopt->version >> 16,gopt->version & 0xffff);
        }
+       if (tb[TCA_HTB_DIRECT_QLEN] &&
+           RTA_PAYLOAD(tb[TCA_HTB_DIRECT_QLEN]) >= sizeof(__u32)) {
+               __u32 direct_qlen = rta_getattr_u32(tb[TCA_HTB_DIRECT_QLEN]);
+
+               fprintf(f, " direct_qlen %u", direct_qlen);
+       }
        return 0;
 }
 
index 72cfff669faa4b4a387d296c2f23be42e1bc5b96..34784a41c9e35747e5fd6aa1bc81227845f5d056 100644 (file)
@@ -239,10 +239,12 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
        struct rtattr *tb[TCA_TBF_PTAB+1];
        struct tc_tbf_qopt *qopt;
+       unsigned int linklayer;
        double buffer, mtu;
        double latency;
        SPRINT_BUF(b1);
        SPRINT_BUF(b2);
+       SPRINT_BUF(b3);
 
        if (opt == NULL)
                return 0;
@@ -294,6 +296,9 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
        if (qopt->rate.overhead) {
                fprintf(f, "overhead %d", qopt->rate.overhead);
        }
+       linklayer = (qopt->rate.linklayer & TC_LINKLAYER_MASK);
+       if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
+               fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b3));
 
        return 0;
 }
index 85b072ef45ce01e66102a728b40f00ce15c6ec5a..a52433700a0962d2e6533e21bd7703ff9f87f255 100644 (file)
@@ -102,6 +102,21 @@ static unsigned tc_adjust_size(unsigned sz, unsigned mpu, enum link_layer linkla
        }
 }
 
+/* Notice, the rate table calculated here, have gotten replaced in the
+ * kernel and is no-longer used for lookups.
+ *
+ * This happened in kernel release v3.8 caused by kernel
+ *  - commit 56b765b79 ("htb: improved accuracy at high rates").
+ * This change unfortunately caused breakage of tc overhead and
+ * linklayer parameters.
+ *
+ * Kernel overhead handling got fixed in kernel v3.10 by
+ * - commit 01cb71d2d47 (net_sched: restore "overhead xxx" handling)
+ *
+ * Kernel linklayer handling got fixed in kernel v3.11 by
+ * - commit 8a8e3d84b17 (net_sched: restore "linklayer atm" handling)
+ */
+
 /*
    rtab[pkt_len>>cell_log] = pkt_xmit_time
  */
@@ -131,6 +146,7 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
 
        r->cell_align=-1; // Due to the sz calc
        r->cell_log=cell_log;
+       r->linklayer = (linklayer & TC_LINKLAYER_MASK);
        return cell_log;
 }
 
index f3bf5b57064aca5acb6bf7a2fe924dee5ef3c781..3002a56c3b09f926e0b94e2eb7794bde98e0cfac 100644 (file)
@@ -137,15 +137,15 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
        if (est.ewma_log)
                addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));
 
-       if (q) {
-               if (!q->parse_qopt) {
-                       fprintf(stderr, "qdisc '%s' does not support option parsing\n", k);
-                       return -1;
-               }
-               if (q->parse_qopt(q, argc, argv, &req.n))
-                       return 1;
-       } else {
-               if (argc) {
+       if (argc) {
+               if (q) {
+                       if (!q->parse_qopt) {
+                               fprintf(stderr, "qdisc '%s' does not support option parsing\n", k);
+                               return -1;
+                       }
+                       if (q->parse_qopt(q, argc, argv, &req.n))
+                               return 1;
+               } else {
                        if (matches(*argv, "help") == 0)
                                usage();
 
index 8114c97c4143e307c04c722b6b847e6fae928d5c..be3ed071b321366db403f1d666814e734705e79b 100644 (file)
@@ -171,20 +171,24 @@ int get_rate(unsigned *rate, const char *str)
        return 0;
 }
 
-void print_rate(char *buf, int len, __u32 rate)
+void print_rate(char *buf, int len, __u64 rate)
 {
        double tmp = (double)rate*8;
        extern int use_iec;
 
        if (use_iec) {
-               if (tmp >= 1000.0*1024.0*1024.0)
+               if (tmp >= 1000.0*1024.0*1024.0*1024.0)
+                       snprintf(buf, len, "%.0fGibit", tmp/(1024.0*1024.0*1024.0));
+               else if (tmp >= 1000.0*1024.0*1024.0)
                        snprintf(buf, len, "%.0fMibit", tmp/(1024.0*1024.0));
                else if (tmp >= 1000.0*1024)
                        snprintf(buf, len, "%.0fKibit", tmp/1024);
                else
                        snprintf(buf, len, "%.0fbit", tmp);
        } else {
-               if (tmp >= 1000.0*1000000.0)
+               if (tmp >= 1000.0*1000000000.0)
+                       snprintf(buf, len, "%.0fGbit", tmp/1000000000.0);
+               else if (tmp >= 1000.0*1000000.0)
                        snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
                else if (tmp >= 1000.0 * 1000.0)
                        snprintf(buf, len, "%.0fKbit", tmp/1000.0);
@@ -193,7 +197,7 @@ void print_rate(char *buf, int len, __u32 rate)
        }
 }
 
-char * sprint_rate(__u32 rate, char *buf)
+char * sprint_rate(__u64 rate, char *buf)
 {
        print_rate(buf, SPRINT_BSIZE-1, rate);
        return buf;
@@ -460,9 +464,19 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
                        q.drops, q.overlimits, q.requeues);
        }
 
-       if (tbs[TCA_STATS_RATE_EST]) {
+       if (tbs[TCA_STATS_RATE_EST64]) {
+               struct gnet_stats_rate_est64 re = {0};
+
+               memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST64]),
+                      MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST64]),
+                          sizeof(re)));
+               fprintf(fp, "\n%srate %s %llupps ",
+                       prefix, sprint_rate(re.bps, b1), re.pps);
+       } else if (tbs[TCA_STATS_RATE_EST]) {
                struct gnet_stats_rate_est re = {0};
-               memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
+
+               memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]),
+                      MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
                fprintf(fp, "\n%srate %s %upps ",
                        prefix, sprint_rate(re.bps, b1), re.pps);
        }
index 4f544363393b9d17e55f86bb828bbc987f444d6a..7c3709f5066cd9138456b7f37d443bca1d3c297d 100644 (file)
@@ -63,12 +63,12 @@ extern int get_size_and_cell(unsigned *size, int *cell_log, char *str);
 extern int get_time(unsigned *time, const char *str);
 extern int get_linklayer(unsigned *val, const char *arg);
 
-extern void print_rate(char *buf, int len, __u32 rate);
+extern void print_rate(char *buf, int len, __u64 rate);
 extern void print_size(char *buf, int len, __u32 size);
 extern void print_qdisc_handle(char *buf, int len, __u32 h);
 extern void print_time(char *buf, int len, __u32 time);
 extern void print_linklayer(char *buf, int len, unsigned linklayer);
-extern char * sprint_rate(__u32 rate, char *buf);
+extern char * sprint_rate(__u64 rate, char *buf);
 extern char * sprint_size(__u32 size, char *buf);
 extern char * sprint_qdisc_handle(__u32 h, char *buf);
 extern char * sprint_tc_classid(__u32 h, char *buf);