From 542b0cc759c6d3456d16c05c886b367e1b2f1e73 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 13 Jan 2015 18:06:16 -0800 Subject: [PATCH 1/9] neighbor: check return values Need to check for invalid address and buffer overrun in ip neigh command with invalid paramters. --- ip/ipneigh.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ip/ipneigh.c b/ip/ipneigh.c index 6be79e1a..eeec7bdd 100644 --- a/ip/ipneigh.c +++ b/ip/ipneigh.c @@ -157,14 +157,19 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) exit(-1); } req.ndm.ndm_family = dst.family; - addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen); + if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0) + return -1; if (lla && strcmp(lla, "null")) { char llabuf[20]; int l; l = ll_addr_a2n(llabuf, sizeof(llabuf), lla); - addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l); + if (l < 0) + return -1; + + if (addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l) < 0) + return -1; } ll_init_map(&rth); From d36d9d41d6e66c130b0632b82ea74c3ae4d0fbe3 Mon Sep 17 00:00:00 2001 From: Reese Moore Date: Wed, 4 Feb 2015 14:04:48 -0500 Subject: [PATCH 2/9] iproute2: ip-link.8.in: Spelling fixes In the ip-link(8) man page, for the gretap, ip6gre, and ip6gretap types, the word tunnel was incorrectly spelled 'tuunel'. Signed-off-by: Reese Moore --- man/man8/ip-link.8.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 1209b55d..313d6f23 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -221,13 +221,13 @@ Link types: - Virtual tunnel interface GRE over IPv4 .sp .BR gretap -- Virtual L2 tuunel interface GRE over IPv4 +- Virtual L2 tunnel interface GRE over IPv4 .sp .BR ip6gre -- Virtual tuunel interface GRE over IPv6 +- Virtual tunnel interface GRE over IPv6 .sp .BR ip6gretap -- Virtual L2 tuunel interface GRE over IPv6 +- Virtual L2 tunnel interface GRE over IPv6 .in -8 .TP From ffff693130e9d6e4184df27835012e46c6abd58d Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 15 Jan 2015 11:36:24 +0100 Subject: [PATCH 3/9] lib: fix warning in namespace.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warning was: In file included from bridge.c:16:0: ../include/namespace.h:33:12: warning: ‘setns’ defined but not used [-Wunused-function] CC: Vadim Kochan Fixes: eb67e4498aec ("lib: Add netns_switch func for change network namespace") Signed-off-by: Nicolas Dichtel --- include/namespace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/namespace.h b/include/namespace.h index b8c5cad6..28a4223b 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -30,7 +30,7 @@ #endif #ifndef HAVE_SETNS -static int setns(int fd, int nstype) +static inline int setns(int fd, int nstype) { #ifdef __NR_setns return syscall(__NR_setns, fd, nstype); From 1ff6b16e2d5b291fd3cc5405c492d9b27d596d0a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 15 Jan 2015 11:36:25 +0100 Subject: [PATCH 4/9] lib: fix setns() function when !HAVE_SETNS When HAVE_SETNS is not set, iproute2 provides a local implementation of this function based on __NR_setns. This macro is defined in sys/syscall.h, which was not included, thus the local implementation always returned -1. CC: Vadim Kochan Fixes: eb67e4498aec ("lib: Add netns_switch func for change network namespace") Signed-off-by: Nicolas Dichtel --- include/namespace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/namespace.h b/include/namespace.h index 28a4223b..52f7fbd7 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -3,6 +3,7 @@ #include #include +#include #include #define NETNS_RUN_DIR "/var/run/netns" From f42a45747071116649d5b70d432efd2dedc280bd Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Thu, 8 Jan 2015 19:32:22 +0200 Subject: [PATCH 5/9] ss: Filter inet dgram sockets with established state by default As inet dgram sockets (udp, raw) can call connect(...) - they might be set in ESTABLISHED state. So keep the original behaviour of 'ss' which filtered them by ESTABLISHED state by default. So: $ ss -u or $ ss -w Will show only ESTABLISHED UDP sockets by default. Signed-off-by: Vadim Kochan --- misc/ss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index f434f57f..40dc1887 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -170,11 +170,11 @@ static const struct filter default_dbs[MAX_DB] = { .families = (1 << AF_INET) | (1 << AF_INET6), }, [UDP_DB] = { - .states = (1 << SS_CLOSE), + .states = (1 << SS_ESTABLISHED), .families = (1 << AF_INET) | (1 << AF_INET6), }, [RAW_DB] = { - .states = (1 << SS_CLOSE), + .states = (1 << SS_ESTABLISHED), .families = (1 << AF_INET) | (1 << AF_INET6), }, [UNIX_DG_DB] = { From 4cec9db0b4085c1b2e8072bac2d07843a9285ac1 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Thu, 15 Jan 2015 18:59:22 +0200 Subject: [PATCH 6/9] tests: Add few 'ip link' related tests Added two tests which checks the following fixed issues: 1) Bug when not possible add new virtual interface via: $ ip link add dev XXX type It was fixed a few releases ago. 2) Crash on older kernels when VF rate info does not exist: $ ip link show Used dump file from William Dauchy : testsuite/tests/ip/link/dev_wo_vf_rate.nl So 'ip link show' replaced by 'ip -d monitor file ...' which does the same thing. Also added new func in testsuite/lib/generic.sh to gen new random dev name. Added 'clean' dependency on running all tests. Signed-off-by: Vadim Kochan --- testsuite/Makefile | 3 ++- testsuite/lib/generic.sh | 8 +++++++- testsuite/tests/ip/link/dev_wo_vf_rate.nl | Bin 0 -> 14076 bytes testsuite/tests/ip/link/new_link.t | 11 +++++++++++ testsuite/tests/ip/link/show_dev_wo_vf_rate.t | 6 ++++++ 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/ip/link/dev_wo_vf_rate.nl create mode 100755 testsuite/tests/ip/link/new_link.t create mode 100755 testsuite/tests/ip/link/show_dev_wo_vf_rate.t diff --git a/testsuite/Makefile b/testsuite/Makefile index 2ba95473..a2c8a2d9 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -31,12 +31,13 @@ listtests: alltests: $(TESTS) clean: + @echo "Removing $(RESULTS_DIR) dir ..." @rm -rf $(RESULTS_DIR) distclean: clean echo "Entering iproute2" && cd iproute2 && $(MAKE) distclean && cd ..; -$(TESTS): +$(TESTS): clean @mkdir -p $(RESULTS_DIR) @for d in $(TESTS_DIR); do \ diff --git a/testsuite/lib/generic.sh b/testsuite/lib/generic.sh index 8f76e492..3473cc13 100644 --- a/testsuite/lib/generic.sh +++ b/testsuite/lib/generic.sh @@ -62,8 +62,9 @@ ts_ip() TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX` || exit $IP $@ 2> $TMP_ERR > $TMP_OUT + RET=$? - if [ -s $TMP_ERR ]; then + if [ -s $TMP_ERR ] || [ "$RET" != "0" ]; then ts_err "${SCRIPT}: ${DESC} failed:" ts_err "command: $IP $@" ts_err "stderr output:" @@ -91,3 +92,8 @@ ts_qdisc_available() return 1; fi } + +rand_dev() +{ + echo "dev-$(tr -dc "[:alpha:]" < /dev/urandom | head -c 6)" +} diff --git a/testsuite/tests/ip/link/dev_wo_vf_rate.nl b/testsuite/tests/ip/link/dev_wo_vf_rate.nl new file mode 100644 index 0000000000000000000000000000000000000000..40fa87ff1b158fb972e064efb38f76b0e9a56697 GIT binary patch literal 14076 zcmeI2QD_`h6o$|4X4B1fZMT}ns!(GsCQqft8lx5o_Nk#2gn}Z4n3_#@VcVp2BSi%l zK`m6|(o55*6q! zb)4tkkUXi*T+a%)Z-E|A^#$7Mln*Km1sYXlo*q(Vi3aKD;<4q*a)q|j2GuucGkCJq zDyp+|k0Sdi@-ln2m0iT|)VKO4ZE=*})4fVJbioD$cFa;AC2zZuy`N6-ST&5X6EATo z_D|Z(Qu>&6?e@!KMAvgf!`ULof*!D8j*?c3=uZxngEPAQq%()pN?GQnhhmRa(B~Ye z(A8pTJ~c$m=QA9IL@)C6>*%|64N6VG20Ecbn#D)dZ_ng7{!(c-0=xKL9cc>-r(+vLpn!)W(%rl8In%!oLR?bA34VJ ztQhmlKitHza7C5aH$^e#k$UUmB_c2eF@vZ9V+O7g?SGr-@R?S2`HvUO)6{;^Q==<_ z>do$84D>@_0|GlJ{cNG$mN0hAbE5V)&o%c8v{}vJPc*{gl%a9wPJSu7_~x%4nmyh7 z_^&agr0#58Q&RsW`ra<_Op1tpM9YpZCUc_~rNvu9zm6*12K{mj{n*D3`lUV&UV1%g zUn49sc-a(QK6ek%rHYrAh=1`}t|P~0gqN_`DKAAobcv6sGkGaYxZrel&nWIuE#r2B zQ{U?X846^*F1%akI<{ai+lX9uP#2Sz_NB|1*yo1jC0w(3`6zUChnGJ%y!^2}FE4v} zc^~`4;Y(kR5Iyaa-ff1{cPQW`^h00+0y_{tTe`))?Zm!YQ?#QXUVc;E_S@cCu&z#d zdFYwH@;|S(*YAYC>a-Sl`4vy<)WPKPQdrOom((4>evgfMfjQGT^D3Lh0ZZ}AW9+z?D zXmZ^_?wic9FI~pOJ~u3LVB2EOW6;%a=E$1Kk2%Oo5Afy_nE*KKh=T|@j8vM;k=z${ zAbz%Vi+kINeYd7)M@eSR)Y+6d(PlHaw}ia>H+p(HfVkbdu%FDqn$%*>E?h?+nbSm` zBkLNQIT&+rc8UjWMkW9b#~|u?nxjWp4m*%2w(S1}t)aWyBr|8__2e=~QsrjA^hg|B z>&K+}_#|!wF=yI2C&_CojH$(($KiG#nZwWRGbGPC{FsB(11wnSB6B3q5#~g(C2@gq z?3E;$In!rS=EM~T5?gD9IZJ$x;_1w-ZxZl*frmMh7@s>~&a^sjlu+V*A;kT@P*nwP z)ceBsZ)C3Q^FIF$JSm0-FzA%Z;a&|wPT;8nJIq$aL=Chozw)~#u`0)nM z9;_Va3E1c>Z}z9W2|Le8=S_7_%A2rrnUsEU@uumM-{Ad%XRe18dh$aOw@YwX6@yD57x9$}LrV!yl{-g+KTPWWMs+?8L;AedW&T$F&Wg?nt>4HrA8Q zozu*nt1D^V6Lvn6(yyD`DH+^Z&)jJouhr}PC3rvcoyj*o+V Date: Tue, 20 Jan 2015 16:14:23 +0200 Subject: [PATCH 7/9] ss: Unify meminfo output Signed-off-by: Vadim Kochan --- misc/ss.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index 40dc1887..ce151be3 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -1613,8 +1613,24 @@ static char *sprint_bw(char *buf, double bw) static void print_skmeminfo(struct rtattr *tb[], int attrtype) { const __u32 *skmeminfo; - if (!tb[attrtype]) + + if (!tb[attrtype]) { + if (attrtype == INET_DIAG_SKMEMINFO) { + if (!tb[INET_DIAG_MEMINFO]) + return; + + const struct inet_diag_meminfo *minfo = + RTA_DATA(tb[INET_DIAG_MEMINFO]); + + printf(" mem:(r%u,w%u,f%u,t%u)", + minfo->idiag_rmem, + minfo->idiag_wmem, + minfo->idiag_fmem, + minfo->idiag_tmem); + } return; + } + skmeminfo = RTA_DATA(tb[attrtype]); printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u", @@ -1639,17 +1655,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, char b1[64]; double rtt = 0; - if (tb[INET_DIAG_SKMEMINFO]) { - print_skmeminfo(tb, INET_DIAG_SKMEMINFO); - } else if (tb[INET_DIAG_MEMINFO]) { - const struct inet_diag_meminfo *minfo - = RTA_DATA(tb[INET_DIAG_MEMINFO]); - printf(" mem:(r%u,w%u,f%u,t%u)", - minfo->idiag_rmem, - minfo->idiag_wmem, - minfo->idiag_fmem, - minfo->idiag_tmem); - } + print_skmeminfo(tb, INET_DIAG_SKMEMINFO); if (tb[INET_DIAG_INFO]) { struct tcp_info *info; From 8250bc9ff4e55a3ef397ed8c7612f1392d164295 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Tue, 20 Jan 2015 16:14:24 +0200 Subject: [PATCH 8/9] ss: Unify inet sockets output Signed-off-by: Vadim Kochan --- misc/ss.c | 667 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 350 insertions(+), 317 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index ce151be3..7fc0a99e 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -689,23 +689,59 @@ static const char *sstate_namel[] = { [SS_CLOSING] = "closing", }; +struct dctcpstat +{ + unsigned int ce_state; + unsigned int alpha; + unsigned int ab_ecn; + unsigned int ab_tot; + bool enabled; +}; + struct tcpstat { - inet_prefix local; - inet_prefix remote; - int lport; - int rport; - int state; - int rq, wq; - int timer; - int timeout; - int retrs; - unsigned ino; - int probes; - unsigned uid; - int refcnt; - unsigned long long sk; - int rto, ato, qack, cwnd, ssthresh; + inet_prefix local; + inet_prefix remote; + int lport; + int rport; + int state; + int rq, wq; + unsigned ino; + unsigned uid; + int refcnt; + unsigned int iface; + unsigned long long sk; + int timer; + int timeout; + int probes; + char *cong_alg; + double rto, ato, rtt, rttvar; + int qack, cwnd, ssthresh, backoff; + double send_bps; + int snd_wscale; + int rcv_wscale; + int mss; + unsigned int lastsnd; + unsigned int lastrcv; + unsigned int lastack; + double pacing_rate; + double pacing_rate_max; + unsigned int unacked; + unsigned int retrans; + unsigned int retrans_total; + unsigned int lost; + unsigned int sacked; + unsigned int fackets; + unsigned int reordering; + double rcv_rtt; + int rcv_space; + bool has_ts_opt; + bool has_sack_opt; + bool has_ecn_opt; + bool has_ecnseen_opt; + bool has_fastopen_opt; + bool has_wscale_opt; + struct dctcpstat *dctcp; }; static const char *tmr_name[] = { @@ -744,12 +780,6 @@ static const char *print_ms_timer(int timeout) return buf; } -static const char *print_hz_timer(int timeout) -{ - int hz = get_user_hz(); - return print_ms_timer(((timeout*1000) + hz-1)/hz); -} - struct scache { struct scache *next; @@ -1439,125 +1469,250 @@ out: return res; } -static int tcp_show_line(char *line, const struct filter *f, int family) +static char *proto_name(int protocol) +{ + switch (protocol) { + case IPPROTO_UDP: + return "udp"; + case IPPROTO_TCP: + return "tcp"; + case IPPROTO_DCCP: + return "dccp"; + } + + return "???"; +} + +static void inet_stats_print(struct tcpstat *s, int protocol) +{ + char *buf = NULL; + + if (netid_width) + printf("%-*s ", netid_width, proto_name(protocol)); + if (state_width) + printf("%-*s ", state_width, sstate_name[s->state]); + + printf("%-6d %-6d ", s->rq, s->wq); + + formatted_print(&s->local, s->lport, s->iface); + formatted_print(&s->remote, s->rport, 0); + + if (show_options) { + if (s->timer) { + if (s->timer > 4) + s->timer = 5; + printf(" timer:(%s,%s,%d)", + tmr_name[s->timer], + print_ms_timer(s->timeout), + s->retrans); + } + } + + if (show_proc_ctx || show_sock_ctx) { + if (find_entry(s->ino, &buf, + (show_proc_ctx & show_sock_ctx) ? + PROC_SOCK_CTX : PROC_CTX) > 0) { + printf(" users:(%s)", buf); + free(buf); + } + } else if (show_users) { + if (find_entry(s->ino, &buf, USERS) > 0) { + printf(" users:(%s)", buf); + free(buf); + } + } +} + +static int proc_parse_inet_addr(char *loc, char *rem, int family, struct tcpstat *s) +{ + s->local.family = s->remote.family = family; + if (family == AF_INET) { + sscanf(loc, "%x:%x", s->local.data, (unsigned*)&s->lport); + sscanf(rem, "%x:%x", s->remote.data, (unsigned*)&s->rport); + s->local.bytelen = s->remote.bytelen = 4; + return 0; + } else { + sscanf(loc, "%08x%08x%08x%08x:%x", + s->local.data, + s->local.data + 1, + s->local.data + 2, + s->local.data + 3, + &s->lport); + sscanf(rem, "%08x%08x%08x%08x:%x", + s->remote.data, + s->remote.data + 1, + s->remote.data + 2, + s->remote.data + 3, + &s->rport); + s->local.bytelen = s->remote.bytelen = 16; + return 0; + } + return -1; +} + +static int proc_inet_split_line(char *line, char **loc, char **rem, char **data) { - struct tcpstat s; - char *loc, *rem, *data; - char opt[256]; - int n; char *p; if ((p = strchr(line, ':')) == NULL) return -1; - loc = p+2; - if ((p = strchr(loc, ':')) == NULL) + *loc = p+2; + if ((p = strchr(*loc, ':')) == NULL) return -1; - p[5] = 0; - rem = p+6; - if ((p = strchr(rem, ':')) == NULL) + p[5] = 0; + *rem = p+6; + if ((p = strchr(*rem, ':')) == NULL) return -1; + p[5] = 0; - data = p+6; + *data = p+6; + return 0; +} - do { - int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); +static char *sprint_bw(char *buf, double bw) +{ + if (bw > 1000000.) + sprintf(buf,"%.1fM", bw / 1000000.); + else if (bw > 1000.) + sprintf(buf,"%.1fK", bw / 1000.); + else + sprintf(buf, "%g", bw); - if (!(f->states & (1<has_ts_opt) + printf(" ts"); + if (s->has_sack_opt) + printf(" sack"); + if (s->has_ecn_opt) + printf(" ecn"); + if (s->has_ecnseen_opt) + printf(" ecnseen"); + if (s->has_fastopen_opt) + printf(" fastopen"); + if (s->cong_alg) + printf(" %s", s->cong_alg); + if (s->has_wscale_opt) + printf(" wscale:%d,%d", s->snd_wscale, s->rcv_wscale); + if (s->rto) + printf(" rto:%g", s->rto); + if (s->backoff) + printf(" backoff:%u", s->backoff); + if (s->rtt) + printf(" rtt:%g/%g", s->rtt, s->rttvar); + if (s->ato) + printf(" ato:%g", s->ato); + + if (s->qack) + printf(" qack:%d", s->qack); + if (s->qack & 1) + printf(" bidir"); + + if (s->mss) + printf(" mss:%d", s->mss); + if (s->cwnd && s->cwnd != 2) + printf(" cwnd:%d", s->cwnd); + if (s->ssthresh) + printf(" ssthresh:%d", s->ssthresh); + + if (s->dctcp && s->dctcp->enabled) { + struct dctcpstat *dctcp = s->dctcp; + + printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u", + dctcp->ce_state, dctcp->alpha, dctcp->ab_ecn, + dctcp->ab_tot); + } else if (s->dctcp) { + printf(" fallback_mode"); } + if (s->send_bps) + printf(" send %sbps", sprint_bw(b1, s->send_bps)); + if (s->lastsnd) + printf(" lastsnd:%u", s->lastsnd); + if (s->lastrcv) + printf(" lastrcv:%u", s->lastrcv); + if (s->lastack) + printf(" lastack:%u", s->lastack); + + if (s->pacing_rate) { + printf(" pacing_rate %sbps", sprint_bw(b1, s->pacing_rate)); + if (s->pacing_rate_max) + printf("/%sbps", sprint_bw(b1, + s->pacing_rate_max)); + } + + if (s->unacked) + printf(" unacked:%u", s->unacked); + if (s->retrans || s->retrans_total) + printf(" retrans:%u/%u", s->retrans, s->retrans_total); + if (s->lost) + printf(" lost:%u", s->lost); + if (s->sacked && s->state != SS_LISTEN) + printf(" sacked:%u", s->sacked); + if (s->fackets) + printf(" fackets:%u", s->fackets); + if (s->reordering != 3) + printf(" reordering:%d", s->reordering); + if (s->rcv_rtt) + printf(" rcv_rtt:%g", s->rcv_rtt); + if (s->rcv_space) + printf(" rcv_space:%d", s->rcv_space); +} + +static int tcp_show_line(char *line, const struct filter *f, int family) +{ + int rto = 0, ato = 0; + struct tcpstat s = {}; + char *loc, *rem, *data; + char opt[256]; + int n; + int hz = get_user_hz(); + + if (proc_inet_split_line(line, &loc, &rem, &data)) + return -1; + + int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); + if (!(f->states & (1 << state))) + return 0; + + proc_parse_inet_addr(loc, rem, family, &s); + if (f->f && run_ssfilter(f->f, &s) == 0) return 0; opt[0] = 0; n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n", &s.state, &s.wq, &s.rq, - &s.timer, &s.timeout, &s.retrs, &s.uid, &s.probes, &s.ino, - &s.refcnt, &s.sk, &s.rto, &s.ato, &s.qack, + &s.timer, &s.timeout, &s.retrans, &s.uid, &s.probes, &s.ino, + &s.refcnt, &s.sk, &rto, &ato, &s.qack, &s.cwnd, &s.ssthresh, opt); if (n < 17) opt[0] = 0; if (n < 12) { - s.rto = 0; + rto = 0; s.cwnd = 2; s.ssthresh = -1; - s.ato = s.qack = 0; + ato = s.qack = 0; } - if (netid_width) - printf("%-*s ", netid_width, "tcp"); - if (state_width) - printf("%-*s ", state_width, sstate_name[s.state]); + s.retrans = s.timer != 1 ? s.probes : s.retrans; + s.timeout = (s.timeout * 1000 + hz - 1) / hz; + s.ato = (double)ato / hz; + s.qack /= 2; + s.rto = (double)rto; + s.ssthresh = s.ssthresh == -1 ? 0 : s.ssthresh; + s.rto = s.rto != 3 * hz ? s.rto / hz : 0; - printf("%-6d %-6d ", s.rq, s.wq); - - formatted_print(&s.local, s.lport, 0); - formatted_print(&s.remote, s.rport, 0); - - if (show_options) { - if (s.timer) { - if (s.timer > 4) - s.timer = 5; - printf(" timer:(%s,%s,%d)", - tmr_name[s.timer], - print_hz_timer(s.timeout), - s.timer != 1 ? s.probes : s.retrs); - } - } - if (show_tcpinfo) { - int hz = get_user_hz(); - if (s.rto && s.rto != 3*hz) - printf(" rto:%g", (double)s.rto/hz); - if (s.ato) - printf(" ato:%g", (double)s.ato/hz); - if (s.cwnd != 2) - printf(" cwnd:%d", s.cwnd); - if (s.ssthresh != -1) - printf(" ssthresh:%d", s.ssthresh); - if (s.qack/2) - printf(" qack:%d", s.qack/2); - if (s.qack&1) - printf(" bidir"); - } - char *buf = NULL; - if (show_proc_ctx || show_sock_ctx) { - if (find_entry(s.ino, &buf, - (show_proc_ctx & show_sock_ctx) ? - PROC_SOCK_CTX : PROC_CTX) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } else if (show_users) { - if (find_entry(s.ino, &buf, USERS) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } + inet_stats_print(&s, IPPROTO_TCP); if (show_details) { if (s.uid) @@ -1567,8 +1722,11 @@ static int tcp_show_line(char *line, const struct filter *f, int family) if (opt[0]) printf(" opt:\"%s\"", opt); } - printf("\n"); + if (show_tcpinfo) + tcp_stats_print(&s); + + printf("\n"); return 0; } @@ -1598,18 +1756,6 @@ outerr: return ferror(fp) ? -1 : 0; } -static char *sprint_bw(char *buf, double bw) -{ - if (bw > 1000000.) - sprintf(buf,"%.1fM", bw / 1000000.); - else if (bw > 1000.) - sprintf(buf,"%.1fK", bw / 1000.); - else - sprintf(buf, "%g", bw); - - return buf; -} - static void print_skmeminfo(struct rtattr *tb[], int attrtype) { const __u32 *skmeminfo; @@ -1649,11 +1795,13 @@ static void print_skmeminfo(struct rtattr *tb[], int attrtype) printf(")"); } +#define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt)) + static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, struct rtattr *tb[]) { - char b1[64]; double rtt = 0; + struct tcpstat s = {}; print_skmeminfo(tb, INET_DIAG_SKMEMINFO); @@ -1670,39 +1818,49 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, info = RTA_DATA(tb[INET_DIAG_INFO]); if (show_options) { - if (info->tcpi_options & TCPI_OPT_TIMESTAMPS) - printf(" ts"); - if (info->tcpi_options & TCPI_OPT_SACK) - printf(" sack"); - if (info->tcpi_options & TCPI_OPT_ECN) - printf(" ecn"); - if (info->tcpi_options & TCPI_OPT_ECN_SEEN) - printf(" ecnseen"); - if (info->tcpi_options & TCPI_OPT_SYN_DATA) - printf(" fastopen"); + s.has_ts_opt = TCPI_HAS_OPT(info, TCPI_OPT_TIMESTAMPS); + s.has_sack_opt = TCPI_HAS_OPT(info, TCPI_OPT_SACK); + s.has_ecn_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN); + s.has_ecnseen_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN_SEEN); + s.has_fastopen_opt = TCPI_HAS_OPT(info, TCPI_OPT_SYN_DATA); } - if (tb[INET_DIAG_CONG]) - printf(" %s", rta_getattr_str(tb[INET_DIAG_CONG])); + if (tb[INET_DIAG_CONG]) { + const char *cong_attr = rta_getattr_str(tb[INET_DIAG_CONG]); + s.cong_alg = malloc(strlen(cong_attr + 1)); + strcpy(s.cong_alg, cong_attr); + } + + if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) { + s.has_wscale_opt = true; + s.snd_wscale = info->tcpi_snd_wscale; + s.rcv_wscale = info->tcpi_rcv_wscale; + } - if (info->tcpi_options & TCPI_OPT_WSCALE) - printf(" wscale:%d,%d", info->tcpi_snd_wscale, - info->tcpi_rcv_wscale); if (info->tcpi_rto && info->tcpi_rto != 3000000) - printf(" rto:%g", (double)info->tcpi_rto/1000); - if (info->tcpi_backoff) - printf(" backoff:%u", info->tcpi_backoff); - if (info->tcpi_rtt) - printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000, - (double)info->tcpi_rttvar/1000); - if (info->tcpi_ato) - printf(" ato:%g", (double)info->tcpi_ato/1000); - if (info->tcpi_snd_mss) - printf(" mss:%d", info->tcpi_snd_mss); - if (info->tcpi_snd_cwnd != 2) - printf(" cwnd:%d", info->tcpi_snd_cwnd); + s.rto = (double)info->tcpi_rto / 1000; + + s.backoff = info->tcpi_backoff; + s.rtt = (double)info->tcpi_rtt / 1000; + s.rttvar = (double)info->tcpi_rttvar / 1000; + s.ato = (double)info->tcpi_rttvar / 1000; + s.mss = info->tcpi_snd_mss; + s.rcv_space = info->tcpi_rcv_space; + s.rcv_rtt = (double)info->tcpi_rcv_rtt / 1000; + s.lastsnd = info->tcpi_last_data_sent; + s.lastrcv = info->tcpi_last_data_recv; + s.lastack = info->tcpi_last_ack_recv; + s.unacked = info->tcpi_unacked; + s.retrans = info->tcpi_retrans; + s.retrans_total = info->tcpi_total_retrans; + s.lost = info->tcpi_lost; + s.sacked = info->tcpi_sacked; + s.reordering = info->tcpi_reordering; + s.rcv_space = info->tcpi_rcv_space; + s.cwnd = info->tcpi_snd_cwnd; + if (info->tcpi_snd_ssthresh < 0xFFFF) - printf(" ssthresh:%d", info->tcpi_snd_ssthresh); + s.ssthresh = info->tcpi_snd_ssthresh; rtt = (double) info->tcpi_rtt; if (tb[INET_DIAG_VEGASINFO]) { @@ -1710,89 +1868,51 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, = RTA_DATA(tb[INET_DIAG_VEGASINFO]); if (vinfo->tcpv_enabled && - vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) + vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) rtt = vinfo->tcpv_rtt; } if (tb[INET_DIAG_DCTCPINFO]) { + struct dctcpstat *dctcp = malloc(sizeof(struct + dctcpstat)); + const struct tcp_dctcp_info *dinfo = RTA_DATA(tb[INET_DIAG_DCTCPINFO]); - if (dinfo->dctcp_enabled) { - printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u", - dinfo->dctcp_ce_state, dinfo->dctcp_alpha, - dinfo->dctcp_ab_ecn, dinfo->dctcp_ab_tot); - } else { - printf(" fallback_mode"); - } + dctcp->enabled = !!dinfo->dctcp_enabled; + dctcp->ce_state = dinfo->dctcp_ce_state; + dctcp->alpha = dinfo->dctcp_alpha; + dctcp->ab_ecn = dinfo->dctcp_ab_ecn; + dctcp->ab_tot = dinfo->dctcp_ab_tot; + s.dctcp = dctcp; } if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) { - printf(" send %sbps", - sprint_bw(b1, (double) info->tcpi_snd_cwnd * - (double) info->tcpi_snd_mss * 8000000. - / rtt)); + s.send_bps = (double) info->tcpi_snd_cwnd * + (double)info->tcpi_snd_mss * 8000000. / rtt; } - if (info->tcpi_last_data_sent) - printf(" lastsnd:%u", info->tcpi_last_data_sent); - - if (info->tcpi_last_data_recv) - printf(" lastrcv:%u", info->tcpi_last_data_recv); - - if (info->tcpi_last_ack_recv) - printf(" lastack:%u", info->tcpi_last_ack_recv); - if (info->tcpi_pacing_rate && - info->tcpi_pacing_rate != ~0ULL) { - printf(" pacing_rate %sbps", - sprint_bw(b1, info->tcpi_pacing_rate * 8.)); + info->tcpi_pacing_rate != ~0ULL) { + s.pacing_rate = info->tcpi_pacing_rate * 8.; if (info->tcpi_max_pacing_rate && - info->tcpi_max_pacing_rate != ~0ULL) - printf("/%sbps", - sprint_bw(b1, info->tcpi_max_pacing_rate * 8.)); + info->tcpi_max_pacing_rate != ~0ULL) + s.pacing_rate_max = info->tcpi_max_pacing_rate * 8.; } - if (info->tcpi_unacked) - printf(" unacked:%u", info->tcpi_unacked); - if (info->tcpi_retrans || info->tcpi_total_retrans) - printf(" retrans:%u/%u", info->tcpi_retrans, - info->tcpi_total_retrans); - if (info->tcpi_lost) - printf(" lost:%u", info->tcpi_lost); - if (info->tcpi_sacked && r->idiag_state != SS_LISTEN) - printf(" sacked:%u", info->tcpi_sacked); - if (info->tcpi_fackets) - printf(" fackets:%u", info->tcpi_fackets); - if (info->tcpi_reordering != 3) - printf(" reordering:%d", info->tcpi_reordering); - if (info->tcpi_rcv_rtt) - printf(" rcv_rtt:%g", (double) info->tcpi_rcv_rtt/1000); - if (info->tcpi_rcv_space) - printf(" rcv_space:%d", info->tcpi_rcv_space); - + tcp_stats_print(&s); + if (s.dctcp) + free(s.dctcp); + if (s.cong_alg) + free(s.cong_alg); } } -static char *proto_name(int protocol) -{ - switch (protocol) { - case IPPROTO_UDP: - return "udp"; - case IPPROTO_TCP: - return "tcp"; - case IPPROTO_DCCP: - return "dccp"; - } - - return "???"; -} - static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) { struct rtattr * tb[INET_DIAG_MAX+1]; struct inet_diag_msg *r = NLMSG_DATA(nlh); - struct tcpstat s; + struct tcpstat s = {}; parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1), nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); @@ -1801,52 +1921,28 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) s.local.family = s.remote.family = r->idiag_family; s.lport = ntohs(r->id.idiag_sport); s.rport = ntohs(r->id.idiag_dport); + s.wq = r->idiag_wqueue; + s.rq = r->idiag_rqueue; + s.timer = r->idiag_timer; + s.timeout = r->idiag_expires; + s.retrans = r->idiag_retrans; + s.ino = r->idiag_inode; + s.uid = r->idiag_uid; + s.iface = r->id.idiag_if; + if (s.local.family == AF_INET) { s.local.bytelen = s.remote.bytelen = 4; } else { s.local.bytelen = s.remote.bytelen = 16; } + memcpy(s.local.data, r->id.idiag_src, s.local.bytelen); memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen); if (f && f->f && run_ssfilter(f->f, &s) == 0) return 0; - if (netid_width) - printf("%-*s ", netid_width, proto_name(protocol)); - if (state_width) - printf("%-*s ", state_width, sstate_name[s.state]); - - printf("%-6d %-6d ", r->idiag_rqueue, r->idiag_wqueue); - - formatted_print(&s.local, s.lport, r->id.idiag_if); - formatted_print(&s.remote, s.rport, 0); - - if (show_options) { - if (r->idiag_timer) { - if (r->idiag_timer > 4) - r->idiag_timer = 5; - printf(" timer:(%s,%s,%d)", - tmr_name[r->idiag_timer], - print_ms_timer(r->idiag_expires), - r->idiag_retrans); - } - } - char *buf = NULL; - - if (show_proc_ctx || show_sock_ctx) { - if (find_entry(r->idiag_inode, &buf, - (show_proc_ctx & show_sock_ctx) ? - PROC_SOCK_CTX : PROC_CTX) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } else if (show_users) { - if (find_entry(r->idiag_inode, &buf, USERS) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } + inet_stats_print(&s, protocol); if (show_details) { if (r->idiag_uid) @@ -1862,13 +1958,13 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) printf(" %c-%c", mask & 1 ? '-' : '<', mask & 2 ? '-' : '>'); } } + if (show_mem || show_tcpinfo) { printf("\n\t"); tcp_show_info(nlh, r, tb); } printf("\n"); - return 0; } @@ -2189,53 +2285,19 @@ outerr: static int dgram_show_line(char *line, const struct filter *f, int family) { - struct tcpstat s; + struct tcpstat s = {}; char *loc, *rem, *data; char opt[256]; int n; - char *p; - if ((p = strchr(line, ':')) == NULL) + if (proc_inet_split_line(line, &loc, &rem, &data)) return -1; - loc = p+2; - if ((p = strchr(loc, ':')) == NULL) - return -1; - p[5] = 0; - rem = p+6; + int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); + if (!(f->states & (1 << state))) + return 0; - if ((p = strchr(rem, ':')) == NULL) - return -1; - p[5] = 0; - data = p+6; - - do { - int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); - - if (!(f->states & (1<f && run_ssfilter(f->f, &s) == 0) return 0; @@ -2249,31 +2311,7 @@ static int dgram_show_line(char *line, const struct filter *f, int family) if (n < 9) opt[0] = 0; - if (netid_width) - printf("%-*s ", netid_width, dg_proto); - if (state_width) - printf("%-*s ", state_width, sstate_name[s.state]); - - printf("%-6d %-6d ", s.rq, s.wq); - - formatted_print(&s.local, s.lport, 0); - formatted_print(&s.remote, s.rport, 0); - - char *buf = NULL; - - if (show_proc_ctx || show_sock_ctx) { - if (find_entry(s.ino, &buf, - (show_proc_ctx & show_sock_ctx) ? - PROC_SOCK_CTX : PROC_CTX) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } else if (show_users) { - if (find_entry(s.ino, &buf, USERS) > 0) { - printf(" users:(%s)", buf); - free(buf); - } - } + inet_stats_print(&s, IPPROTO_UDP); if (show_details) { if (s.uid) @@ -2283,12 +2321,11 @@ static int dgram_show_line(char *line, const struct filter *f, int family) if (opt[0]) printf(" opt:\"%s\"", opt); } - printf("\n"); + printf("\n"); return 0; } - static int udp_show(struct filter *f) { FILE *fp = NULL; @@ -2357,7 +2394,6 @@ outerr: } while (0); } - struct unixstat { struct unixstat *next; @@ -2371,12 +2407,9 @@ struct unixstat char *name; }; - - int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT, SS_ESTABLISHED, SS_CLOSING }; - #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat)) static void unix_list_free(struct unixstat *list) From 4c7d75de95f5f20ab106460cfe86218b2dd87a77 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Feb 2015 10:17:50 -0800 Subject: [PATCH 9/9] can: update kernel header Sanitized header from upstream 3.20-rc kernel --- include/linux/can/netlink.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h index 25fd52cc..6d4ec2a9 100644 --- a/include/linux/can/netlink.h +++ b/include/linux/can/netlink.h @@ -98,6 +98,7 @@ struct can_ctrlmode { #define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ #define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */ #define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ +#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ /* * CAN device statistics