]> git.proxmox.com Git - mirror_qemu.git/commitdiff
slirp: improve send_packet() callback
authorMarc-André Lureau <marcandre.lureau@redhat.com>
Thu, 17 Jan 2019 11:43:54 +0000 (15:43 +0400)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Thu, 7 Feb 2019 13:49:08 +0000 (15:49 +0200)
Use a more descriptive name for the callback.

Reuse the SlirpWriteCb type. Wrap it to check that all data has been written.

Return a ssize_t for potential error handling and data-loss reporting.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
include/net/net.h
net/net.c
net/slirp.c
slirp/libslirp.h
slirp/ncsi.c
slirp/slirp.c
slirp/slirp.h

index 643295d1637f3b854c74c42c339596038a14d801..075cc0126719790864b322067ed65740989386bd 100644 (file)
@@ -146,7 +146,7 @@ ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
                           int iovcnt);
 ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
                                 int iovcnt, NetPacketSent *sent_cb);
-void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
+ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
 ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
 ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
                                int size, NetPacketSent *sent_cb);
index 3acbdccd61b91cace1271f1fbaa7c8e1552c66d8..5dcff7fe2ab7767f773f803cd8f10deb19e26365 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -668,9 +668,9 @@ ssize_t qemu_send_packet_async(NetClientState *sender,
                                              buf, size, sent_cb);
 }
 
-void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
+ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
 {
-    qemu_send_packet_async(nc, buf, size, NULL);
+    return qemu_send_packet_async(nc, buf, size, NULL);
 }
 
 ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
index 7b4f9f5c5ee31c3208d4e8d8b8362fb8c1264555..664ff1c0022b4845e5ed720d21cb4276bdbd8f20 100644 (file)
@@ -108,11 +108,12 @@ static void slirp_smb_cleanup(SlirpState *s);
 static inline void slirp_smb_cleanup(SlirpState *s) { }
 #endif
 
-static void net_slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
+static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
+                                     void *opaque)
 {
     SlirpState *s = opaque;
 
-    qemu_send_packet(&s->nc, pkt, pkt_len);
+    return qemu_send_packet(&s->nc, pkt, pkt_len);
 }
 
 static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
@@ -197,7 +198,7 @@ static void net_slirp_unregister_poll_fd(int fd)
 }
 
 static const SlirpCb slirp_cb = {
-    .output = net_slirp_output,
+    .send_packet = net_slirp_send_packet,
     .guest_error = net_slirp_guest_error,
     .clock_get_ns = net_slirp_clock_get_ns,
     .timer_new = net_slirp_timer_new,
@@ -780,7 +781,7 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
     slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
 }
 
-static int guestfwd_write(const void *buf, size_t len, void *chr)
+static ssize_t guestfwd_write(const void *buf, size_t len, void *chr)
 {
     return qemu_chr_fe_write_all(chr, buf, len);
 }
index 02cbec9f8beacf5c3b095ec0e828ab8c10fbf093..8e5d4ed11b5e7a0f59fad76f6fd95c752a95ca2d 100644 (file)
@@ -15,7 +15,7 @@
 
 typedef struct Slirp Slirp;
 
-typedef int (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
+typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
 typedef void (*SlirpTimerCb)(void *opaque);
 
 /*
@@ -23,10 +23,13 @@ typedef void (*SlirpTimerCb)(void *opaque);
  */
 typedef struct SlirpCb {
     /*
-     * Send an ethernet frame to the guest network. The opaque parameter
-     * is the one given to slirp_init().
+     * Send an ethernet frame to the guest network. The opaque
+     * parameter is the one given to slirp_init(). The function
+     * doesn't need to send all the data and may return <len (no
+     * buffering is done on libslirp side, so the data will be dropped
+     * in this case). <0 reports an IO error.
      */
-    void (*output)(void *opaque, const uint8_t *pkt, int pkt_len);
+    SlirpWriteCb send_packet;
     /* Print a message for an error due to guest misbehavior.  */
     void (*guest_error)(const char *msg);
     /* Return the virtual clock value in nanoseconds */
index 327f17543ce0e8c091169d05d84cda6573b55ec2..359f52c284042237e437c441264b7ecfe0d0b32e 100644 (file)
@@ -162,5 +162,5 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     *pchecksum = htonl(checksum);
     ncsi_rsp_len += 4;
 
-    slirp->cb->output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
+    slirp_send_packet_all(slirp, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
 }
index 3304c83001160d27ee59978579c29b063a421014..2bc53e3e127eef0bd4f78dceaf90e29e1402d593 100644 (file)
@@ -800,7 +800,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
             rah->ar_sip = ah->ar_tip;
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
             rah->ar_tip = ah->ar_sip;
-            slirp->cb->output(slirp->opaque, arp_reply, sizeof(arp_reply));
+            slirp_send_packet_all(slirp, arp_reply, sizeof(arp_reply));
         }
         break;
     case ARPOP_REPLY:
@@ -900,7 +900,7 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
             /* target IP */
             rah->ar_tip = iph->ip_dst.s_addr;
             slirp->client_ipaddr = iph->ip_dst;
-            slirp->cb->output(slirp->opaque, arp_req, sizeof(arp_req));
+            slirp_send_packet_all(slirp, arp_req, sizeof(arp_req));
             ifm->resolution_requested = true;
 
             /* Expire request and drop outgoing packet after 1 second */
@@ -985,7 +985,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
               eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
               eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
     memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
-    slirp->cb->output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+    slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
     return 1;
 }
 
@@ -1152,3 +1152,15 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
     if (ret > 0)
         tcp_output(sototcpcb(so));
 }
+
+void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len)
+{
+    ssize_t ret = slirp->cb->send_packet(buf, len, slirp->opaque);
+
+    if (ret < 0) {
+        g_critical("Failed to send packet, ret: %ld", (long) ret);
+    } else if (ret < len) {
+        DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu",
+                (long) ret, (unsigned long) len);
+    }
+}
index 05b8364c07c23883778dd8ec4398e268f4f61520..752a4cd8c81c687bfb45269637a21f7123f56a57 100644 (file)
@@ -269,4 +269,6 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
 struct socket *
 slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port);
 
+void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len);
+
 #endif