Commit c5e3ee2c authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'master' into net-next-3.11

parents b1d0525f d3c77c46
...@@ -30,7 +30,7 @@ int filter_index; ...@@ -30,7 +30,7 @@ int filter_index;
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "Usage: bridge fdb { add | append | del } ADDR dev DEV {self|master} [ temp ]\n" fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ]\n"
" [router] [ dst IPADDR] [ vlan VID ]\n" " [router] [ dst IPADDR] [ vlan VID ]\n"
" [ port PORT] [ vni VNI ] [via DEV]\n"); " [ port PORT] [ vni VNI ] [via DEV]\n");
fprintf(stderr, " bridge fdb {show} [ dev DEV ]\n"); fprintf(stderr, " bridge fdb {show} [ dev DEV ]\n");
...@@ -334,6 +334,8 @@ int do_fdb(int argc, char **argv) ...@@ -334,6 +334,8 @@ int do_fdb(int argc, char **argv)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1); return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
if (matches(*argv, "append") == 0) if (matches(*argv, "append") == 0)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_APPEND, argc-1, argv+1); return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_APPEND, argc-1, argv+1);
if (matches(*argv, "replace") == 0)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1);
if (matches(*argv, "delete") == 0) if (matches(*argv, "delete") == 0)
return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1); return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1);
if (matches(*argv, "show") == 0 || if (matches(*argv, "show") == 0 ||
......
...@@ -2542,13 +2542,15 @@ Namely, ...@@ -2542,13 +2542,15 @@ Namely,
the \verb|monitor| command is the first in the command line and then the \verb|monitor| command is the first in the command line and then
the object list follows: the object list follows:
\begin{verbatim} \begin{verbatim}
ip monitor [ file FILE ] [ all | OBJECT-LIST ] ip monitor [ file FILE ] [ all | OBJECT-LIST ] [ label ]
\end{verbatim} \end{verbatim}
\verb|OBJECT-LIST| is the list of object types that we want to monitor. \verb|OBJECT-LIST| is the list of object types that we want to
It may contain \verb|link|, \verb|address| and \verb|route|. monitor. It may contain \verb|link|, \verb|address| and \verb|route|.
If no \verb|file| argument is given, \verb|ip| opens RTNETLINK, Specifying \verb|label| indicates that output lines should be labelled
listens on it and dumps state changes in the format described with the type of object being printed --- this happens by default if
in previous sections. \verb|all| is specified. If no \verb|file| argument is given,
\verb|ip| opens RTNETLINK, listens on it and dumps state changes in
the format described in previous sections.
If a file name is given, it does not listen on RTNETLINK, If a file name is given, it does not listen on RTNETLINK,
but opens the file containing RTNETLINK messages saved in binary format but opens the file containing RTNETLINK messages saved in binary format
......
static const char SNAPSHOT[] = "130716"; static const char SNAPSHOT[] = "130903";
...@@ -73,9 +73,17 @@ struct tc_estimator { ...@@ -73,9 +73,17 @@ struct tc_estimator {
#define TC_H_ROOT (0xFFFFFFFFU) #define TC_H_ROOT (0xFFFFFFFFU)
#define TC_H_INGRESS (0xFFFFFFF1U) #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 { struct tc_ratespec {
unsigned char cell_log; unsigned char cell_log;
unsigned char __reserved; __u8 linklayer; /* lower 4 bits */
unsigned short overhead; unsigned short overhead;
short cell_align; short cell_align;
unsigned short mpu; unsigned short mpu;
......
...@@ -79,7 +79,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[] ...@@ -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)) RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
return; return;
mode = rta_getattr_u32(tb[IFLA_VLAN_ID]); mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
fprintf(f, " mode %s ", fprintf(f, " mode %s ",
mode == MACVLAN_MODE_PRIVATE ? "private" mode == MACVLAN_MODE_PRIVATE ? "private"
: mode == MACVLAN_MODE_VEPA ? "vepa" : mode == MACVLAN_MODE_VEPA ? "vepa"
......
...@@ -29,14 +29,13 @@ int prefix_banner; ...@@ -29,14 +29,13 @@ int prefix_banner;
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]\n"); fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] [ label ]\n");
fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n"); fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
fprintf(stderr, " neigh | netconf\n"); fprintf(stderr, " neigh | netconf\n");
fprintf(stderr, "FILE := file FILENAME\n"); fprintf(stderr, "FILE := file FILENAME\n");
exit(-1); exit(-1);
} }
static int accept_msg(const struct sockaddr_nl *who, static int accept_msg(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg) struct nlmsghdr *n, void *arg)
{ {
...@@ -88,6 +87,13 @@ static int accept_msg(const struct sockaddr_nl *who, ...@@ -88,6 +87,13 @@ static int accept_msg(const struct sockaddr_nl *who,
} }
if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH || if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
n->nlmsg_type == RTM_GETNEIGH) { 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) if (prefix_banner)
fprintf(fp, "[NEIGH]"); fprintf(fp, "[NEIGH]");
print_neigh(who, n, arg); print_neigh(who, n, arg);
...@@ -157,6 +163,8 @@ int do_ipmonitor(int argc, char **argv) ...@@ -157,6 +163,8 @@ int do_ipmonitor(int argc, char **argv)
if (matches(*argv, "file") == 0) { if (matches(*argv, "file") == 0) {
NEXT_ARG(); NEXT_ARG();
file = *argv; file = *argv;
} else if (matches(*argv, "label") == 0) {
prefix_banner = 1;
} else if (matches(*argv, "link") == 0) { } else if (matches(*argv, "link") == 0) {
llink=1; llink=1;
groups = 0; groups = 0;
......
...@@ -167,7 +167,7 @@ static int netns_exec(int argc, char **argv) ...@@ -167,7 +167,7 @@ static int netns_exec(int argc, char **argv)
fprintf(stderr, "unshare failed: %s\n", strerror(errno)); fprintf(stderr, "unshare failed: %s\n", strerror(errno));
return -1; return -1;
} }
/* Don't let any mounts propogate back to the parent */ /* Don't let any mounts propagate back to the parent */
if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) {
fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n",
strerror(errno)); strerror(errno));
...@@ -205,11 +205,15 @@ static int netns_exec(int argc, char **argv) ...@@ -205,11 +205,15 @@ static int netns_exec(int argc, char **argv)
exit(1); exit(1);
} }
/* If child failed, propogate status */ if (WIFEXITED(status)) {
if (WIFEXITED(status)) /* ip must return the status of the child,
exit(WEXITSTATUS(status)); * 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);
} }
} }
...@@ -405,7 +409,7 @@ static int netns_add(int argc, char **argv) ...@@ -405,7 +409,7 @@ static int netns_add(int argc, char **argv)
/* Create the base netns directory if it doesn't exist */ /* Create the base netns directory if it doesn't exist */
mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
/* Make it possible for network namespace mounts to propogate between /* Make it possible for network namespace mounts to propagate between
* mount namespaces. This makes it likely that a unmounting a network * mount namespaces. This makes it likely that a unmounting a network
* namespace file in one namespace will unmount the network namespace * namespace file in one namespace will unmount the network namespace
* file in all namespaces allowing the network namespace to be freed * file in all namespaces allowing the network namespace to be freed
......
...@@ -305,7 +305,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) ...@@ -305,7 +305,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv)
if (!namep) if (!namep)
missarg("NAME"); missarg("NAME");
if (!threshsp && !gc_intp && !parms_change) { if (!threshsp && !gc_intp && !parms_change) {
fprintf(stderr, "Not enough information: changable attributes required.\n"); fprintf(stderr, "Not enough information: changeable attributes required.\n");
exit(-1); exit(-1);
} }
......
...@@ -63,7 +63,7 @@ static void usage(void) ...@@ -63,7 +63,7 @@ static void usage(void)
fprintf(stderr, " ip route restore\n"); fprintf(stderr, " ip route restore\n");
fprintf(stderr, " ip route showdump\n"); fprintf(stderr, " ip route showdump\n");
fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\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, " [ mark NUMBER ]\n");
fprintf(stderr, " ip route { add | del | change | append | replace } ROUTE\n"); fprintf(stderr, " ip route { add | del | change | append | replace } ROUTE\n");
fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n"); fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n");
...@@ -76,7 +76,7 @@ static void usage(void) ...@@ -76,7 +76,7 @@ static void usage(void)
fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n"); fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"); fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\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, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");
fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n");
fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n");
......
...@@ -280,7 +280,7 @@ static int do_add(int cmd, int argc, char **argv) ...@@ -280,7 +280,7 @@ static int do_add(int cmd, int argc, char **argv)
return -1; return -1;
if (p.iph.ttl && p.iph.frag_off == 0) { 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; return -1;
} }
......
...@@ -856,7 +856,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo, ...@@ -856,7 +856,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
if (flags) if (flags)
fprintf(fp, "%x", 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]); __u32 extra_flags = *(__u32 *)RTA_DATA(tb[XFRMA_SA_EXTRA_FLAGS]);
fprintf(fp, "extra_flag "); fprintf(fp, "extra_flag ");
......
...@@ -233,7 +233,7 @@ get_failed: ...@@ -233,7 +233,7 @@ get_failed:
} }
if (ttl && pmtudisc == 0) { if (ttl && pmtudisc == 0) {
fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n"); fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
exit(-1); exit(-1);
} }
......
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
static void usage(void) static void usage(void)
{ {
printf("Usage: ip link <options> type veth " printf("Usage: ip link <options> type veth [peer <options>]\n"
"[peer <options>]\nTo get <options> type " "To get <options> type 'ip link add help'\n");
"'ip link add help'\n");
} }
static int veth_parse_opt(struct link_util *lu, int argc, char **argv, static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
......
...@@ -97,6 +97,8 @@ replace " } " ...@@ -97,6 +97,8 @@ replace " } "
.IR TIME " ] [ " .IR TIME " ] [ "
.B rttvar .B rttvar
.IR TIME " ] [ " .IR TIME " ] [ "
.B reordering
.IR NUMBER " ] [ "
.B window .B window
.IR NUMBER " ] [ " .IR NUMBER " ] [ "
.B cwnd .B cwnd
...@@ -110,7 +112,7 @@ replace " } " ...@@ -110,7 +112,7 @@ replace " } "
.B initcwnd .B initcwnd
.IR NUMBER " ] [ " .IR NUMBER " ] [ "
.B initrwnd .B initrwnd
.IR NUMBER " ]" .IR NUMBER " ] [ "
.B quickack .B quickack
.IR BOOL " ]" .IR BOOL " ]"
......
...@@ -415,7 +415,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, ...@@ -415,7 +415,7 @@ static int parse_ipt(struct action_util *a,int *argc_p,
} }
if (argc <= 2) { if (argc <= 2) {
fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc); fprintf(stderr,"bad arguments to ipt %d vs %d \n", argc, rargc);
return -1; return -1;
} }
......
...@@ -105,7 +105,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p, ...@@ -105,7 +105,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p,
} else if (!mirror && matches(*argv, "mirror") == 0) { } else if (!mirror && matches(*argv, "mirror") == 0) {
mirror=1; mirror=1;
if (redir) { if (redir) {
fprintf(stderr, "Cant have both mirror and redir\n"); fprintf(stderr, "Can't have both mirror and redir\n");
return -1; return -1;
} }
p.eaction = TCA_EGRESS_MIRROR; p.eaction = TCA_EGRESS_MIRROR;
...@@ -114,7 +114,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p, ...@@ -114,7 +114,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p,
} else if (!redir && matches(*argv, "redirect") == 0) { } else if (!redir && matches(*argv, "redirect") == 0) {
redir=1; redir=1;
if (mirror) { if (mirror) {
fprintf(stderr, "Cant have both mirror and redir\n"); fprintf(stderr, "Can't have both mirror and redir\n");
return -1; return -1;
} }
p.eaction = TCA_EGRESS_REDIR; p.eaction = TCA_EGRESS_REDIR;
...@@ -215,14 +215,14 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p, ...@@ -215,14 +215,14 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p,
char **argv = *argv_p; char **argv = *argv_p;
if (argc < 0) { if (argc < 0) {
fprintf(stderr,"mirred bad arguement count %d\n", argc); fprintf(stderr,"mirred bad argument count %d\n", argc);
return -1; return -1;
} }
if (matches(*argv, "mirred") == 0) { if (matches(*argv, "mirred") == 0) {
NEXT_ARG(); NEXT_ARG();
} else { } else {
fprintf(stderr,"mirred bad arguement %s\n", *argv); fprintf(stderr,"mirred bad argument %s\n", *argv);
return -1; return -1;
} }
......
...@@ -322,9 +322,11 @@ int ...@@ -322,9 +322,11 @@ int
print_police(struct action_util *a, FILE *f, struct rtattr *arg) print_police(struct action_util *a, FILE *f, struct rtattr *arg)
{ {
SPRINT_BUF(b1); SPRINT_BUF(b1);
SPRINT_BUF(b2);
struct tc_police *p; struct tc_police *p;
struct rtattr *tb[TCA_POLICE_MAX+1]; struct rtattr *tb[TCA_POLICE_MAX+1];
unsigned buffer; unsigned buffer;
unsigned int linklayer;
if (arg == NULL) if (arg == NULL)
return 0; return 0;
...@@ -360,6 +362,9 @@ print_police(struct action_util *a, FILE *f, struct rtattr *arg) ...@@ -360,6 +362,9 @@ print_police(struct action_util *a, FILE *f, struct rtattr *arg)
} else } else
fprintf(f, " "); fprintf(f, " ");
fprintf(f, "overhead %ub ", p->rate.overhead); 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); fprintf(f, "\nref %d bind %d\n",p->refcnt, p->bindcnt);
return 0; return 0;
......
...@@ -147,7 +147,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, ...@@ -147,7 +147,7 @@ static int parse_ipt(struct action_util *a,int *argc_p,
} }
if (argc <= 2) { if (argc <= 2) {
fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc); fprintf(stderr,"bad arguments to ipt %d vs %d \n", argc, rargc);
return -1; return -1;
} }
......
...@@ -232,7 +232,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, ...@@ -232,7 +232,7 @@ static int parse_ipt(struct action_util *a,int *argc_p,
} }
if (argc <= 2) { if (argc <= 2) {
fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc); fprintf(stderr,"bad arguments to ipt %d vs %d \n", argc, rargc);
return -1; return -1;
} }
......
...@@ -442,7 +442,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -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_wrropt *wrr = NULL;
struct tc_cbq_fopt *fopt = NULL; struct tc_cbq_fopt *fopt = NULL;
struct tc_cbq_ovl *ovl = NULL; struct tc_cbq_ovl *ovl = NULL;
unsigned int linklayer;
SPRINT_BUF(b1); SPRINT_BUF(b1);
SPRINT_BUF(b2);
if (opt == NULL) if (opt == NULL)
return 0; return 0;
...@@ -486,6 +488,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -486,6 +488,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
char buf[64]; char buf[64];
print_rate(buf, sizeof(buf), r->rate); print_rate(buf, sizeof(buf), r->rate);
fprintf(f, "rate %s ", buf); 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) { if (show_details) {
fprintf(f, "cell %ub ", 1<<r->cell_log); fprintf(f, "cell %ub ", 1<<r->cell_log);
if (r->mpu) if (r->mpu)
......
...@@ -244,9 +244,11 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -244,9 +244,11 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
struct tc_htb_opt *hopt; struct tc_htb_opt *hopt;
struct tc_htb_glob *gopt; struct tc_htb_glob *gopt;
double buffer,cbuffer; double buffer,cbuffer;
unsigned int linklayer;
SPRINT_BUF(b1); SPRINT_BUF(b1);
SPRINT_BUF(b2); SPRINT_BUF(b2);
SPRINT_BUF(b3); SPRINT_BUF(b3);
SPRINT_BUF(b4);
if (opt == NULL) if (opt == NULL)
return 0; return 0;
...@@ -268,6 +270,9 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -268,6 +270,9 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
buffer = tc_calc_xmitsize(hopt->rate.rate, hopt->buffer); buffer = tc_calc_xmitsize(hopt->rate.rate, hopt->buffer);
fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1)); fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1));
cbuffer = tc_calc_xmitsize(hopt->ceil.rate, hopt->cbuffer); 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) { if (show_details) {
fprintf(f, "burst %s/%u mpu %s overhead %s ", fprintf(f, "burst %s/%u mpu %s overhead %s ",
sprint_size(buffer, b1), sprint_size(buffer, b1),
......
...@@ -239,10 +239,12 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -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 rtattr *tb[TCA_TBF_PTAB+1];
struct tc_tbf_qopt *qopt; struct tc_tbf_qopt *qopt;
unsigned int linklayer;
double buffer, mtu; double buffer, mtu;
double latency; double latency;
SPRINT_BUF(b1); SPRINT_BUF(b1);
SPRINT_BUF(b2); SPRINT_BUF(b2);
SPRINT_BUF(b3);
if (opt == NULL) if (opt == NULL)
return 0; return 0;
...@@ -294,6 +296,9 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) ...@@ -294,6 +296,9 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (qopt->rate.overhead) { if (qopt->rate.overhead) {
fprintf(f, "overhead %d", 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; return 0;
} }
......
...@@ -102,6 +102,21 @@ static unsigned tc_adjust_size(unsigned sz, unsigned mpu, enum link_layer linkla ...@@ -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 rtab[pkt_len>>cell_log] = pkt_xmit_time
*/ */
...@@ -131,6 +146,7 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab, ...@@ -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_align=-1; // Due to the sz calc
r->cell_log=cell_log; r->cell_log=cell_log;
r->linklayer = (linklayer & TC_LINKLAYER_MASK);
return cell_log; return cell_log;
} }
......
...@@ -137,15 +137,15 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -137,15 +137,15 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
if (est.ewma_log) if (est.ewma_log)
addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));
if (q) { if (argc) {
if (!q->parse_qopt) { if (q) {
fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); if (!q->parse_qopt) {
return -1; fprintf(stderr, "qdisc '%s' does not support option parsing\n", k);
} return -1;
if (q->parse_qopt(q, argc, argv, &req.n)) }
return 1; if (q->parse_qopt(q, argc, argv, &req.n))
} else { return 1;
if (argc) { } else {
if (matches(*argv, "help") == 0) if (matches(*argv, "help") == 0)
usage(); usage();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment