qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/2] slirp: Add query-usernet QMP command
@ 2018-05-02  7:30 Fam Zheng
  2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" " Fam Zheng
  2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 2/2] tests: Use query-usernet instead of 'info usernet' Fam Zheng
  0 siblings, 2 replies; 5+ messages in thread
From: Fam Zheng @ 2018-05-02  7:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: Samuel Thibault, Fam Zheng, Jason Wang, Eric Blake,
	Philippe Mathieu-Daudé, Markus Armbruster, Jan Kiszka,
	Alex Bennée

v4: vlan -> hub. [Samuel]
    Free 'info. [Samuel]

v3: - Add Eric's rev-by to patch 2.
    - Address Eric's comments on patch 1:
      * Fix spell/grammar: "programmed", "awaiting".
      * Fix include "qapi/qapi-commands-net.h".
      * Underscores to dashes.
      * "Since 2.13" now.

v2: Fix compiler error. [patchew]

The command is a counterpart of HMP "info usernet" and is at least very useful
for the VM tests. So add it.

Fam Zheng (2):
  slirp: Add "query-usernet" QMP command
  tests: Use query-usernet instead of 'info usernet'

 net/slirp.c        |  26 +++++++
 qapi/net.json      | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/libslirp.h   |   2 +
 slirp/misc.c       | 158 +++++++++++++++++++++++++++++------------
 slirp/tcp.h        |  15 ----
 tests/vm/basevm.py |  14 ++--
 6 files changed, 349 insertions(+), 67 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" QMP command
  2018-05-02  7:30 [Qemu-devel] [PATCH v4 0/2] slirp: Add query-usernet QMP command Fam Zheng
@ 2018-05-02  7:30 ` Fam Zheng
  2018-05-02 19:41   ` Eric Blake
  2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 2/2] tests: Use query-usernet instead of 'info usernet' Fam Zheng
  1 sibling, 1 reply; 5+ messages in thread
From: Fam Zheng @ 2018-05-02  7:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: Samuel Thibault, Fam Zheng, Jason Wang, Eric Blake,
	Philippe Mathieu-Daudé, Markus Armbruster, Jan Kiszka,
	Alex Bennée

HMP "info usernet" has been available but it isn't ideal for programmed
use cases. This closes the gap in QMP by adding a counterpart
"query-usernet" command. It is basically translated from
the HMP slirp_connection_info() loop, which now calls the QMP
implementation and prints the data, just like other HMP info_* commands.

The TCPS_* macros are now defined as a QAPI enum.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 net/slirp.c      |  26 +++++++
 qapi/net.json    | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/libslirp.h |   2 +
 slirp/misc.c     | 158 ++++++++++++++++++++++++++++++-------------
 slirp/tcp.h      |  15 -----
 5 files changed, 342 insertions(+), 60 deletions(-)

diff --git a/net/slirp.c b/net/slirp.c
index 8991816bbf..9c48a882ec 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -36,6 +36,7 @@
 #include "monitor/monitor.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
+#include "slirp/slirp.h"
 #include "slirp/libslirp.h"
 #include "slirp/ip6.h"
 #include "chardev/char-fe.h"
@@ -43,6 +44,7 @@
 #include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
+#include "qapi/qapi-commands-net.h"
 
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 {
@@ -864,6 +866,30 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
     return -1;
 }
 
