lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sun, 14 Dec 2014 17:56:43 -0800 From: Martin KaFai Lau <kafai@...com> To: <netdev@...r.kernel.org> CC: "David S. Miller" <davem@...emloft.net>, Hannes Frederic Sowa <hannes@...essinduktion.org>, Steven Rostedt <rostedt@...dmis.org>, Lawrence Brakmo <brakmo@...com>, Josef Bacik <jbacik@...com>, Kernel Team <Kernel-team@...com> Subject: [RFC PATCH net-next 2/5] tcp: A perf script for TCP tracepoints A sample perf script. It has a simple ip/port filtering and a summary output. Here is a test with netem delay 100ms loss 0.1% and comparing the tcp-summary output between reno and cubic. It was run in a kvm environment: [root@...u1-centos65 perf]# sysctl -w net.ipv4.tcp_congestion_control=reno net.ipv4.tcp_congestion_control = reno [root@...u1-centos65 perf]# ./perf record -a -e 'tcp:*' netperf -c -C -H 192.168.168.254 -l 60 -p 8888 -- -s 1M -S 1M -m 64K -P ,8889 MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.168.254 () port 8889 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 2097152 425984 65536 60.78 2.91 0.00 0.86 0.000 771.397 [ perf record: Woken up 13 times to write data ] [ perf record: Captured and wrote 3.231 MB perf.data (~141185 samples) ] [root@...u1 perf]# PYTHONPATH="$PYTHONPATH:/root/devhostshare/fb-kernel/linux/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace" ./perf script -s scripts/python/tcp-summary.py -- --rport 8889 snd_cwnd(avg/min/max): 27/8/47 segs out: 15290 data segs out: 15275 octets out: 22116754 loss rxmits: 0 other rxmits: 13 rxmits%: 0.085 dup_acks: 402 established: 1 close: 1 [root@...u1 perf]# sysctl -w net.ipv4.tcp_congestion_control=cubic net.ipv4.tcp_congestion_control = cubic [root@...u1 perf]# ./perf record -a -e 'tcp:*' netperf -c -C -H 192.168.168.254 -l 60 -p 8888 -- -s 1M -S 1M -m 64K -P ,8889 MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.168.254 () port 8889 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 2097152 425984 65536 60.25 4.97 0.02 0.86 1.096 454.051 [ perf record: Woken up 21 times to write data ] [ perf record: Captured and wrote 5.525 MB perf.data (~241393 samples) ] [root@...u1 perf]# PYTHONPATH="$PYTHONPATH:/root/devhostshare/fb-kernel/linux/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace" ./perf script -s scripts/python/tcp-summary.py -- --rport 8889 snd_cwnd(avg/min/max): 47/10/78 segs out: 25869 data segs out: 25848 octets out: 37426458 loss rxmits: 0 other rxmits: 19 rxmits%: 0.074 dup_acks: 957 established: 1 close: 1 Signed-off-by: Martin KaFai Lau <kafai@...com> --- tools/perf/scripts/python/tcp-summary.py | 262 +++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 tools/perf/scripts/python/tcp-summary.py diff --git a/tools/perf/scripts/python/tcp-summary.py b/tools/perf/scripts/python/tcp-summary.py new file mode 100644 index 0000000..fe85a43 --- /dev/null +++ b/tools/perf/scripts/python/tcp-summary.py @@ -0,0 +1,262 @@ +import os +import sys +import argparse +import struct +import socket + +sys.path.append(os.environ['PERF_EXEC_PATH'] + \ + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + +from perf_trace_context import * +from Core import * + +def ntohip(nip): + hip = 0L + for i in nip: + hip <<= 8 + hip |= i + return hip + +def unpack_nip(nip_in_c): + fmt = "!" + "B" * len(nip_in_c) + return struct.unpack(fmt, nip_in_c) + +def unpack_and_hostify_sa(laddr, lport, raddr, rport): + return (ntohip(unpack_nip(laddr)), socket.ntohs(lport), + ntohip(unpack_nip(raddr)), socket.ntohs(rport)) + +class SimpleSubnet(object): + def _parse_ip4(self): + hip = 0L + dec_u8 = self.ip_str.split(".") + for i in dec_u8: + hip = hip << 8 + hip |= long(i) + self.hip = hip + + def _parse_ip6(self): + hip = 0L; + hex_u16 = self.ip_str.split(":") + if self.ip_str.endswith("::"): + if hex_u16.count("") > 2: + raise Exception("Error in parsing IPv6") + cpz_zeros = 8 - len(hex_u16) + 2 + hex_u16 = hex_u16[:-1] + elif "" in hex_u16: + if hex_u16.count("") > 1: + raise Exception("Error in parsing IPv6") + cpz_zeros = 8 - len(hex_u16) + 1 + for i in hex_u16: + if len(i) == 0: + for j in range(cpz_zeros): + hip = hip << 16 + else: + hip = hip << 16; + hip |= long(i, 16) + self.hip = hip + + def _parse_ip(self, ip_str): + slash_start = ip_str.find("/") + if slash_start == -1: + self.ip_str = ip_str + self.plen = 0 + else: + self.ip_str = ip_str[0:slash_start] + self.plen = int(ip_str[slash_start+1:]) + + if ':' in self.ip_str: + self._parse_ip6() + self.is_ip6 = True + if self.plen == 0: + self.plen = 128 + self.netmask = 0xffffffffffffffffffffffffffffffffL >> (128 - self.plen) << (128 - self.plen) + else: + self._parse_ip4() + self.is_ip6 = False + if self.plen == 0: + self.plen = 32 + self.netmask = 0xffffffffL >> (32 - self.plen) << (32 - self.plen) + + def _min_ip(self): + return self.hip & self.netmask + + def _max_ip(self): + if self.is_ip6: + return self._min_ip() | (0xffffffffffffffffffffffffffffffffL - self.netmask) + else: + return self._min_ip() | (0xffffffffL - self.netmask) + + def __contains__(self, hip): + return self._min_ip() <= hip <= self._max_ip() + + def __init__(self, ip_str): + self._parse_ip(ip_str) + +class SimpleFilter(object): + def __init__(self, lsn, lhport, rsn, rhport): + self.lsn = lsn + self.rsn = rsn + self.lhport = lhport + self.rhport = rhport + + def match(self, lhip, lhport, rhip, rhport): + if self.lsn and lhip not in self.lsn: + return False + if self.rsn and rhip not in self.rsn: + return False + if self.lhport and self.lhport != lhport: + return False + if self.rhport and self.rhport != rhport: + return False + + return True + +class TcpSummary(object): + def __init__(self): + self.snd_cwnd_sum = 0 + self.snd_cwnd_count = 0 + self.max_snd_cwnd = 0 + self.min_snd_cwnd = 0xffffffff + self.segs_out = 0 + self.data_segs_out = 0 + self.data_octets_out = 0 + self.loss_rxmits = 0 + self.other_rxmits = 0 + self.dup_acks = 0 + self.established = 0 + self.close = 0 + + def add_loss_rxmits(self, n): + self.loss_rxmits += n + + def add_other_rxmits(self, n): + self.other_rxmits += n + + def add_segs_out(self, n): + self.segs_out += n + + def add_data_segs_out(self, n): + self.data_segs_out += n + + def add_data_octets_out(self, n): + self.data_octets_out += n + + def add_snd_cwnd_sample(self, n): + self.snd_cwnd_sum += n + self.snd_cwnd_count += 1 + self.min_snd_cwnd = min(self.min_snd_cwnd, n) + self.max_snd_cwnd = max(self.max_snd_cwnd, n) + + def inc_dup_acks(self): + self.dup_acks += 1 + + def inc_established(self): + self.established += 1 + + def inc_close(self): + self.close += 1 + + def report(self): + if self.snd_cwnd_count == 0: + avg_cwnd = 0 + min_snd_cwnd = 0 + else: + avg_cwnd = self.snd_cwnd_sum / self.snd_cwnd_count + min_snd_cwnd = self.min_snd_cwnd + rxmit_rate = (self.loss_rxmits + self.other_rxmits) * 100.0 / \ + self.data_segs_out if self.data_segs_out else 0 + print "snd_cwnd(avg/min/max): %u/%u/%u" % (avg_cwnd, + min_snd_cwnd, + self.max_snd_cwnd) + print "segs out: %u" % self.segs_out + print "data segs out: %u" % self.data_segs_out + print "octets out: %u" % self.data_octets_out + print "loss rxmits: %u" % self.loss_rxmits + print "other rxmits: %u" % self.other_rxmits + print "rxmits%%: %.3f" % rxmit_rate + print "dup_acks: %u" % self.dup_acks + print "established: %u" % self.established + print "close: %u" % self.close + +parser = argparse.ArgumentParser() +parser.add_argument("--laddr", help="Local address in IP[/prefix-len]") +parser.add_argument("--raddr", help="Remote address in IP[/prefix-len]") +parser.add_argument("--lport", type=int, default=0, help="Local port") +parser.add_argument("--rport", type=int, default=0, help="Remote port") +args = parser.parse_args() +lsn = SimpleSubnet(args.laddr) if args.laddr else None +rsn = SimpleSubnet(args.raddr) if args.raddr else None +addr_filter = SimpleFilter(lsn, args.lport, rsn, args.rport) +tcp_summary = TcpSummary() + +def trace_begin(): + pass + +def trace_end(): + tcp_summary.report(); + +def tcp__tcp_transmit_skb(event_name, context, common_cpu, + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, ipv6, laddr, raddr, lport, + rport, seq, end_seq, pcount, ca_state, + snd_nxt, snd_una, snd_wnd, snd_cwnd, mss_cache, + ssthresh, srtt_us, rto_ms): + + if not addr_filter.match(*unpack_and_hostify_sa(laddr, lport, + raddr, rport)): + return + + tcp_summary.add_segs_out(pcount) + if end_seq > seq: + tcp_summary.add_snd_cwnd_sample(snd_cwnd) + if seq < snd_nxt: + if ca_state == 4: + tcp_summary.add_loss_rxmits(pcount) + else: + tcp_summary.add_other_rxmits(pcount) + else: + tcp_summary.add_data_segs_out(pcount) + tcp_summary.add_data_octets_out(end_seq - seq) + +def tcp__tcp_rcv_established(event_name, context, common_cpu, + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, ipv6, laddr, raddr, lport, + rport, seq, end_seq, ack_seq, snd_una, + rcv_nxt, rcv_wnd): + if not addr_filter.match(*unpack_and_hostify_sa(laddr, lport, + raddr, rport)): + return + + if seq == end_seq and ack_seq == snd_una: + tcp_summary.inc_dup_acks() + +def tcp__tcp_established(event_name, context, common_cpu, + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, ipv6, laddr, raddr, lport, + rport, snd_cwnd, mss_cache, ssthresh, srtt_us, + rto_ms): + + if not addr_filter.match(*unpack_and_hostify_sa(laddr, lport, + raddr, rport)): + return + + tcp_summary.inc_established() + +def tcp__tcp_close(event_name, context, common_cpu, + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, ipv6, laddr, raddr, lport, + rport, snd_cwnd, mss_cache, ssthresh, srtt_us, + rto_ms): + + if not addr_filter.match(*unpack_and_hostify_sa(laddr, lport, + raddr, rport)): + return + + tcp_summary.inc_close() + +def trace_unhandled(event_name, context, event_fields_dict): + print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) + +def print_header(event_name, cpu, secs, nsecs, pid, comm): + print "%-20s %5u %05u.%09u %8u %-20s " % \ + (event_name, cpu, secs, nsecs, pid, comm), -- 1.8.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists