From 5a9bca7145e05637a333f87bad43909903138c09 Mon Sep 17 00:00:00 2001 From: yupeng Date: Thu, 26 Oct 2017 07:15:31 +0000 Subject: [PATCH 1/5] man: add additional explainations for ss Add detail explains of -m, -o, -e and -i options, which are not documented anywhere Signed-off-by: yupeng Acked-by: Phil Sutter Signed-off-by: Stephen Hemminger --- man/man8/ss.8 | 185 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 4 deletions(-) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 3bec97f0..8565ccb4 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -37,19 +37,196 @@ Display both listening and non-listening (for TCP this means established connect Display only listening sockets (these are omitted by default). .TP .B \-o, \-\-options -Show timer information. +Show timer information. For tcp protocol, the output format is: +.RS +.P +timer:(,,) +.P +.TP +.B +the name of the timer, there are five kind of timer names: +.RS +.P +.BR on ": means one of these timers: tcp retrans timer, tcp early retrans timer and tail loss probe timer" +.P +.BR keepalive ": tcp keep alive timer" +.P +.BR timewait ": timewait stage timer" +.P +.BR persist ": zero window probe timer" +.P +.BR unknown ": none of the above timers" +.RE +.TP +.B +how long time the timer will expire +.P +.TP +.B +how many times the retran occurs +.RE .TP .B \-e, \-\-extended -Show detailed socket information +Show detailed socket information. The output format is: +.RS +.P +uid: ino: sk: +.P +.TP +.B +the user id the socket belongs to +.P +.TP +.B +the socket's inode number in VFS +.P +.TP +.B +an uuid of the socket +.RE .TP .B \-m, \-\-memory -Show socket memory usage. +Show socket memory usage. The output format is: +.RS +.P +skmem:(r,rb,t,tb,f,w,o,bl) +.P +.TP +.B +the memory allocated for receiving packet +.P +.TP +.B +the total memory can be allocated for receiving packet +.P +.TP +.B +the memory used for sending packet (which has been sent to layer 3) +.P +.TP +.B +the total memory can be allocated for sending packet +.P +.TP +.B +the memory allocated by the socket as cache, but not used for receiving/sending packet yet. If need memory to send/receive packet, the memory in this cache will be used before allocate additional memory. +.P +.TP +.B +The memory allocated for sending packet (which has not been sent to layer 3) +.P +.TP +.B +The memory used for storing socket option, e.g., the key for TCP MD5 signature +.P +.TP +.B +The memory used for the sk backlog queue. On a process context, if the process is receiving packet, and a new packet is received, it will be put into the sk backlog queue, so it can be received by the process immediately +.RE .TP .B \-p, \-\-processes Show process using socket. .TP .B \-i, \-\-info -Show internal TCP information. +Show internal TCP information. Below fields may appear: +.RS +.P +.TP +.B ts +show string "ts" if the timestamp option is set +.P +.TP +.B sack +show string "sack" if the sack option is set +.P +.TP +.B ecn +show string "ecn" if the explicit congestion notification option is set +.P +.TP +.B ecnseen +show string "ecnseen" if the saw ecn flag is found in received packets +.P +.TP +.B fastopen +show string "fastopen" if the fastopen option is set +.P +.TP +.B cong_alg +the congestion algorithm name, the default congestion algorithm is "cubic" +.P +.TP +.B wscale:: +if window scale option is used, this field shows the send scale factory and receive scale factory +.P +.TP +.B rto: +tcp re-transmission timeout value, the unit is millisecond +.P +.TP +.B backoff: +used for exponential backoff re-transmission, the actual re-transmission timeout value is icsk_rto << icsk_backoff +.P +.TP +.B rtt:/ +rtt is the average round trip time, rttvar is the mean deviation of rtt, their units are millisecond +.P +.TP +.B ato: +ack timeout, unit is millisecond, used for delay ack mode +.P +.TP +.B mss: +max segment size +.P +.TP +.B cwnd: +congestion window size +.P +.TP +.B ssthresh: +tcp congestion window slow start threshold +.P +.TP +.B bytes_acked: +bytes acked +.P +.TP +.B bytes_received: +bytes received +.P +.TP +.B segs_out: +segments sent out +.P +.TP +.B segs_in: +segments received +.P +.TP +.B send bps +egress bps +.P +.TP +.B lastsnd: +how long time since the last packet sent, the unit is millisecond +.P +.TP +.B lastrcv: +how long time since the last packet received, the unit is millisecond +.P +.TP +.B lastack: +how long time since the last ack received, the unit is millisecond +.P +.TP +.B pacing_rate bps/bps +the pacing rate and max pacing rate +.P +.TP +.B rcv_space: +a helper variable for TCP internal auto tuning socket receive buffer +.RE .TP .B \-K, \-\-kill Attempts to forcibly close sockets. This option displays sockets that are From b97c679c9f1b36109fa439b93e6dbbeb98a9fb75 Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 8 Sep 2017 17:52:21 -0400 Subject: [PATCH 2/5] bridge: isolate vlans parsing code in a separate API IFLA_BRIDGE_VLAN_INFO parsing logic will be used in link and vlan processing code, so it makes sense to move it in the separate function. Signed-off-by: Roman Mashak --- bridge/br_common.h | 1 + bridge/vlan.c | 145 +++++++++++++++++++++++---------------------- 2 files changed, 76 insertions(+), 70 deletions(-) diff --git a/bridge/br_common.h b/bridge/br_common.h index c649e7d9..01447ddc 100644 --- a/bridge/br_common.h +++ b/bridge/br_common.h @@ -4,6 +4,7 @@ #define MDB_RTR_RTA(r) \ ((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32)))) +extern void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex); extern int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); diff --git a/bridge/vlan.c b/bridge/vlan.c index ebcdacee..fc361ae4 100644 --- a/bridge/vlan.c +++ b/bridge/vlan.c @@ -189,7 +189,6 @@ static int print_vlan(const struct sockaddr_nl *who, struct ifinfomsg *ifm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[IFLA_MAX+1]; - bool vlan_flags = false; if (n->nlmsg_type != RTM_NEWLINK) { fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n", @@ -218,75 +217,7 @@ static int print_vlan(const struct sockaddr_nl *who, ll_index_to_name(ifm->ifi_index)); return 0; } else { - struct rtattr *i, *list = tb[IFLA_AF_SPEC]; - int rem = RTA_PAYLOAD(list); - __u16 last_vid_start = 0; - - if (!filter_vlan) - print_vlan_port(fp, ifm->ifi_index); - - for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { - struct bridge_vlan_info *vinfo; - int vcheck_ret; - - if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) - continue; - - vinfo = RTA_DATA(i); - - if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)) - last_vid_start = vinfo->vid; - vcheck_ret = filter_vlan_check(vinfo); - if (vcheck_ret == -1) - break; - else if (vcheck_ret == 0) - continue; - - if (filter_vlan) - print_vlan_port(fp, ifm->ifi_index); - if (jw_global) { - jsonw_start_object(jw_global); - jsonw_uint_field(jw_global, "vlan", - last_vid_start); - if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) - continue; - } else { - fprintf(fp, "\t %hu", last_vid_start); - } - if (last_vid_start != vinfo->vid) { - if (jw_global) - jsonw_uint_field(jw_global, "vlanEnd", - vinfo->vid); - else - fprintf(fp, "-%hu", vinfo->vid); - } - if (vinfo->flags & BRIDGE_VLAN_INFO_PVID) { - if (jw_global) { - start_json_vlan_flags_array(&vlan_flags); - jsonw_string(jw_global, "PVID"); - } else { - fprintf(fp, " PVID"); - } - } - if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED) { - if (jw_global) { - start_json_vlan_flags_array(&vlan_flags); - jsonw_string(jw_global, - "Egress Untagged"); - } else { - fprintf(fp, " Egress Untagged"); - } - } - if (jw_global && vlan_flags) { - jsonw_end_array(jw_global); - vlan_flags = false; - } - - if (jw_global) - jsonw_end_object(jw_global); - else - fprintf(fp, "\n"); - } + print_vlan_info(fp, tb[IFLA_AF_SPEC], ifm->ifi_index); } if (!filter_vlan) { if (jw_global) @@ -470,6 +401,80 @@ static int vlan_show(int argc, char **argv) return 0; } +void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex) +{ + struct rtattr *i, *list = tb; + int rem = RTA_PAYLOAD(list); + __u16 last_vid_start = 0; + bool vlan_flags = false; + + if (!filter_vlan) + print_vlan_port(fp, ifindex); + + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + struct bridge_vlan_info *vinfo; + int vcheck_ret; + + if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) + continue; + + vinfo = RTA_DATA(i); + + if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)) + last_vid_start = vinfo->vid; + vcheck_ret = filter_vlan_check(vinfo); + if (vcheck_ret == -1) + break; + else if (vcheck_ret == 0) + continue; + + if (filter_vlan) + print_vlan_port(fp, ifindex); + if (jw_global) { + jsonw_start_object(jw_global); + jsonw_uint_field(jw_global, "vlan", + last_vid_start); + if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) + continue; + } else { + fprintf(fp, "\t %hu", last_vid_start); + } + if (last_vid_start != vinfo->vid) { + if (jw_global) + jsonw_uint_field(jw_global, "vlanEnd", + vinfo->vid); + else + fprintf(fp, "-%hu", vinfo->vid); + } + if (vinfo->flags & BRIDGE_VLAN_INFO_PVID) { + if (jw_global) { + start_json_vlan_flags_array(&vlan_flags); + jsonw_string(jw_global, "PVID"); + } else { + fprintf(fp, " PVID"); + } + } + if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED) { + if (jw_global) { + start_json_vlan_flags_array(&vlan_flags); + jsonw_string(jw_global, + "Egress Untagged"); + } else { + fprintf(fp, " Egress Untagged"); + } + } + if (jw_global && vlan_flags) { + jsonw_end_array(jw_global); + vlan_flags = false; + } + + if (jw_global) + jsonw_end_object(jw_global); + else + fprintf(fp, "\n"); + } +} + int do_vlan(int argc, char **argv) { ll_init_map(&rth); From 52fd1fe36c25175f79fc550e666eb0b194c7c1b4 Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 8 Sep 2017 17:52:22 -0400 Subject: [PATCH 3/5] bridge: dump vlan table information for link Kernel also reports vlans a port is member of, so print it. Since vlan table can be quite large, dump it only when detailed information is requested. Signed-off-by: Roman Mashak --- bridge/link.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bridge/link.c b/bridge/link.c index 93472ad3..60200f16 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -213,6 +213,13 @@ int print_linkinfo(const struct sockaddr_nl *who, if (aftb[IFLA_BRIDGE_MODE]) print_hwmode(fp, rta_getattr_u16(aftb[IFLA_BRIDGE_MODE])); + if (show_details) { + if (aftb[IFLA_BRIDGE_VLAN_INFO]) { + fprintf(fp, "\n"); + print_vlan_info(fp, tb[IFLA_AF_SPEC], + ifi->ifi_index); + } + } } fprintf(fp, "\n"); From fab9a18a2e527c3d35c95abd7e09f6d4bd06754c Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 8 Sep 2017 17:52:23 -0400 Subject: [PATCH 4/5] bridge: request vlans along with link information Signed-off-by: Roman Mashak --- bridge/link.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/bridge/link.c b/bridge/link.c index 60200f16..9e4206f5 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -461,9 +461,19 @@ static int brlink_show(int argc, char **argv) } } - if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) { - perror("Cannon send dump request"); - exit(1); + if (show_details) { + if (rtnl_wilddump_req_filter(&rth, PF_BRIDGE, RTM_GETLINK, + (compress_vlans ? + RTEXT_FILTER_BRVLAN_COMPRESSED : + RTEXT_FILTER_BRVLAN)) < 0) { + perror("Cannon send dump request"); + exit(1); + } + } else { + if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) { + perror("Cannon send dump request"); + exit(1); + } } if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) { From bcddcddd2993e9c798f3279525fafee228c76b6f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Oct 2017 09:15:23 +0200 Subject: [PATCH 5/5] bridge: checkpatch related cleanups Signed-off-by: Stephen Hemminger --- bridge/fdb.c | 15 ++++++++------- bridge/vlan.c | 21 +++++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/bridge/fdb.c b/bridge/fdb.c index e5cebf9b..c2f654c4 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -35,11 +35,12 @@ json_writer_t *jw_global; static void usage(void) { - fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n" - " [ self ] [ master ] [ use ] [ router ]\n" - " [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n" - " [ port PORT] [ vni VNI ] [ via DEV ]\n"); - fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n"); + fprintf(stderr, + "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n" + " [ self ] [ master ] [ use ] [ router ]\n" + " [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n" + " [ port PORT] [ vni VNI ] [ via DEV ]\n" + " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n"); exit(-1); } @@ -479,9 +480,9 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) } else if (matches(*argv, "use") == 0) { req.ndm.ndm_flags |= NTF_USE; } else { - if (strcmp(*argv, "to") == 0) { + if (strcmp(*argv, "to") == 0) NEXT_ARG(); - } + if (matches(*argv, "help") == 0) usage(); if (addr) diff --git a/bridge/vlan.c b/bridge/vlan.c index fc361ae4..ccd14bf4 100644 --- a/bridge/vlan.c +++ b/bridge/vlan.c @@ -17,13 +17,14 @@ static unsigned int filter_index, filter_vlan; static int last_ifidx = -1; -json_writer_t *jw_global = NULL; +json_writer_t *jw_global; static void usage(void) { - fprintf(stderr, "Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid ] [ untagged ]\n"); - fprintf(stderr, " [ self ] [ master ]\n"); - fprintf(stderr, " bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n"); + fprintf(stderr, + "Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid ] [ untagged ]\n" + " [ self ] [ master ]\n" + " bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n"); exit(-1); } @@ -73,9 +74,8 @@ static int vlan_modify(int cmd, int argc, char **argv) } else if (strcmp(*argv, "untagged") == 0) { vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; } else { - if (matches(*argv, "help") == 0) { + if (matches(*argv, "help") == 0) NEXT_ARG(); - } } argc--; argv++; } @@ -216,9 +216,9 @@ static int print_vlan(const struct sockaddr_nl *who, fprintf(fp, "%s\tNone\n", ll_index_to_name(ifm->ifi_index)); return 0; - } else { - print_vlan_info(fp, tb[IFLA_AF_SPEC], ifm->ifi_index); } + + print_vlan_info(fp, tb[IFLA_AF_SPEC], ifm->ifi_index); if (!filter_vlan) { if (jw_global) jsonw_end_array(jw_global); @@ -332,9 +332,10 @@ static int vlan_show(int argc, char **argv) } if (filter_dev) { - if ((filter_index = if_nametoindex(filter_dev)) == 0) { + filter_index = if_nametoindex(filter_dev); + if (filter_index == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", - filter_dev); + filter_dev); return -1; } }