+UsernetInfoList *qmp_query_usernet(Error **errp)
+{
+    SlirpState *s;
+    UsernetInfoList *list = NULL;
+    UsernetInfoList **p = &list;
+
+    QTAILQ_FOREACH(s, &slirp_stacks, entry) {
+        int hub;
+        UsernetInfoList *il = g_new0(UsernetInfoList, 1);
+        UsernetInfo *info = il->value = g_new0(UsernetInfo, 1);
+
+        info->id = g_strdup(s->nc.name);
+        if (!net_hub_id_for_client(&s->nc, &hub)) {
+            info->hub = hub;
+        } else {
+            info->hub = -1;
+        }
+        usernet_get_info(s->slirp, info);
+        *p = il;
+        p = &il->next;
+    }
+    return list;
+}
+
 void hmp_info_usernet(Monitor *mon, const QDict *qdict)
 {
     SlirpState *s;
diff --git a/qapi/net.json b/qapi/net.json
index 9117c56972..414805ba1a 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -689,3 +689,204 @@
 ##
 { 'event': 'NIC_RX_FILTER_CHANGED',
   'data': { '*name': 'str', 'path': 'str' } }
+
+##
+# @TCPS:
+#
+# TCP States of a SLIRP connection.
+#
+# - States where connections are not established: none, closed, listen, syn-sent,
+#   syn-received
+#
+# - States where user has closed: fin-wait-1, closing, last-ack, fin-wait-2,
+#   time-wait
+#
+# - States awaiting ACK of FIN: fin-wait-1, closing, last-ack
+#
+# 'none' state is used only when host forwarding
+#
+# Since 2.13
+#
+##
+{ 'enum': 'TCPS',
+  'data':
+   ['closed',
+    'listen',
+    'syn-sent',
+    'syn-received',
+    'established',
+    'close-wait',
+    'fin-wait-1',
+    'closing',
+    'last-ack',
+    'fin-wait-2',
+    'time-wait',
+    'none'
+   ] }
+
+##
+# @UsernetTCPConnection:
+#
+# SLIRP TCP information.
+#
+# @state: tcp connection state
+#
+# @hostfwd: whether this connection has host port forwarding
+#
+# @fd: the file descriptor of the connection
+#
+# @src-addr: source address of host port forwarding
+#
+# @src-port: source port of host port forwarding
+#
+# @dest-addr: destination address of host port forwarding
+#
+# @dest-port: destination port of host port forwarding
+#
+# @recv-buffered: number of bytes queued in the receive buffer
+#
+# @send-buffered: number of bytes queued in the send buffer
+#
+# Since: 2.13
+##
+{ 'struct': 'UsernetTCPConnection',
+  'data': {
+    'state': 'TCPS',
+    'hostfwd': 'bool',
+    'fd': 'int',
+    'src-addr': 'str',
+    'src-port': 'int',
+    'dest-addr': 'str',
+    'dest-port': 'int',
+    'recv-buffered': 'int',
+    'send-buffered': 'int'
+  } }
+
+##
+# @UsernetUDPConnection:
+#
+# SLIRP UDP information.
+#
+# @hostfwd: whether this connection has host port forwarding
+#
+# @expire-time-ms: time in microseconds after which this connection will expire
+#
+# @fd: the file descriptor of the connection
+#
+# @src-addr: source address of host port forwarding
+#
+# @src-port: source port of host port forwarding
+#
+# @dest-addr: destination address of host port forwarding
+#
+# @dest-port: destination port of host port forwarding
+#
+# @recv-buffered: number of bytes queued in the receive buffer
+#
+# @send-buffered: number of bytes queued in the send buffer
+#
+# Since: 2.13
+##
+{ 'struct': 'UsernetUDPConnection',
+  'data': {
+    'hostfwd': 'bool',
+    'expire-time-ms': 'int',
+    'fd': 'int',
+    'src-addr': 'str',
+    'src-port': 'int',
+    'dest-addr': 'str',
+    'dest-port': 'int',
+    'recv-buffered': 'int',
+    'send-buffered': 'int'
+    } }
+
+##
+# @UsernetICMPConnection:
+#
+# SLIRP ICMP information.
+#
+# @expire-time-ms: time in microseconds after which this connection will expire
+#
+# @fd: the file descriptor of the connection
+#
+# @src-addr: source address of host port forwarding
+#
+# @dest-addr: destination address of host port forwarding
+#
+# @recv-buffered: number of bytes queued in the receive buffer
+#
+# @send-buffered: number of bytes queued in the send buffer
+#
+# Since: 2.13
+##
+{ 'struct': 'UsernetICMPConnection',
+  'data': {
+    'expire-time-ms': 'int',
+    'fd': 'int',
+    'src-addr': 'str',
+    'dest-addr': 'str',
+    'recv-buffered': 'int',
+    'send-buffered': 'int'
+    } }
+
+##
+# @UsernetType:
+#
+# Available netdev drivers.
+#
+# Since: 2.13
+##
+{ 'enum': 'UsernetType',
+  'data': [ 'tcp', 'udp', 'icmp' ] }
+
+##
+# @UsernetConnection:
+#
+# SLIRP usernet connection information.
+#
+# Since: 2.13
+##
+{ 'union': 'UsernetConnection',
+  'discriminator': 'type',
+  'base': { 'type': 'UsernetType' },
+  'data': {
+    'tcp':     'UsernetTCPConnection',
+    'udp':     'UsernetUDPConnection',
+    'icmp':    'UsernetICMPConnection'
+    } }
+
+##
+# @UsernetInfo:
+#
+# SLIRP usernet information.
+#
+# Since: 2.13
+##
+{ 'struct': 'UsernetInfo',
+  'data': {
+    'id':              'str',
+    'hub':             'int',
+    'connections':     ['UsernetConnection']
+} }
+
+##
+# @query-usernet:
+#
+# Return SLIRP network information.
+#
+# Since: 2.13
+#
+# Example:
+#
+# -> { "execute": "query-usernet", "arguments": { } }
+# <- { "return": [
+#         {
+#             "promiscuous": true,
+#             "name": "vnet0"
+#         }
+#       ]
+#    }
+#
+##
+{ 'command': 'query-usernet',
+  'returns': ['UsernetInfo'] }
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 540b3e5903..3ba361ea41 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -2,6 +2,7 @@
 #define LIBSLIRP_H
 
 #include "qemu-common.h"
+#include "qapi/qapi-commands-net.h"
 
 typedef struct Slirp Slirp;
 
@@ -37,6 +38,7 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
                    struct in_addr *guest_addr, int guest_port);
 
 void slirp_connection_info(Slirp *slirp, Monitor *mon);
