#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,
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)
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
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
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
udpstats();
icmpstats();
mbufstats();
- sockstats();
#else
lprint("SLIRP statistics code not compiled.\n");
#endif
extern "C" {
#endif
+#include <qemu-common.h>
+
void slirp_init(int restricted, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost,
const char *vhostname, const char *tftp_path,
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);
*/
#include <slirp.h>
+#include <libslirp.h>
+
+#include "monitor.h"
u_int curtime, time_fasttimo, last_slowtimo;
}
}
#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);
+ }
+}
extern tcp_seq tcp_iss; /* tcp initial send seq # */
-extern const char * const tcpstates[];
-
#endif
#include <slirp.h>
-/*
- * 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,