Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2017-10-27 09:27:43 +02:00
commit 106753c937
5 changed files with 295 additions and 93 deletions

View File

@ -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);

View File

@ -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)

View File

@ -216,6 +216,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");
@ -467,9 +474,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) {

View File

@ -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++;
}
@ -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",
@ -217,77 +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 {
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)
jsonw_end_array(jw_global);
@ -401,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;
}
}
@ -470,6 +402,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);

View File

@ -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:(<timer_name>,<expire_time>,<retrans>)
.P
.TP
.B <timer_name>
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 <expire_time>
how long time the timer will expire
.P
.TP
.B <retrans>
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:<uid_number> ino:<inode_number> sk:<cookie>
.P
.TP
.B <uid_number>
the user id the socket belongs to
.P
.TP
.B <inode_number>
the socket's inode number in VFS
.P
.TP
.B <cookie>
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<rmem_alloc>,rb<rcv_buf>,t<wmem_alloc>,tb<snd_buf>,f<fwd_alloc>,w<wmem_queued>,o<opt_mem>,bl<back_log>)
.P
.TP
.B <rmem_alloc>
the memory allocated for receiving packet
.P
.TP
.B <rcv_buf>
the total memory can be allocated for receiving packet
.P
.TP
.B <wmem_alloc>
the memory used for sending packet (which has been sent to layer 3)
.P
.TP
.B <snd_buf>
the total memory can be allocated for sending packet
.P
.TP
.B <fwd_alloc>
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 <wmem_queued>
The memory allocated for sending packet (which has not been sent to layer 3)
.P
.TP
.B <opt_mem>
The memory used for storing socket option, e.g., the key for TCP MD5 signature
.P
.TP
.B <back_log>
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:<snd_wscale>:<rcv_wscale>
if window scale option is used, this field shows the send scale factory and receive scale factory
.P
.TP
.B rto:<icsk_rto>
tcp re-transmission timeout value, the unit is millisecond
.P
.TP
.B backoff:<icsk_backoff>
used for exponential backoff re-transmission, the actual re-transmission timeout value is icsk_rto << icsk_backoff
.P
.TP
.B rtt:<rtt>/<rttvar>
rtt is the average round trip time, rttvar is the mean deviation of rtt, their units are millisecond
.P
.TP
.B ato:<ato>
ack timeout, unit is millisecond, used for delay ack mode
.P
.TP
.B mss:<mss>
max segment size
.P
.TP
.B cwnd:<cwnd>
congestion window size
.P
.TP
.B ssthresh:<ssthresh>
tcp congestion window slow start threshold
.P
.TP
.B bytes_acked:<bytes_acked>
bytes acked
.P
.TP
.B bytes_received:<bytes_received>
bytes received
.P
.TP
.B segs_out:<segs_out>
segments sent out
.P
.TP
.B segs_in:<segs_in>
segments received
.P
.TP
.B send <send_bps>bps
egress bps
.P
.TP
.B lastsnd:<lastsnd>
how long time since the last packet sent, the unit is millisecond
.P
.TP
.B lastrcv:<lastrcv>
how long time since the last packet received, the unit is millisecond
.P
.TP
.B lastack:<lastack>
how long time since the last ack received, the unit is millisecond
.P
.TP
.B pacing_rate <pacing_rate>bps/<max_pacing_rate>bps
the pacing rate and max pacing rate
.P
.TP
.B rcv_space:<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