From 232aaf4f4b993a3a96099f2ff02cee8847daa8b9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 26 May 2015 02:51:30 -0400 Subject: [PATCH 1/7] enable transparent LFS Make sure we use 64-bit filesystem functions everywhere. This applies not only to being able to read large files (which generally doesn't apply to us), but also being able to simply stat them (as they might be using large inodes). Signed-off-by: Mike Frysinger --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 2e91c328..67176bef 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,8 @@ ADDLIB+=mpls_ntop.o mpls_pton.o CC = gcc HOSTCC = gcc DEFINES += -D_GNU_SOURCE +# Turn on transparent support for LFS +DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE CCOPTS = -O2 WFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2 From b6907403efd9d64ed5a140d3bc6e23773452bef9 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Fri, 29 May 2015 13:27:41 +0300 Subject: [PATCH 2/7] configure: Check for libmnl Indicate existence of libmnl which is required by tipc. Signed-off-by: Vadim Kochan --- configure | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/configure b/configure index f1325df8..1605464c 100755 --- a/configure +++ b/configure @@ -284,6 +284,17 @@ check_selinux() fi } +check_mnl() +{ + if ${PKG_CONFIG} libmnl --exists + then + echo "HAVE_MNL:=y" >>Config + echo -n "yes" + else + echo -n "no" + fi +} + echo "# Generated config based on" $INCLUDE >Config check_toolchain @@ -313,5 +324,10 @@ check_selinux echo -n "ELF support: " check_elf +echo -n "libmnl support: " +check_mnl +echo " (required by tipc)" + echo -e "\nDocs" check_docs +echo "" From d2055ea597e571bbbb6468b23b9c85de5ebf4591 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 29 May 2015 04:04:05 -0700 Subject: [PATCH 3/7] ss: Fix allocation of cong control alg name On Fri, 2015-05-29 at 13:30 +0300, Vadim Kochan wrote: > From: Vadim Kochan > > Use strdup instead of malloc, and get rid of bad strcpy. > > Signed-off-by: Vadim Kochan > --- > misc/ss.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/misc/ss.c b/misc/ss.c > index 347e3a1..a719466 100644 > --- a/misc/ss.c > +++ b/misc/ss.c > @@ -1908,8 +1908,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, > > 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); > + s.cong_alg = strdup(cong_attr); > } > > if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) { I doubt TCP_CA_NAME_MAX will ever change in the kernel : 16 bytes. Its typically "cubic" and less than 8 bytes. Using 8 bytes to point to a malloc(8) is a waste. Please remove the memory allocation, or store the pointer, since tcp_show_info() does the malloc()/free() before return. --- misc/ss.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index 347e3a12..9fe229fe 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -755,7 +755,7 @@ struct tcpstat int timer; int timeout; int probes; - char *cong_alg; + char cong_alg[16]; double rto, ato, rtt, rttvar; int qack, cwnd, ssthresh, backoff; double send_bps; @@ -1664,7 +1664,7 @@ static void tcp_stats_print(struct tcpstat *s) printf(" ecnseen"); if (s->has_fastopen_opt) printf(" fastopen"); - if (s->cong_alg) + if (s->cong_alg[0]) printf(" %s", s->cong_alg); if (s->has_wscale_opt) printf(" wscale:%d,%d", s->snd_wscale, s->rcv_wscale); @@ -1906,11 +1906,10 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, s.has_fastopen_opt = TCPI_HAS_OPT(info, TCPI_OPT_SYN_DATA); } - 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 (tb[INET_DIAG_CONG]) + strncpy(s.cong_alg, + rta_getattr_str(tb[INET_DIAG_CONG]), + sizeof(s.cong_alg) - 1); if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) { s.has_wscale_opt = true; @@ -1984,8 +1983,6 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, tcp_stats_print(&s); if (s.dctcp) free(s.dctcp); - if (s.cong_alg) - free(s.cong_alg); } } From 22588a0e65428611af7f7da648fc9542d65a2a0c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 29 May 2015 04:45:48 -0700 Subject: [PATCH 4/7] ss: speedup resolve_service() Lets implement a full cache with proper hash table, memory got cheaper these days. Before : $ time ss -t | wc -l 529678 real 0m22.708s user 0m19.591s sys 0m2.969s After : $ time ss -t | wc -l 528291 real 0m5.078s user 0m4.099s sys 0m0.985s Signed-off-by: Eric Dumazet --- misc/ss.c | 69 +++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index 9fe229fe..68bffe28 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -858,8 +858,7 @@ static const char *print_ms_timer(int timeout) return buf; } -struct scache -{ +struct scache { struct scache *next; int port; char *name; @@ -949,11 +948,15 @@ static const char *__resolve_service(int port) return NULL; } +#define SCACHE_BUCKETS 1024 +static struct scache *cache_htab[SCACHE_BUCKETS]; static const char *resolve_service(int port) { static char buf[128]; - static struct scache cache[256]; + struct scache *c; + const char *res; + int hash; if (port == 0) { buf[0] = '*'; @@ -961,45 +964,35 @@ static const char *resolve_service(int port) return buf; } - if (resolve_services) { - if (dg_proto == RAW_PROTO) { - return inet_proto_n2a(port, buf, sizeof(buf)); - } else { - struct scache *c; - const char *res; - int hash = (port^(((unsigned long)dg_proto)>>2))&255; + if (!resolve_services) + goto do_numeric; - for (c = &cache[hash]; c; c = c->next) { - if (c->port == port && - c->proto == dg_proto) { - if (c->name) - return c->name; - goto do_numeric; - } - } + if (dg_proto == RAW_PROTO) + return inet_proto_n2a(port, buf, sizeof(buf)); - if ((res = __resolve_service(port)) != NULL) { - if ((c = malloc(sizeof(*c))) == NULL) - goto do_numeric; - } else { - c = &cache[hash]; - if (c->name) - free(c->name); - } - c->port = port; - c->name = NULL; - c->proto = dg_proto; - if (res) { - c->name = strdup(res); - c->next = cache[hash].next; - cache[hash].next = c; - } - if (c->name) - return c->name; - } + + hash = (port^(((unsigned long)dg_proto)>>2)) % SCACHE_BUCKETS; + + for (c = cache_htab[hash]; c; c = c->next) { + if (c->port == port && c->proto == dg_proto) + goto do_cache; } - do_numeric: + c = malloc(sizeof(*c)); + if (!c) + goto do_numeric; + res = __resolve_service(port); + c->port = port; + c->name = res ? strdup(res) : NULL; + c->proto = dg_proto; + c->next = cache_htab[hash]; + cache_htab[hash] = c; + +do_cache: + if (c->name) + return c->name; + +do_numeric: sprintf(buf, "%u", port); return buf; } From 518af1e0b14cdc8eeac4db313767f5d1dfd1fce1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 29 May 2015 05:37:49 -0700 Subject: [PATCH 5/7] ss: do not bindly dump two families ss currently dumps IPv4 sockets, then IPv6 sockets from the kernel, even if -4 or -6 option was given. Filtering in user space then has to drop all sockets of wrong family. Such a waste of time... Before : $ time ss -tn -4 | wc -l 251659 real 0m1.241s user 0m0.423s sys 0m0.806s After: $ time ss -tn -4 | wc -l 251672 real 0m0.779s user 0m0.412s sys 0m0.386s Signed-off-by: Eric Dumazet --- misc/ss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/misc/ss.c b/misc/ss.c index 68bffe28..1f4a30f7 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -2199,6 +2199,8 @@ static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol) return -1; rth.dump = MAGIC_SEQ; rth.dump_fp = dump_fp; + if (preferred_family == PF_INET6) + family = PF_INET6; again: if ((err = sockdiag_send(family, rth.fd, protocol, f))) @@ -2211,7 +2213,7 @@ again: } goto Exit; } - if (family == PF_INET) { + if (family == PF_INET && preferred_family != PF_INET) { family = PF_INET6; goto again; } From ad1fe0d8e976a5f7815f930fddfa1d94114c3fa8 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 29 May 2015 21:47:45 +0200 Subject: [PATCH 6/7] tc: util: fix print_rate for ludicrous speeds The for loop should only probe up to G[i]bit rates, so that we end up with T[i]bit as the last max units[] slot for snprintf(3), and not possibly an invalid pointer in case rate is multiple of kilo. Fixes: 8cecdc283743 ("tc: more user friendly rates") Reported-by: Jose R. Guzman Mosqueda Signed-off-by: Daniel Borkmann --- tc/tc_util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tc/tc_util.c b/tc/tc_util.c index dc2b70fa..aa6de244 100644 --- a/tc/tc_util.c +++ b/tc/tc_util.c @@ -250,18 +250,19 @@ void print_rate(char *buf, int len, __u64 rate) extern int use_iec; unsigned long kilo = use_iec ? 1024 : 1000; const char *str = use_iec ? "i" : ""; - int i = 0; static char *units[5] = {"", "K", "M", "G", "T"}; + int i; rate <<= 3; /* bytes/sec -> bits/sec */ - for (i = 0; i < ARRAY_SIZE(units); i++) { + for (i = 0; i < ARRAY_SIZE(units) - 1; i++) { if (rate < kilo) break; if (((rate % kilo) != 0) && rate < 1000*kilo) break; rate /= kilo; } + snprintf(buf, len, "%.0f%s%sbit", (double)rate, units[i], str); } From 30383b074de101c778bc65c36e2b0d4690d3d6dc Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Thu, 18 Jun 2015 00:28:18 +0300 Subject: [PATCH 7/7] tests: Add output testing Added possibility to check command output by grep from the testing script. Now TMP_OUT & TMP_ERR are passed from Makefile and changed to STD_ERR & STD_OUT. Also changed some existing tests to make output testing. Signed-off-by: Vadim Kochan --- testsuite/Makefile | 4 + testsuite/lib/generic.sh | 80 ++++++++++++++------ testsuite/tests/ip/link/new_link.t | 4 + testsuite/tests/ip/route/add_default_route.t | 23 +++++- 4 files changed, 88 insertions(+), 23 deletions(-) diff --git a/testsuite/Makefile b/testsuite/Makefile index 4b945b0c..20276500 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -52,6 +52,9 @@ endif @for i in $(IPVERS); do \ o=`echo $$i | sed -e 's/iproute2\///'`; \ echo -n "Running $@ [$$o/`uname -r`]: "; \ + TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX`; \ + TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX`; \ + STD_ERR="$$TMP_ERR" STD_OUT="$$TMP_OUT" \ TC="$$i/tc/tc" IP="$$i/ip/ip" DEV="$(DEV)" IPVER="$@" SNAME="$$i" \ ERRF="$(RESULTS_DIR)/$@.$$o.err" $(KENV) $(PREFIX) tests/$@ > $(RESULTS_DIR)/$@.$$o.out; \ if [ "$$?" = "127" ]; then \ @@ -61,5 +64,6 @@ endif else \ echo "PASS"; \ fi; \ + rm "$$TMP_ERR" "$$TMP_OUT"; \ dmesg > $(RESULTS_DIR)/$@.$$o.dmesg; \ done diff --git a/testsuite/lib/generic.sh b/testsuite/lib/generic.sh index 3473cc13..b7de7044 100644 --- a/testsuite/lib/generic.sh +++ b/testsuite/lib/generic.sh @@ -30,57 +30,49 @@ ts_tc() { SCRIPT=$1; shift DESC=$1; shift - TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX` || exit - TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX` || exit - $TC $@ 2> $TMP_ERR > $TMP_OUT + $TC $@ 2> $STD_ERR > $STD_OUT - if [ -s $TMP_ERR ]; then + if [ -s $STD_ERR ]; then ts_err "${SCRIPT}: ${DESC} failed:" ts_err "command: $TC $@" ts_err "stderr output:" - ts_err_cat $TMP_ERR - if [ -s $TMP_OUT ]; then + ts_err_cat $STD_ERR + if [ -s $STD_OUT ]; then ts_err "stdout output:" - ts_err_cat $TMP_OUT + ts_err_cat $STD_OUT fi - elif [ -s $TMP_OUT ]; then + elif [ -s $STD_OUT ]; then echo "${SCRIPT}: ${DESC} succeeded with output:" - cat $TMP_OUT + cat $STD_OUT else echo "${SCRIPT}: ${DESC} succeeded" fi - - rm $TMP_ERR $TMP_OUT } ts_ip() { SCRIPT=$1; shift DESC=$1; shift - TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX` || exit - TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX` || exit - $IP $@ 2> $TMP_ERR > $TMP_OUT + $IP $@ 2> $STD_ERR > $STD_OUT RET=$? - if [ -s $TMP_ERR ] || [ "$RET" != "0" ]; then + if [ -s $STD_ERR ] || [ "$RET" != "0" ]; then ts_err "${SCRIPT}: ${DESC} failed:" ts_err "command: $IP $@" ts_err "stderr output:" - ts_err_cat $TMP_ERR - if [ -s $TMP_OUT ]; then + ts_err_cat $STD_ERR + if [ -s $STD_OUT ]; then ts_err "stdout output:" - ts_err_cat $TMP_OUT + ts_err_cat $STD_OUT fi - elif [ -s $TMP_OUT ]; then + elif [ -s $STD_OUT ]; then echo "${SCRIPT}: ${DESC} succeeded with output:" - cat $TMP_OUT + cat $STD_OUT else echo "${SCRIPT}: ${DESC} succeeded" fi - - rm $TMP_ERR $TMP_OUT } ts_qdisc_available() @@ -97,3 +89,47 @@ rand_dev() { echo "dev-$(tr -dc "[:alpha:]" < /dev/urandom | head -c 6)" } + +pr_failed() +{ + echo " [FAILED]" + ts_err "matching failed" +} + +pr_success() +{ + echo " [SUCCESS]" +} + +test_on() +{ + echo -n "test on: \"$1\"" + if cat "$STD_OUT" | grep -qE "$1" + then + pr_success + else + pr_failed + fi +} + +test_on_not() +{ + echo -n "test on: \"$1\"" + if cat "$STD_OUT" | grep -vqE "$1" + then + pr_success + else + pr_failed + fi +} + +test_lines_count() +{ + echo -n "test on lines count ($1): " + if cat "$STD_OUT" | wc -l | grep -q "$1" + then + pr_success + else + pr_failed + fi +} diff --git a/testsuite/tests/ip/link/new_link.t b/testsuite/tests/ip/link/new_link.t index 549ff256..699adbcd 100755 --- a/testsuite/tests/ip/link/new_link.t +++ b/testsuite/tests/ip/link/new_link.t @@ -7,5 +7,9 @@ ts_log "[Testing add/del virtual links]" NEW_DEV="$(rand_dev)" ts_ip "$0" "Add $NEW_DEV dummy interface" link add dev $NEW_DEV type dummy + ts_ip "$0" "Show $NEW_DEV dummy interface" link show dev $NEW_DEV +test_on "$NEW_DEV" +test_lines_count 2 + ts_ip "$0" "Del $NEW_DEV dummy interface" link del dev $NEW_DEV diff --git a/testsuite/tests/ip/route/add_default_route.t b/testsuite/tests/ip/route/add_default_route.t index 29085288..e5ea6473 100755 --- a/testsuite/tests/ip/route/add_default_route.t +++ b/testsuite/tests/ip/route/add_default_route.t @@ -8,5 +8,26 @@ DEV=dummy0 ts_ip "$0" "Add new interface $DEV" link add $DEV type dummy ts_ip "$0" "Set $DEV into UP state" link set up dev $DEV + ts_ip "$0" "Add 1.1.1.1/24 addr on $DEV" addr add 1.1.1.1/24 dev $DEV -ts_ip "$0" "Add default route via 1.1.1.1" route add default via 1.1.1.1 +ts_ip "$0" "Add default route via 1.1.1.2" route add default via 1.1.1.2 + +ts_ip "$0" "Show IPv4 default route" -4 route show default +test_on "default via 1.1.1.2 dev $DEV" +test_lines_count 1 + +ts_ip "$0" "Add another IPv4 route dst 2.2.2.0/24" -4 route add 2.2.2.0/24 dev $DEV +ts_ip "$0" "Show IPv4 default route" -4 route show default +test_on "default via 1.1.1.2 dev $DEV" +test_lines_count 1 + +ts_ip "$0" "Add dead:beef::1/64 addr on $DEV" -6 addr add dead:beef::1/64 dev $DEV +ts_ip "$0" "Add default route via dead:beef::2" route add default via dead:beef::2 +ts_ip "$0" "Show IPv6 default route" -6 route show default +test_on "default via dead:beef::2 dev $DEV" +test_lines_count 1 + +ts_ip "$0" "Add another IPv6 route dst cafe:babe::/64" -6 route add cafe:babe::/64 dev $DEV +ts_ip "$0" "Show IPv6 default route" -6 route show default +test_on "default via dead:beef::2 dev $DEV" +test_lines_count 1