/
usr
/
share
/
systemtap
/
examples
/
network
/
/usr/share/systemtap/examples/network
mkdir
upload
Name
Size
Mode
Actions
autofs4.meta
397
0644
edit
dl
rm
autofs4.stp
4167
0755
edit
dl
rm
connect_stat.meta
404
0644
edit
dl
rm
connect_stat.stp
1019
0755
edit
dl
rm
dropwatch.meta
494
0644
edit
dl
rm
dropwatch.stp
900
0755
edit
dl
rm
netdev.meta
389
0644
edit
dl
rm
netdev.stp
1458
0755
edit
dl
rm
netfilter_drop.meta
630
0644
edit
dl
rm
netfilter_drop.stp
1156
0755
edit
dl
rm
netfilter_summary.meta
587
0644
edit
dl
rm
netfilter_summary.stp
591
0755
edit
dl
rm
netfilter_summary.txt
2873
0644
edit
dl
rm
netfilter_summary_json.meta
511
0644
edit
dl
rm
netfilter_summary_json.stp
1070
0644
edit
dl
rm
nettop.meta
519
0644
edit
dl
rm
nettop.stp
989
0755
edit
dl
rm
nettop.txt
953
0644
edit
dl
rm
net_xmit_json.meta
453
0644
edit
dl
rm
net_xmit_json.stp
1801
0644
edit
dl
rm
nfsd-recent.meta
423
0644
edit
dl
rm
nfsd-recent.stp
442
0755
edit
dl
rm
nfsd-trace.meta
314
0644
edit
dl
rm
nfsd-trace.stp
701
0644
edit
dl
rm
nfsd-trace.txt
876
0644
edit
dl
rm
nfsdtop.meta
405
0644
edit
dl
rm
nfsdtop.stp
3385
0755
edit
dl
rm
nfsd_unlink.meta
479
0644
edit
dl
rm
nfsd_unlink.stp
523
0755
edit
dl
rm
packet_contents.meta
550
0644
edit
dl
rm
packet_contents.stp
216
0755
edit
dl
rm
packet_contents.txt
2066
0644
edit
dl
rm
sk_stream_wait_memory.meta
742
0644
edit
dl
rm
sk_stream_wait_memory.stp
999
0755
edit
dl
rm
socket-trace.meta
702
0644
edit
dl
rm
socket-trace.stp
222
0755
edit
dl
rm
socktop
9144
0755
edit
dl
rm
socktop.meta
548
0644
edit
dl
rm
socktop.txt
4135
0644
edit
dl
rm
stp_dump.meta
339
0644
edit
dl
rm
stp_dump.stp
568
0644
edit
dl
rm
stp_dump.txt
1632
0644
edit
dl
rm
tcpdumplike.meta
381
0644
edit
dl
rm
tcpdumplike.stp
581
0755
edit
dl
rm
tcpipstat.meta
725
0644
edit
dl
rm
tcpipstat.stp
18247
0755
edit
dl
rm
tcpipstat.txt
898
0644
edit
dl
rm
tcp_connections.meta
625
0644
edit
dl
rm
tcp_connections.stp
361
0755
edit
dl
rm
tcp_init_cwnd.meta
589
0644
edit
dl
rm
tcp_init_cwnd.stp
343
0755
edit
dl
rm
tcp_retransmission.meta
286
0644
edit
dl
rm
tcp_retransmission.stp
1182
0644
edit
dl
rm
tcp_trace.meta
684
0644
edit
dl
rm
tcp_trace.stp
19095
0755
edit
dl
rm
tcp_trace.txt
3465
0644
edit
dl
rm
who_sent_it.meta
583
0644
edit
dl
rm
who_sent_it.stp
477
0644
edit
dl
rm
who_sent_it.txt
803
0644
edit
dl
rm
Edit:
/usr/share/systemtap/examples/network/tcp_trace.stp
(19095B)
#!/usr/bin/stap /* * Copyright (C) 2009 IBM Corp. * Copyright (C) 2015 Red Hat, Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. * * Version 0.1 wilder@us.ibm.com 2009-05-13 * Version 0.3 varuncha@in.ibm.com 2009-05-20 * Version 1.0 wilder@us.ibm.com 2009-09-24 * Version 1.1 wilder@us.ibm.com 2009-10-08 * * Tcp connection tracing utility. * * Description: * This script traces tcp connections and displays connection parameters. * The filter option specifies what parameters are to be displayed. Address * "rules" must be supplied to limit what connections are to be traced. * * Synopsis: * tcp_trace.stp [filter=all|state|txq|rxq|srtt|snd_cwnd|snd_wnd|rexmit\ * |pmtu|ssthresh|timer|rcvwnd|length]\ * [timeout=<N sec>]\ * [update=change|all]\ * * Rule format: * <local ip-address>:<local-port>-<remote ip-address>:<remote-port> * * filter tcp_trace collects the socket state and other connection * parameters from various probe points in the tcp stack; however, * not all this data may needed when debugging a tcp problem. * Specifying only the required parameters reduces analysis time. * Multiple parameters can be specified by using * ','. * * timeout (optional) When a timeout value (in seconds) is specified * tcp_trace will automatically terminate it's run at the end of * the specified time. By default the script will run until the * user terminates it by typing a ^c. * * update (optional) By default the script only displays data if there * is a value change in a parameters specified in the "filter". * This can be changed by specifying "update=all", which will * output parameters of every packet that hits the probe. * Note: Changes to the packet length will not trigger an update. * * Rules Rules limit what connections will be traced. Multiple rules may * be given separated by a space. A wild-card value can be used * for any component of the filter. Rules can be used to limit * tracing to a single socket or allow many sockets to be traced. * Memory consumed by the tracer will increase with the number * of connections being traced. * * The Rule Format is: * <local-address>:<local-port>-<remote address>:<remote-port> * * -Address are specified as ipv4 dot notation address. * -Ports are specified as decimal numbers. * * "*" character can be used in any field to indicate a wild-card * value. * * Note: The number of active sockets that can be traced is * limited by MAXMAPENTRIES. * * Examples: * Here are some examples of using tcp_trace: * * Trace TCP connection from 172.16.15.160 to 172.16.15.1 on * port 22 with state,txq,rxq,pmtu filter. * * tcp_trace.stp filter=state,txq,rxq,pmtu timeout=100\ * 172.16.15.160:*-172.16.15.1:22 * * Trace TCP connection from any address to the local http server. * all parameters are displayed for every packet. * * tcp_trace.stp filter=all update=all *.*.*.*:*-*.*.*.*:80 */ global tcp_state; global timer_info; global filter; global key_list; global lastkey; global number_of_rules; global timeout = -1; global always_update; global snd_cwnd_flg; global snd_cwnd; global snd_wnd_flg; global snd_wnd; global srtt_flg; global srtt; global state_flg; global state; global txq_flg; global txq; global rxq_flg; global rxq; global rexmit_flg; global rexmit; global pmtu_flg; global pmtu; global ssthresh_flg; global ssthresh; global timer_flg; global tx_timer; global find_timer; global rcvwnd_flg; global rcvwnd; global length_flg; global length; probe begin { number_of_rules = process_cmdline() if ( number_of_rules < 1) usage("One or more connection rules must be specified!") if ( number_of_rules < 0 ) usage("Incorrect connection rule format!") init_tcp_state() init_timer_info() printf("Start TCP Probing.....\n\n"); print_header(); } function init_tcp_state () { tcp_state[1] = "ESTABLISHED" tcp_state[2] = "SYN_SENT" tcp_state[3] = "SYN_RECV" tcp_state[4] = "FIN_WAIT1" tcp_state[5] = "FIN_WAIT2" tcp_state[6] = "TIME_WAIT" tcp_state[7] = "CLOSE" tcp_state[8] = "CLOSE_WAIT" tcp_state[9] = "LAST_ACK" tcp_state[10] = "LISTEN" tcp_state[11] = "CLOSING" } function state_num2str:string ( state:long ) { return (state in tcp_state ? tcp_state[state] : "UNDEF") } function init_timer_info () { timer_info[0] = "" timer_info[1] = "Rxmit" timer_info[2] = "Delack" timer_info[3] = "Probe" timer_info[4] = "Keepalv" } function timer_info_num2str:string ( timer:long ) { return (timer in timer_info ? timer_info[timer] : "UNDEF") } probe kernel.{function("tcp_rcv_established"), function("tcp_rcv_state_process")} { sk = $sk key = filter_key(sk) if ( !key ) next; if ( is_packet_updated(key,sk) ) { length[key] = $skb->len; print_packet_info(key, 0) } } probe kernel.function("tcp_transmit_skb") { sk = $sk key = filter_key(sk) if ( !key ) next; if ( is_packet_updated(key,sk) ) { length[key] = $skb->len; print_packet_info(key, 1) } } probe kernel.function("tcp_keepalive_timer") { if ( !timer_flg ) next; sk = @choose_defined($data, & @container_of($t, "struct sock", sk_timer)) key = filter_key(sk) if ( !key ) next; is_packet_updated(key,sk) length[key] = 0 tx_timer[key] = 4; print_packet_info(key, 1) tx_timer[key] = 0; } probe kernel.function("tcp_delack_timer") { if ( !timer_flg ) next; sk = @choose_defined($data, & @container_of($t, "struct inet_connection_sock", icsk_delack_timer)->icsk_inet->sk) key = filter_key(sk) if ( !key ) next; is_packet_updated(key,sk) length[key] = 0 tx_timer[key] = 2; print_packet_info(key, 1) tx_timer[key] = 0; } probe kernel.function("tcp_send_probe0") { if ( !timer_flg ) next; sk = $sk key = filter_key(sk) if ( !key ) next; if ( find_timer[key] == 3 ) { find_timer[key] = 0 tx_timer[key] = 3; is_packet_updated(key,sk) length[key] = 0 print_packet_info(key, 1) tx_timer[key] = 0; } } probe kernel.function("tcp_retransmit_skb") { if ( !timer_flg ) next; sk = $sk; key = filter_key(sk) if ( !key ) next; if ( find_timer[key] == 1 ) { find_timer[key] = 0 tx_timer[key] = 1; is_packet_updated(key,sk) length[key] = $skb->len print_packet_info(key,1) tx_timer[key] = 0; } } probe kernel.function("tcp_write_timer") { if ( !timer_flg ) next; sk = @choose_defined($data, & @container_of($t, "struct inet_connection_sock", icsk_retransmit_timer)->icsk_inet->sk ) key = filter_key(sk) if ( !key ) next; /* Don't trace calls to tcp_retransmit_skb() * or tcp_send_probe0 that were not the result of a * write timer expiration. */ find_timer[key] = @cast(sk, "inet_connection_sock")->icsk_pending } %( kernel_v > "2.6.24" %? probe kernel.function("tcp_set_state") { sk = $sk new_state = $state TCP_CLOSE = 7 TCP_CLOSE_WAIT = 8 key = filter_key(sk) if ( key && ((new_state == TCP_CLOSE)||(new_state == TCP_CLOSE_WAIT))){ if (state_flg && state[key]) print_close(key,new_state); clean_up(key); } } %) function print_header() { printf("%-22s","Source Address") printf("%-22s","Dest Address") if (state_flg) printf("%-12s","State") if (timer_flg) printf("%-8s","Timer") if (txq_flg) printf("%8s","Tx-Q") if (rxq_flg) printf("%8s","Rx-Q") if (pmtu_flg) printf("%8s","PMTU") if (snd_cwnd_flg) printf("%8s","SndCwnd") if (snd_wnd_flg) printf("%8s","SndWnd") if (rcvwnd_flg) printf("%8s","RcvWnd") if (srtt_flg) printf("%8s","SSRT") if (ssthresh_flg) printf("%14s","Ssthreshold") if (rexmit_flg) printf("%8s","Rexmit") if (length_flg) printf("%8s","Length") printf("\n"); } function print_packet_info:long ( key:long, SourceIsLocal:long) { foreach ( [laddr, raddr, lport, rport] in key_list ){ if ( key_list[laddr, raddr, lport, rport] == key ) break } local_addr = sprintf("%s:%d",ip_ntop(htonl(laddr)), lport) remote_addr = sprintf("%s:%d",ip_ntop(htonl(raddr)) ,rport) SourceIsLocal ? printf("%-22s%-22s",local_addr,remote_addr): printf("%-22s%-22s",remote_addr,local_addr) if (state_flg) printf("%-12s",state_num2str(state[key])) if (timer_flg) printf("%-8s",timer_info_num2str(tx_timer[key])) if (txq_flg) printf("%8d",txq[key]) if (rxq_flg) printf("%8d",rxq[key]) if (pmtu_flg) printf("%8d",pmtu[key]) if (snd_cwnd_flg) printf("%8d",snd_cwnd[key]) if (snd_wnd_flg) printf("%8d",snd_wnd[key]) if (rcvwnd_flg) printf("%8d",rcvwnd[key]) if (srtt_flg) printf("%8d",srtt[key]) if (ssthresh_flg) printf("%14d",ssthresh[key]) if (rexmit_flg) printf("%8d",rexmit[key]) if (length_flg && length[key]) printf("%8d", length[key]) printf("\n"); } %( kernel_v > "2.6.24" %? function print_close:long (key:long, new_state:long) { foreach ( [laddr, raddr, lport, rport] in key_list ){ if ( key_list[laddr, raddr, lport, rport] == key ) break } local_addr = sprintf("%s:%d",ip_ntop(htonl(laddr)), lport) remote_addr = sprintf("%s:%d",ip_ntop(htonl(raddr)) ,rport) printf("%-22s%-22s",local_addr,remote_addr) printf("%-12s",state_num2str(new_state)) printf("\n"); } %) /* * Update the values in the data collection arrays, returns 1 if one or more * values have changed. */ function is_packet_updated:long ( key:long, sk:long ) { packet_updated = 0 if ( !key ) return 0 if ( state_flg ) { new_state = @cast(sk, "sock_common")->skc_state if( always_update || (state[key] != new_state) ){ state[key]= new_state packet_updated = 1 } } if ( txq_flg ) { if(@cast(sk, "sock_common")->skc_state == 10) new_txq = @cast(sk, "sock")->sk_max_ack_backlog else new_txq = @cast(sk, "tcp_sock")->write_seq - @cast(sk, "tcp_sock")->snd_una if( always_update || (txq[key] != new_txq) ){ txq[key] = new_txq packet_updated = 1 } } if ( rxq_flg ) { if(@cast(sk, "sock_common")->skc_state == 10) new_rxq = @cast(sk, "sock")->sk_ack_backlog else new_rxq = @cast(sk, "tcp_sock")->rcv_nxt - @cast(sk, "tcp_sock")->copied_seq if( always_update || (rxq[key] != new_rxq) ){ rxq[key] = new_rxq packet_updated = 1 } } if( rexmit_flg ) { new_rexmit = @cast(sk, "inet_connection_sock")->icsk_retransmits if( always_update || (rexmit[key] != new_rexmit ) ){ rexmit[key] = new_rexmit packet_updated = 1 } } if ( pmtu_flg ) { new_pmtu = @cast(sk, "inet_connection_sock")->icsk_pmtu_cookie if( always_update || (pmtu[key] != new_pmtu) ){ pmtu[key] = new_pmtu packet_updated = 1 } } if ( snd_cwnd_flg ) { new_snd_cwnd = @cast(sk, "tcp_sock")->snd_cwnd if( always_update || (snd_cwnd[key] != new_snd_cwnd) ){ snd_cwnd[key] = new_snd_cwnd packet_updated = 1 } } if ( snd_wnd_flg ) { new_snd_wnd = @cast(sk, "tcp_sock")->snd_wnd if( always_update || (snd_wnd[key] != new_snd_wnd) ){ snd_wnd[key] = new_snd_wnd packet_updated = 1 } } if ( srtt_flg ) { new_srtt = @choose_defined(@cast(sk, "tcp_sock")->srtt_us, @cast(sk, "tcp_sock")->srtt) if( always_update || (srtt[key] != new_srtt) ){ srtt[key] = new_srtt packet_updated = 1 } } if( ssthresh_flg ) { new_ssthresh = tcp_current_ssthresh(sk) if( always_update || (ssthresh[key] != new_ssthresh) ){ ssthresh[key] = new_ssthresh packet_updated = 1 } } if ( rcvwnd_flg ) { new_rcvwnd = @cast(sk, "tcp_sock")->rcv_wnd if( always_update || (rcvwnd[key] != new_rcvwnd) ){ rcvwnd[key] = new_rcvwnd packet_updated = 1 } } return packet_updated } /* * copied from: * include/net/tcp.h:tcp_current_ssthresh() */ function tcp_current_ssthresh(sk:long) { if ((1 << @cast(sk, "inet_connection_sock")->icsk_ca_state) & ((1 << 2) | (1 << 3))){ return @cast(sk, "tcp_sock")->snd_ssthresh }else{ return netmax(@cast(sk, "tcp_sock")->snd_ssthresh, ((@cast(sk, "tcp_sock")->snd_cwnd >>1)+ (@cast(sk, "tcp_sock")->snd_cwnd >> 2))) } } function netmax:long (val1:long, val2:long) { if(val1 > val2) return val1 else return val2 } /* All command line arguments other than the address rules are processed * first and must be placed on the command line prior to any address rules. */ function process_cmdline:long () { filter_number = 0 for (i=1; i <= argc; i++) { argument = tokenize(argv[i], "=") if (argument == "help") usage("") if (argument == "filter") { filter_given=1; argv[i]="" while(strlen(byte = tokenize(argv[i], ",")) != 0) { argv[i] = "" if ( byte == "snd_cwnd" ) { snd_cwnd_flg = 1; continue }; if ( byte == "snd_wnd" ) { snd_wnd_flg = 1; continue }; if ( byte == "srtt" ) { srtt_flg = 1; continue }; %( kernel_v > "2.6.24" %? if ( byte == "state" ) { state_flg = 1; continue }; %: state_flg = 0; %) if ( byte == "txq" ) { txq_flg = 1; continue }; if ( byte == "rxq" ) { rxq_flg = 1; continue }; if ( byte == "rexmit" ) { rexmit_flg = 1; continue }; if ( byte == "pmtu" ) { pmtu_flg = 1; continue }; if ( byte == "ssthresh" ) { ssthresh_flg = 1; continue }; if ( byte == "timer" ) { timer_flg = 1; continue }; if ( byte == "rcvwnd" ) { rcvwnd_flg = 1; continue }; if ( byte == "length" ) { length_flg = 1; continue }; if ( byte == "all" ) { snd_cwnd_flg = snd_wnd_flg = srtt_flg = txq_flg = rxq_flg = rexmit_flg = pmtu_flg = ssthresh_flg = timer_flg = rcvwnd_flg = length_flg = 1; %( kernel_v > "2.6.24" %? state_flg = 1; %) continue }; usage("Unknown filter value given!") } continue; } if ( argument == "timeout" ){ argv[i]="" timeout=strtol(tokenize(argv[i], "="),10) continue; } if ( argument == "update") { argv[i]="" update_disp = tokenize(argv[i], "=") if (update_disp == "all") always_update = 1; continue; } /* Anything on the command line after this point must * be an address rule. */ source = tokenize(argv[i], "-") argv[i] = "" dest = tokenize(argv[i], "-") source_addr = tokenize(source, ":") source="" source_port = tokenize(source, ":") dest_addr = tokenize(dest, ":") dest="" dest_port = tokenize(dest, ":") /* stap bug */ if ( dest_port == "fobar") i=i; ++filter_number; j=filter_number*6; filter[j] = ipv4_pton(source_addr,0) // Source address filter[j+1] = ipv4_pton(source_addr,1) // Source address mask filter[j+2] = ipv4_portton(source_port) // Source port filter[j+3] = ipv4_pton(dest_addr,0) // Dest address filter[j+4] = ipv4_pton(dest_addr,1) // Dest address mask filter[j+5] = ipv4_portton(dest_port) // Dest port if (filter[j]< -1 || filter[j+1] < -1 || filter[j+2] < -1 || filter[j+3] < -1 || filter[j+4] < -1 || filter[j+5] < -1 ) return -1; } /* default filter is all */ if ( !filter_given ) snd_cwnd_flg = snd_wnd_flg = srtt_flg = txq_flg = rxq_flg = rexmit_flg = pmtu_flg = ssthresh_flg = timer_flg = rcvwnd_flg = length_flg = 1; %( kernel_v > "2.6.24" %? state_flg = 1; %) return filter_number; } /* * Convert an ascii integer values between 0 and 65534 to a u16 port number. * "*" are treated as wildcards and will be converted to -1. */ function ipv4_portton:long (port:string) { if ( port == "*" ) return -1; pport=strtol(port,10); if ( pport > 0xffff ){ printf("Bad port number %s\n",port) return -22; } return pport } /* * Convert ipv4 dot notation address into longs. * Supports "*" in any field treating it as a wildcard by making the byte=0. * If make_mask is set it creates a mask based on the "*" fields. All non='*' * bytes are set to 0xff all * fields are set to 0x0;. */ function ipv4_pton:long (addr:string, make_mask:long) { i=32; ip=0; ips=addr; while(strlen(byte = tokenize(ips, ".")) != 0) { i-=8; ips=""; if ( byte == "*" ){ byte = "0" } else { if ( make_mask ) byte = "255"; } j=strtol(byte,10); if ( j > 255 ){ printf("bad address %s\n",addr) return -22; } ip=ip+(j<<i) // left shift the byte into the address } if ( i != 0 ){ printf("bad address %s\n",addr) return -22; } return ip; } /* * Returns a unique value (stored in the global key_list) based on the socket * address tuple. A new value is created if one does not already exist. */ function build_key:long (laddr:long, raddr:long, lport:long, rport:long) { if ( key_list[laddr, raddr, lport, rport] ) return key_list[laddr, raddr, lport, rport] else return key_list[laddr, raddr, lport, rport] = ++lastkey } /* * Checks the tuple against the rule list. If we pass through the rule * then return a unique key value, otherwise return zero. */ function filter_key:long (sk:long) { laddr = tcpmib_local_addr(sk); raddr = tcpmib_remote_addr(sk); lport = tcpmib_local_port(sk); rport = tcpmib_remote_port(sk); for (i=1; i <= number_of_rules; i++){ j=i*6; // Local filter local_filter=remote_filter=0; if ( (laddr&filter[j+1]) == filter[j] ) { if ( (filter[j+2] == -1 ) || (lport == filter[j+2])) local_filter = 1; } // Remote filter if ( (raddr&filter[j+4]) == filter[j+3] ) { if ( (filter[j+5] == -1 ) || (rport == filter[j+5])) remote_filter = 1; } if(local_filter && remote_filter){ return build_key(laddr, raddr, lport, rport); } } return 0; } /* Free up a slot in the data arrays */ %( kernel_v > "2.6.24" %? function clean_up (key:long) { foreach ( [laddr, raddr, lport, rport] in key_list ){ if ( key_list[laddr, raddr, lport, rport] == key ){ break } } delete key_list[laddr, raddr, lport, rport] if (snd_cwnd_flg) delete snd_cwnd[key]; if (snd_wnd_flg) delete snd_wnd[key]; if (srtt_flg) delete srtt[key]; if (state_flg) delete state[key]; if (txq_flg) delete txq[key]; if (rxq_flg) delete rxq[key]; if (rexmit_flg) delete rexmit[key]; if (pmtu_flg) delete pmtu[key]; if (ssthresh_flg) delete ssthresh[key]; if ( timer_flg ) { delete tx_timer[key]; delete find_timer[key]; } if (rcvwnd_flg) delete rcvwnd[key]; delete length[key]; } %) /* Terminates the run in timeout seconds, using global timeout value */ probe timer.s(1) { if ( timeout == -1 ) next if ( !--timeout ) exit() } function usage (msg:string) { printf("\nUsage:\n"); printf("\ttcp_trace.stp filter=<list of filters>[timeout=<sec>] \n"); printf("\t\t\t[update=change|all] Rule\n\n"); printf("\tRule format:"); printf("<local address>:<local-port>-<remote address>:<remote-port>\n"); %( kernel_v > "2.6.24" %? printf("\tFilter values: all|state|txq|rxq|srtt|snd_cwnd|snd_wnd|\n"); %: printf("\tFilter values: all|txq|rxq|srtt|snd_cwnd|snd_wnd|\n"); %) printf("\t\t\trexmit|pmtu|ssthresh|timer|rcvwnd\n\n"); printf("%s\n\n",msg); error(msg); }
Save
cmd:
run