+void usernet_get_info(Slirp *slirp, UsernetInfo *info);
 
 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
                        int guest_port, const uint8_t *buf, int size);
diff --git a/slirp/misc.c b/slirp/misc.c
index 260187b6b6..335b49aad8 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -205,39 +205,28 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 }
 #endif
 
-void slirp_connection_info(Slirp *slirp, Monitor *mon)
+void usernet_get_info(Slirp *slirp, UsernetInfo *info)
 {
-    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];
-
-    monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
-                        "Dest. Address  Port RecvQ SendQ\n");
+    UsernetConnectionList **p_next = &info->connections;
 
     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
+        UsernetConnection *conn = g_new0(UsernetConnection, 1);
+        UsernetTCPConnection *tcp = &conn->u.tcp;
+        UsernetConnectionList *list = g_new0(UsernetConnectionList, 1);
+
+        list->value = conn;
         if (so->so_state & SS_HOSTFWD) {
-            state = "HOST_FORWARD";
+            tcp->hostfwd = true;
+            tcp->state = so->so_tcpcb->t_state;
         } else if (so->so_tcpcb) {
-            state = tcpstates[so->so_tcpcb->t_state];
+            tcp->state = so->so_tcpcb->t_state;
         } else {
-            state = "NONE";
+            tcp->state = TCPS_NONE;
         }
         if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
             src_len = sizeof(src);
@@ -250,46 +239,125 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
             dst_addr = so->so_faddr;
             dst_port = so->so_fport;
         }
