diff --git a/bridge/fdb.c b/bridge/fdb.c index 591fbbed..e2e53f1f 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -30,7 +30,7 @@ int filter_index; 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" " [ port PORT] [ vni VNI ] [via DEV]\n"); fprintf(stderr, " bridge fdb {show} [ dev DEV ]\n"); @@ -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); if (matches(*argv, "append") == 0) 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) return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1); if (matches(*argv, "show") == 0 || diff --git a/doc/ip-cref.tex b/doc/ip-cref.tex index d8fed66e..f062b3af 100644 --- a/doc/ip-cref.tex +++ b/doc/ip-cref.tex @@ -2542,13 +2542,15 @@ Namely, the \verb|monitor| command is the first in the command line and then the object list follows: \begin{verbatim} - ip monitor [ file FILE ] [ all | OBJECT-LIST ] + ip monitor [ file FILE ] [ all | OBJECT-LIST ] [ label ] \end{verbatim} -\verb|OBJECT-LIST| is the list of object types that we want to monitor. -It may contain \verb|link|, \verb|address| and \verb|route|. -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. +\verb|OBJECT-LIST| is the list of object types that we want to +monitor. It may contain \verb|link|, \verb|address| and \verb|route|. +Specifying \verb|label| indicates that output lines should be labelled +with the type of object being printed --- this happens by default if +\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, but opens the file containing RTNETLINK messages saved in binary format diff --git a/include/SNAPSHOT.h b/include/SNAPSHOT.h index 63b857de..8f896b78 100644 --- a/include/SNAPSHOT.h +++ b/include/SNAPSHOT.h @@ -1 +1 @@ -static const char SNAPSHOT[] = "130716"; +static const char SNAPSHOT[] = "130903"; diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index dbd71b0c..09d62b92 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -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; diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c index 5b4b868b..ec511065 100644 --- a/ip/iplink_macvlan.c +++ b/ip/iplink_macvlan.c @@ -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" diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index 86c473e9..70f2a7ad 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -29,14 +29,13 @@ int prefix_banner; 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, " neigh | netconf\n"); fprintf(stderr, "FILE := file FILENAME\n"); 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); @@ -157,6 +163,8 @@ int do_ipmonitor(int argc, char **argv) if (matches(*argv, "file") == 0) { NEXT_ARG(); file = *argv; + } else if (matches(*argv, "label") == 0) { + prefix_banner = 1; } else if (matches(*argv, "link") == 0) { llink=1; groups = 0; diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 794a4988..89dda3ff 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -167,7 +167,7 @@ static int netns_exec(int argc, char **argv) fprintf(stderr, "unshare failed: %s\n", strerror(errno)); 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)) { fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", strerror(errno)); @@ -205,11 +205,15 @@ static int netns_exec(int argc, char **argv) exit(1); } - /* If child failed, propogate 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); } } @@ -405,7 +409,7 @@ static int netns_add(int argc, char **argv) /* Create the base netns directory if it doesn't exist */ 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 * namespace file in one namespace will unmount the network namespace * file in all namespaces allowing the network namespace to be freed diff --git a/ip/ipntable.c b/ip/ipntable.c index 67b199e4..193e50cf 100644 --- a/ip/ipntable.c +++ b/ip/ipntable.c @@ -305,7 +305,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) if (!namep) missarg("NAME"); 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); } diff --git a/ip/iproute.c b/ip/iproute.c index b069f1e0..25a56d1f 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -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"); diff --git a/ip/iptunnel.c b/ip/iptunnel.c index 43f85855..40186d3d 100644 --- a/ip/iptunnel.c +++ b/ip/iptunnel.c @@ -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; } diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index 0a3a9fb6..411d9d53 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -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 "); diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 394254d8..d5324f8e 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -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); } diff --git a/ip/link_veth.c b/ip/link_veth.c index 3d19b01f..7730f394 100644 --- a/ip/link_veth.c +++ b/ip/link_veth.c @@ -19,9 +19,8 @@ static void usage(void) { - printf("Usage: ip link type veth " - "[peer ]\nTo get type " - "'ip link add help'\n"); + printf("Usage: ip link type veth [peer ]\n" + "To get type 'ip link add help'\n"); } static int veth_parse_opt(struct link_util *lu, int argc, char **argv, diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in index 7191bce4..79bc7f10 100644 --- a/man/man8/ip-route.8.in +++ b/man/man8/ip-route.8.in @@ -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 " ]" diff --git a/tc/m_ipt.c b/tc/m_ipt.c index dc2dedc0..bb016f17 100644 --- a/tc/m_ipt.c +++ b/tc/m_ipt.c @@ -415,7 +415,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, } 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; } diff --git a/tc/m_mirred.c b/tc/m_mirred.c index 1ef9f2bd..dc231d7c 100644 --- a/tc/m_mirred.c +++ b/tc/m_mirred.c @@ -105,7 +105,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p, } else if (!mirror && matches(*argv, "mirror") == 0) { mirror=1; if (redir) { - fprintf(stderr, "Cant have both mirror and redir\n"); + fprintf(stderr, "Can't have both mirror and redir\n"); return -1; } p.eaction = TCA_EGRESS_MIRROR; @@ -114,7 +114,7 @@ parse_egress(struct action_util *a, int *argc_p, char ***argv_p, } else if (!redir && matches(*argv, "redirect") == 0) { redir=1; if (mirror) { - fprintf(stderr, "Cant have both mirror and redir\n"); + fprintf(stderr, "Can't have both mirror and redir\n"); return -1; } p.eaction = TCA_EGRESS_REDIR; @@ -215,14 +215,14 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p, char **argv = *argv_p; if (argc < 0) { - fprintf(stderr,"mirred bad arguement count %d\n", argc); + fprintf(stderr,"mirred bad argument count %d\n", argc); return -1; } if (matches(*argv, "mirred") == 0) { NEXT_ARG(); } else { - fprintf(stderr,"mirred bad arguement %s\n", *argv); + fprintf(stderr,"mirred bad argument %s\n", *argv); return -1; } diff --git a/tc/m_police.c b/tc/m_police.c index 53cbefcf..300287e9 100644 --- a/tc/m_police.c +++ b/tc/m_police.c @@ -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; diff --git a/tc/m_xt.c b/tc/m_xt.c index e9186709..27029c1b 100644 --- a/tc/m_xt.c +++ b/tc/m_xt.c @@ -147,7 +147,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, } 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; } diff --git a/tc/m_xt_old.c b/tc/m_xt_old.c index 554e4ed4..4d61a5ab 100644 --- a/tc/m_xt_old.c +++ b/tc/m_xt_old.c @@ -232,7 +232,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, } 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; } diff --git a/tc/q_cbq.c b/tc/q_cbq.c index 3c5e72c1..d76600cc 100644 --- a/tc/q_cbq.c +++ b/tc/q_cbq.c @@ -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<cell_log); if (r->mpu) diff --git a/tc/q_htb.c b/tc/q_htb.c index 9321c0ad..7b6f9082 100644 --- a/tc/q_htb.c +++ b/tc/q_htb.c @@ -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_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; @@ -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); 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), diff --git a/tc/q_tbf.c b/tc/q_tbf.c index 72cfff66..34784a41 100644 --- a/tc/q_tbf.c +++ b/tc/q_tbf.c @@ -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; } diff --git a/tc/tc_core.c b/tc/tc_core.c index 85b072ef..a5243370 100644 --- a/tc/tc_core.c +++ b/tc/tc_core.c @@ -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; } diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c index f3bf5b57..3002a56c 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -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();