From 6dbe553fe9ffdee008c1bbbe1af2d030e0f04aab Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 24 Jun 2009 14:42:29 +0200 Subject: slirp: Add info usernet for dumping connection states Break out sockstats from the slirp statistics and present them under the new info category "usernet". This patch also improves the current output /wrt proper reporting connection source and destination. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- monitor.c | 2 ++ net.c | 6 ++++ net.h | 2 ++ qemu-monitor.hx | 2 ++ slirp/debug.c | 42 -------------------------- slirp/libslirp.h | 4 +++ slirp/misc.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ slirp/tcp.h | 2 -- slirp/tcp_output.c | 11 ------- 9 files changed, 102 insertions(+), 55 deletions(-) diff --git a/monitor.c b/monitor.c index 6b45f6cca0..47fc9de7f6 100644 --- a/monitor.c +++ b/monitor.c @@ -1735,6 +1735,8 @@ static const mon_cmd_t info_cmds[] = { #if defined(CONFIG_SLIRP) { "slirp", "", do_info_slirp, "", "show SLIRP statistics", }, + { "usernet", "", do_info_usernet, + "", "show user network stack connection states", }, #endif { "migrate", "", do_info_migrate, "", "show migration status" }, { "balloon", "", do_info_balloon, diff --git a/net.c b/net.c index 603e77cae8..fe33b4f88e 100644 --- a/net.c +++ b/net.c @@ -1198,6 +1198,12 @@ static void slirp_guestfwd(Monitor *mon, const char *config_str, config_error(mon, "invalid guest forwarding rule '%s'\n", config_str); } +void do_info_usernet(Monitor *mon) +{ + monitor_printf(mon, "VLAN %d (%s):\n", slirp_vc->vlan->id, slirp_vc->name); + slirp_connection_info(mon); +} + #endif /* CONFIG_SLIRP */ #if !defined(_WIN32) diff --git a/net.h b/net.h index 016db31365..2cc6c13225 100644 --- a/net.h +++ b/net.h @@ -81,6 +81,8 @@ void qemu_handler_true(void *opaque); void do_info_network(Monitor *mon); int do_set_link(Monitor *mon, const char *name, const char *up_or_down); +void do_info_usernet(Monitor *mon); + /* NIC info */ #define MAX_NICS 8 diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 34f699288a..359bdc68cb 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -87,6 +87,8 @@ show the current VM UUID show CPU statistics @item info slirp show SLIRP statistics (if available) +@item info usernet +show user network stack connection states @item info migrate show migration status @item info balloon diff --git a/slirp/debug.c b/slirp/debug.c index bfef580694..ac856ca19b 100644 --- a/slirp/debug.c +++ b/slirp/debug.c @@ -291,47 +291,6 @@ mbufstats(void) lprint(" %6d mbufs on used list\r\n", i); lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); } - -static void -sockstats(void) -{ - char buff[256]; - int n; - struct socket *so; - - lprint(" \r\n"); - - lprint( - "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); - - for (so = tcb.so_next; so != &tcb; so = so->so_next) { - - n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); - while (n < 17) - buff[n++] = ' '; - buff[17] = 0; - lprint("%s %3d %15s %5d ", - buff, so->s, - inet_ntoa(so->so_laddr), ntohs(so->so_lport)); - lprint("%15s %5d %5d %5d\r\n", - inet_ntoa(so->so_faddr), ntohs(so->so_fport), - so->so_rcv.sb_cc, so->so_snd.sb_cc); - } - - for (so = udb.so_next; so != &udb; so = so->so_next) { - - n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); - while (n < 17) - buff[n++] = ' '; - buff[17] = 0; - lprint("%s %3d %15s %5d ", - buff, so->s, - inet_ntoa(so->so_laddr), ntohs(so->so_lport)); - lprint("%15s %5d %5d %5d\r\n", - inet_ntoa(so->so_faddr), ntohs(so->so_fport), - so->so_rcv.sb_cc, so->so_snd.sb_cc); - } -} #endif #ifndef CONFIG_QEMU @@ -386,7 +345,6 @@ slirp_stats(void) udpstats(); icmpstats(); mbufstats(); - sockstats(); #else lprint("SLIRP statistics code not compiled.\n"); #endif diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 9be4425bb6..5c7a8e91e8 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -5,6 +5,8 @@ extern "C" { #endif +#include + void slirp_init(int restricted, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, const char *vhostname, const char *tftp_path, @@ -29,6 +31,8 @@ int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr, int guest_port); void slirp_stats(void); +void slirp_connection_info(Monitor *mon); + void slirp_socket_recv(struct in_addr guest_addr, int guest_port, const uint8_t *buf, int size); size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port); diff --git a/slirp/misc.c b/slirp/misc.c index 069d8b102d..8d03f79551 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -6,6 +6,9 @@ */ #include +#include + +#include "monitor.h" u_int curtime, time_fasttimo, last_slowtimo; @@ -906,3 +909,86 @@ rsh_exec(so,ns, user, host, args) } } #endif + +void slirp_connection_info(Monitor *mon) +{ + const char * const tcpstates[] = { + [TCPS_CLOSED] = "CLOSED", + [TCPS_LISTEN] = "LISTEN", + [TCPS_SYN_SENT] = "SYN_SENT", + [TCPS_SYN_RECEIVED] = "SYN_RCVD", + [TCPS_ESTABLISHED] = "ESTABLISHED", + [TCPS_CLOSE_WAIT] = "CLOSE_WAIT", + [TCPS_FIN_WAIT_1] = "FIN_WAIT_1", + [TCPS_CLOSING] = "CLOSING", + [TCPS_LAST_ACK] = "LAST_ACK", + [TCPS_FIN_WAIT_2] = "FIN_WAIT_2", + [TCPS_TIME_WAIT] = "TIME_WAIT", + }; + struct in_addr dst_addr; + struct sockaddr_in src; + socklen_t src_len; + uint16_t dst_port; + struct socket *so; + const char *state; + char buf[20]; + int n; + + monitor_printf(mon, " Protocol[State] FD Source Address Port " + "Dest. Address Port RecvQ SendQ\n"); + + for (so = tcb.so_next; so != &tcb; so = so->so_next) { + if (so->so_state & SS_HOSTFWD) { + state = "HOST_FORWARD"; + } else if (so->so_tcpcb) { + state = tcpstates[so->so_tcpcb->t_state]; + } else { + state = "NONE"; + } + if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) { + src_len = sizeof(src); + getsockname(so->s, (struct sockaddr *)&src, &src_len); + dst_addr = so->so_laddr; + dst_port = so->so_lport; + } else { + src.sin_addr = so->so_laddr; + src.sin_port = so->so_lport; + dst_addr = so->so_faddr; + dst_port = so->so_fport; + } + n = snprintf(buf, sizeof(buf), " TCP[%s]", state); + memset(&buf[n], ' ', 19 - n); + buf[19] = 0; + monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s, + src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*", + ntohs(src.sin_port)); + monitor_printf(mon, "%15s %5d %5d %5d\n", + inet_ntoa(dst_addr), ntohs(dst_port), + so->so_rcv.sb_cc, so->so_snd.sb_cc); + } + + for (so = udb.so_next; so != &udb; so = so->so_next) { + if (so->so_state & SS_HOSTFWD) { + n = snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]"); + src_len = sizeof(src); + getsockname(so->s, (struct sockaddr *)&src, &src_len); + dst_addr = so->so_laddr; + dst_port = so->so_lport; + } else { + n = snprintf(buf, sizeof(buf), " UDP[%d sec]", + (so->so_expire - curtime) / 1000); + src.sin_addr = so->so_laddr; + src.sin_port = so->so_lport; + dst_addr = so->so_faddr; + dst_port = so->so_fport; + } + memset(&buf[n], ' ', 19 - n); + buf[19] = 0; + monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s, + src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*", + ntohs(src.sin_port)); + monitor_printf(mon, "%15s %5d %5d %5d\n", + inet_ntoa(dst_addr), ntohs(dst_port), + so->so_rcv.sb_cc, so->so_snd.sb_cc); + } +} diff --git a/slirp/tcp.h b/slirp/tcp.h index 40570326cb..3399857513 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -166,6 +166,4 @@ struct tcphdr { extern tcp_seq tcp_iss; /* tcp initial send seq # */ -extern const char * const tcpstates[]; - #endif diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c index 9ed50f5002..5daf58e73a 100644 --- a/slirp/tcp_output.c +++ b/slirp/tcp_output.c @@ -40,17 +40,6 @@ #include -/* - * Since this is only used in "stats socket", we give meaning - * names instead of the REAL names - */ -const char * const tcpstates[] = { -/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ - "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", - "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", - "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", -}; - static const u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, -- cgit v1.2.3