-        snprintf(buf, sizeof(buf), "  TCP[%s]", state);
-        monitor_printf(mon, "%-19s %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);
+        tcp->fd = so->s;
+        tcp->src_addr =
+            g_strdup(src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
+        tcp->src_port = ntohs(src.sin_port);
+        tcp->dest_addr = g_strdup(inet_ntoa(dst_addr));
+        tcp->dest_port = ntohs(dst_port);
+        tcp->recv_buffered = so->so_rcv.sb_cc;
+        tcp->send_buffered = so->so_snd.sb_cc;
+        *p_next = list;
+        p_next = &list->next;
     }
-
     for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
+        UsernetConnection *conn = g_new0(UsernetConnection, 1);
+        UsernetUDPConnection *udp = &conn->u.udp;
+        UsernetConnectionList *list = g_new0(UsernetConnectionList, 1);
+
+        list->value = conn;
         if (so->so_state & SS_HOSTFWD) {
-            snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
+            udp->hostfwd = true;
             src_len = sizeof(src);
             getsockname(so->s, (struct sockaddr *)&src, &src_len);
             dst_addr = so->so_laddr;
             dst_port = so->so_lport;
         } else {
-            snprintf(buf, sizeof(buf), "  UDP[%d sec]",
-                         (so->so_expire - curtime) / 1000);
+            udp->expire_time_ms = so->so_expire - curtime;
             src.sin_addr = so->so_laddr;
             src.sin_port = so->so_lport;
             dst_addr = so->so_faddr;
             dst_port = so->so_fport;
         }
-        monitor_printf(mon, "%-19s %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);
+        udp->fd = so->s;
+        udp->src_addr =
+            g_strdup(src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
+        udp->src_port = ntohs(src.sin_port);
+        udp->dest_addr = g_strdup(inet_ntoa(dst_addr));
+        udp->dest_port = ntohs(dst_port);
+        udp->recv_buffered = so->so_rcv.sb_cc;
+        udp->send_buffered = so->so_snd.sb_cc;
+        *p_next = list;
+        p_next = &list->next;
     }
 
     for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) {
-        snprintf(buf, sizeof(buf), "  ICMP[%d sec]",
-                     (so->so_expire - curtime) / 1000);
+        UsernetConnection *conn = g_new0(UsernetConnection, 1);
+        UsernetICMPConnection *icmp = &conn->u.icmp;
+        UsernetConnectionList *list = g_new0(UsernetConnectionList, 1);
+
+        icmp->expire_time_ms = so->so_expire - curtime;
         src.sin_addr = so->so_laddr;
         dst_addr = so->so_faddr;
-        monitor_printf(mon, "%-19s %3d %15s  -    ", buf, so->s,
-                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
-        monitor_printf(mon, "%15s  -    %5d %5d\n", inet_ntoa(dst_addr),
-                       so->so_rcv.sb_cc, so->so_snd.sb_cc);
+        icmp->fd = so->s;
+        icmp->src_addr =
+            g_strdup(src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
+        icmp->dest_addr = g_strdup(inet_ntoa(dst_addr));
+        icmp->recv_buffered = so->so_rcv.sb_cc;
+        icmp->send_buffered = so->so_snd.sb_cc;
+        *p_next = list;
+        p_next = &list->next;
     }
 }
+
+
+void slirp_connection_info(Slirp *slirp, Monitor *mon)
+{
+    const char *state;
+    char buf[64];
+    UsernetInfo *info = g_new0(UsernetInfo, 1);
+    UsernetConnectionList *cl;
+
+    monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
+                        "Dest. Address  Port RecvQ SendQ\n");
+
+    usernet_get_info(slirp, info);
+    for (cl = info->connections; cl && cl->value; cl = cl->next) {
+        UsernetConnection *conn = cl->value;
+
+        if (conn->type == USERNET_TYPE_TCP) {
+            UsernetTCPConnection *tcp = &conn->u.tcp;
+
+            if (tcp->hostfwd) {
+                state = "HOST_FORWARD";
+            } else {
+                state = TCPS_str(tcp->state);
+            }
+            snprintf(buf, sizeof(buf), "  TCP[%s]", state);
+            monitor_printf(mon, "%-19s %3" PRId64 " %15s %5" PRId64 " ",
+                           buf, tcp->fd,
+                           tcp->src_addr, tcp->src_port);
+            monitor_printf(mon, "%15s %5" PRId64 " %5" PRId64 " %5" PRId64 "\n",
+                           tcp->dest_addr, tcp->dest_port,
+                           tcp->recv_buffered, tcp->send_buffered);
+        } else if (conn->type == USERNET_TYPE_UDP) {
+            UsernetUDPConnection *udp = &conn->u.udp;
+
+            if (udp->hostfwd) {
+                snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
+            } else {
+                snprintf(buf, sizeof(buf), "  UDP[%" PRId64 " sec]",
+                         udp->expire_time_ms / 1000);
+            }
+            monitor_printf(mon, "%-19s %3" PRId64 " %15s %5" PRId64 " ",
+                           buf, udp->fd,
+                           udp->src_addr, udp->src_port);
+            monitor_printf(mon, "%15s %5" PRId64 " %5" PRId64 " %5" PRId64 "\n",
+                           udp->dest_addr, udp->dest_port,
+                           udp->recv_buffered, udp->send_buffered);
+        } else {
+            UsernetICMPConnection *icmp = &conn->u.icmp;
+
+            assert(conn->type == USERNET_TYPE_ICMP);
+            snprintf(buf, sizeof(buf), "  ICMP[%" PRId64 " sec]",
+                     icmp->expire_time_ms / 1000);
+            monitor_printf(mon, "%-19s %3" PRId64 " %15s  -    ", buf, icmp->fd,
+                           icmp->src_addr);
+            monitor_printf(mon, "%15s  -    %5" PRId64 " %5" PRId64 "\n",
+                           icmp->dest_addr,
+                           icmp->recv_buffered, icmp->send_buffered);
+        }
+    }
+
+    qapi_free_UsernetInfo(info);
+}
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 174d3d960c..155569f380 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -133,21 +133,6 @@ struct tcphdr {
 
 #define TCP_NSTATES     11
 
-#define TCPS_CLOSED             0       /* closed */
-#define TCPS_LISTEN             1       /* listening for connection */
-#define TCPS_SYN_SENT           2       /* active, have sent syn */
-#define TCPS_SYN_RECEIVED       3       /* have send and received syn */
-/* states < TCPS_ESTABLISHED are those where connections not established */
-#define TCPS_ESTABLISHED        4       /* established */
-#define TCPS_CLOSE_WAIT         5       /* rcvd fin, waiting for close */
-/* states > TCPS_CLOSE_WAIT are those where user has closed */
-#define TCPS_FIN_WAIT_1         6       /* have closed, sent fin */
-#define TCPS_CLOSING            7       /* closed xchd FIN; await FIN ACK */
-#define TCPS_LAST_ACK           8       /* had fin and close; await FIN ACK */
-/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */
-#define TCPS_FIN_WAIT_2         9       /* have closed, fin is acked */
-#define TCPS_TIME_WAIT          10      /* in 2*msl quiet wait after close */
-
 #define TCPS_HAVERCVDSYN(s)     ((s) >= TCPS_SYN_RECEIVED)
 #define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED)
 #define TCPS_HAVERCVDFIN(s)     ((s) >= TCPS_TIME_WAIT)
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v4 2/2] tests: Use query-usernet instead of 'info usernet'
  2018-05-02  7:30 [Qemu-devel] [PATCH v4 0/2] slirp: Add query-usernet QMP command Fam Zheng
  2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" " Fam Zheng
@ 2018-05-02  7:30 ` Fam Zheng
  1 sibling, 0 replies; 5+ messages in thread
From: Fam Zheng @ 2018-05-02  7:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: Samuel Thibault, Fam Zheng, Jason Wang, Eric Blake,
	Philippe Mathieu-Daudé, Markus Armbruster, Jan Kiszka,
	Alex Bennée

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 tests/vm/basevm.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 3a2d508c35..dcfa6597ad 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -101,7 +101,7 @@ class BaseVM(object):
                    "-o", "StrictHostKeyChecking=no",
                    "-o", "UserKnownHostsFile=" + os.devnull,
                    "-o", "ConnectTimeout=1",
-                   "-p", self.ssh_port, "-i", self._ssh_key_file]
+                   "-p", str(self.ssh_port), "-i", self._ssh_key_file]
         if interactive:
             ssh_cmd += ['-t']
         assert not isinstance(cmd, str)
@@ -163,13 +163,13 @@ class BaseVM(object):
             raise
         atexit.register(self.shutdown)
         self._guest = guest
-        usernet_info = guest.qmp("human-monitor-command",
-                                 command_line="info usernet")
+        usernet_info = guest.qmp("query-usernet")
         self.ssh_port = None
-        for l in usernet_info["return"].splitlines():
-            fields = l.split()
-            if "TCP[HOST_FORWARD]" in fields and "22" in fields:
-                self.ssh_port = l.split()[3]
+        for i in usernet_info["return"]:
+            if i.get("id") != "vnet":
+                continue
+            self.ssh_port = i["connections"][0]["src_port"]
+            break
         if not self.ssh_port:
             raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
                             usernet_info)
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" QMP command
  2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" " Fam Zheng
@ 2018-05-02 19:41   ` Eric Blake
  2018-05-03  1:25     ` Fam Zheng
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Blake @ 2018-05-02 19:41 UTC (permalink / raw)
  To: Fam Zheng, qemu-devel
  Cc: Samuel Thibault, Jason Wang, Philippe Mathieu-Daudé,
	Markus Armbruster, Jan Kiszka, Alex Bennée

On 05/02/2018 02:30 AM, Fam Zheng wrote:
> HMP "info usernet" has been available but it isn't ideal for programmed
> use cases. This closes the gap in QMP by adding a counterpart
> "query-usernet" command. It is basically translated from
> the HMP slirp_connection_info() loop, which now calls the QMP
> implementation and prints the data, just like other HMP info_* commands.
> 
> The TCPS_* macros are now defined as a QAPI enum.
> 
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---

> +##
> +# @UsernetInfo:
> +#
> +# SLIRP usernet information.
> +#
> +# Since: 2.13
> +##
> +{ 'struct': 'UsernetInfo',
> +  'data': {
> +    'id':              'str',
> +    'hub':             'int',
> +    'connections':     ['UsernetConnection']
> +} }
> +
> +##
> +# @query-usernet:
> +#
> +# Return SLIRP network information.
> +#
> +# Since: 2.13
> +#
> +# Example:
> +#
> +# -> { "execute": "query-usernet", "arguments": { } }
> +# <- { "return": [
> +#         {
> +#             "promiscuous": true,
> +#             "name": "vnet0"

That example looks wrong; I'm expecting 'id', 'hub', and another array 
'connections'.

> +#         }
> +#       ]
> +#    }
> +#
> +##
> +{ 'command': 'query-usernet',
> +  'returns': ['UsernetInfo'] }

Other than the botched example, the qapi additions look okay to me.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" QMP command
  2018-05-02 19:41   ` Eric Blake
@ 2018-05-03  1:25     ` Fam Zheng
  0 siblings, 0 replies; 5+ messages in thread
From: Fam Zheng @ 2018-05-03  1:25 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Samuel Thibault, Jason Wang,
	Philippe Mathieu-Daudé, Markus Armbruster, Jan Kiszka,
	Alex Bennée

On Wed, 05/02 14:41, Eric Blake wrote:
> On 05/02/2018 02:30 AM, Fam Zheng wrote:
> > HMP "info usernet" has been available but it isn't ideal for programmed
> > use cases. This closes the gap in QMP by adding a counterpart
> > "query-usernet" command. It is basically translated from
> > the HMP slirp_connection_info() loop, which now calls the QMP
> > implementation and prints the data, just like other HMP info_* commands.
> > 
> > The TCPS_* macros are now defined as a QAPI enum.
> > 
> > Signed-off-by: Fam Zheng <famz@redhat.com>
> > ---
> 
> > +##
> > +# @UsernetInfo:
> > +#
> > +# SLIRP usernet information.
> > +#
> > +# Since: 2.13
> > +##
> > +{ 'struct': 'UsernetInfo',
> > +  'data': {
> > +    'id':              'str',
> > +    'hub':             'int',
> > +    'connections':     ['UsernetConnection']
> > +} }
> > +
> > +##
> > +# @query-usernet:
> > +#
> > +# Return SLIRP network information.
> > +#
> > +# Since: 2.13
> > +#
> > +# Example:
> > +#
> > +# -> { "execute": "query-usernet", "arguments": { } }
> > +# <- { "return": [
> > +#         {
> > +#             "promiscuous": true,
> > +#             "name": "vnet0"
> 
> That example looks wrong; I'm expecting 'id', 'hub', and another array
> 'connections'.

Copy-pasto. Will fix.

Fam

> 
> > +#         }
> > +#       ]
> > +#    }
> > +#
> > +##
> > +{ 'command': 'query-usernet',
> > +  'returns': ['UsernetInfo'] }
> 
> Other than the botched example, the qapi additions look okay to me.
> 
> -- 
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-05-03  1:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-02  7:30 [Qemu-devel] [PATCH v4 0/2] slirp: Add query-usernet QMP command Fam Zheng
2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 1/2] slirp: Add "query-usernet" " Fam Zheng
2018-05-02 19:41   ` Eric Blake
2018-05-03  1:25     ` Fam Zheng
2018-05-02  7:30 ` [Qemu-devel] [PATCH v4 2/2] tests: Use query-usernet instead of 'info usernet' Fam Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).