linux下 ss -i 可显示rto.
how to display tcp rto
http://linuxaleph.blogspot.com/2013/07/how-to-display-tcp-rto.html
1 /* 2 * ss.c "sockstat", socket statistics 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 #include <syslog.h> 16 #include <fcntl.h> 17 #include <sys/ioctl.h> 18 #include <sys/socket.h> 19 #include <sys/uio.h> 20 #include <netinet/in.h> 21 #include <string.h> 22 #include <errno.h> 23 #include <netdb.h> 24 #include <arpa/inet.h> 25 #include <resolv.h> 26 #include <dirent.h> 27 #include <fnmatch.h> 28 #include <getopt.h> 29 30 #include "utils.h" 31 #include "rt_names.h" 32 #include "ll_map.h" 33 #include "libnetlink.h" 34 #include "SNAPSHOT.h" 35 36 #include <netinet/tcp.h> 37 #include <linux/inet_diag.h> 38 39 int resolve_hosts = 0; 40 int resolve_services = 1; 41 int preferred_family = AF_UNSPEC; 42 int show_options = 0; 43 int show_details = 0; 44 int show_users = 0; 45 int show_mem = 0; 46 int show_tcpinfo = 0; 47 48 int netid_width; 49 int state_width; 50 int addrp_width; 51 int addr_width; 52 int serv_width; 53 int screen_width; 54 55 static const char *TCP_PROTO = "tcp"; 56 static const char *UDP_PROTO = "udp"; 57 static const char *RAW_PROTO = "raw"; 58 static const char *dg_proto = NULL; 59 60 enum 61 { 62 TCP_DB, 63 DCCP_DB, 64 UDP_DB, 65 RAW_DB, 66 UNIX_DG_DB, 67 UNIX_ST_DB, 68 PACKET_DG_DB, 69 PACKET_R_DB, 70 NETLINK_DB, 71 MAX_DB 72 }; 73 74 #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB)) 75 #define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)) 76 #define ALL_DB ((1<<MAX_DB)-1) 77 78 enum { 79 SS_UNKNOWN, 80 SS_ESTABLISHED, 81 SS_SYN_SENT, 82 SS_SYN_RECV, 83 SS_FIN_WAIT1, 84 SS_FIN_WAIT2, 85 SS_TIME_WAIT, 86 SS_CLOSE, 87 SS_CLOSE_WAIT, 88 SS_LAST_ACK, 89 SS_LISTEN, 90 SS_CLOSING, 91 SS_MAX 92 }; 93 94 #define SS_ALL ((1<<SS_MAX)-1) 95 96 #include "ssfilter.h" 97 98 struct filter 99 { 100 int dbs; 101 int states; 102 int families; 103 struct ssfilter *f; 104 }; 105 106 struct filter default_filter = { 107 .dbs = (1<<TCP_DB), 108 .states = SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)), 109 .families= (1<<AF_INET)|(1<<AF_INET6), 110 }; 111 112 struct filter current_filter; 113 114 static FILE *generic_proc_open(const char *env, const char *name) 115 { 116 const char *p = getenv(env); 117 char store[128]; 118 119 if (!p) { 120 p = getenv("PROC_ROOT") ? : "/proc"; 121 snprintf(store, sizeof(store)-1, "%s/%s", p, name); 122 p = store; 123 } 124 125 return fopen(p, "r"); 126 } 127 128 static FILE *net_tcp_open(void) 129 { 130 return generic_proc_open("PROC_NET_TCP", "net/tcp"); 131 } 132 133 static FILE *net_tcp6_open(void) 134 { 135 return generic_proc_open("PROC_NET_TCP6", "net/tcp6"); 136 } 137 138 static FILE *net_udp_open(void) 139 { 140 return generic_proc_open("PROC_NET_UDP", "net/udp"); 141 } 142 143 static FILE *net_udp6_open(void) 144 { 145 return generic_proc_open("PROC_NET_UDP6", "net/udp6"); 146 } 147 148 static FILE *net_raw_open(void) 149 { 150 return generic_proc_open("PROC_NET_RAW", "net/raw"); 151 } 152 153 static FILE *net_raw6_open(void) 154 { 155 return generic_proc_open("PROC_NET_RAW6", "net/raw6"); 156 } 157 158 static FILE *net_unix_open(void) 159 { 160 return generic_proc_open("PROC_NET_UNIX", "net/unix"); 161 } 162 163 static FILE *net_packet_open(void) 164 { 165 return generic_proc_open("PROC_NET_PACKET", "net/packet"); 166 } 167 168 static FILE *net_netlink_open(void) 169 { 170 return generic_proc_open("PROC_NET_NETLINK", "net/netlink"); 171 } 172 173 static FILE *slabinfo_open(void) 174 { 175 return generic_proc_open("PROC_SLABINFO", "slabinfo"); 176 } 177 178 static FILE *net_sockstat_open(void) 179 { 180 return generic_proc_open("PROC_NET_SOCKSTAT", "net/sockstat"); 181 } 182 183 static FILE *net_sockstat6_open(void) 184 { 185 return generic_proc_open("PROC_NET_SOCKSTAT6", "net/sockstat6"); 186 } 187 188 static FILE *net_snmp_open(void) 189 { 190 return generic_proc_open("PROC_NET_SNMP", "net/snmp"); 191 } 192 193 static FILE *ephemeral_ports_open(void) 194 { 195 return generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", "sys/net/ipv4/ip_local_port_range"); 196 } 197 198 struct user_ent { 199 struct user_ent *next; 200 unsigned int ino; 201 int pid; 202 int fd; 203 char process[0]; 204 }; 205 206 #define USER_ENT_HASH_SIZE 256 207 struct user_ent *user_ent_hash[USER_ENT_HASH_SIZE]; 208 209 static int user_ent_hashfn(unsigned int ino) 210 { 211 int val = (ino >> 24) ^ (ino >> 16) ^ (ino >> 8) ^ ino; 212 213 return val & (USER_ENT_HASH_SIZE - 1); 214 } 215 216 static void user_ent_add(unsigned int ino, const char *process, int pid, int fd) 217 { 218 struct user_ent *p, **pp; 219 int str_len; 220 221 str_len = strlen(process) + 1; 222 p = malloc(sizeof(struct user_ent) + str_len); 223 if (!p) 224 abort(); 225 p->next = NULL; 226 p->ino = ino; 227 p->pid = pid; 228 p->fd = fd; 229 strcpy(p->process, process); 230 231 pp = &user_ent_hash[user_ent_hashfn(ino)]; 232 p->next = *pp; 233 *pp = p; 234 } 235 236 static void user_ent_hash_build(void) 237 { 238 const char *root = getenv("PROC_ROOT") ? : "/proc/"; 239 struct dirent *d; 240 char name[1024]; 241 int nameoff; 242 DIR *dir; 243 244 strcpy(name, root); 245 if (strlen(name) == 0 || name[strlen(name)-1] != '/') 246 strcat(name, "/"); 247 248 nameoff = strlen(name); 249 250 dir = opendir(name); 251 if (!dir) 252 return; 253 254 while ((d = readdir(dir)) != NULL) { 255 struct dirent *d1; 256 char process[16]; 257 int pid, pos; 258 DIR *dir1; 259 char crap; 260 261 if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1) 262 continue; 263 264 sprintf(name + nameoff, "%d/fd/", pid); 265 pos = strlen(name); 266 if ((dir1 = opendir(name)) == NULL) 267 continue; 268 269 process[0] = '