slirp: improve send_packet() callback
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>
This commit is contained in:
parent
d7df0b41dc
commit
625a526b32
|
@ -146,7 +146,7 @@ ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
|
||||||
int iovcnt);
|
int iovcnt);
|
||||||
ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
|
ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
|
||||||
int iovcnt, NetPacketSent *sent_cb);
|
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_raw(NetClientState *nc, const uint8_t *buf, int size);
|
||||||
ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
|
ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
|
||||||
int size, NetPacketSent *sent_cb);
|
int size, NetPacketSent *sent_cb);
|
||||||
|
|
|
@ -668,9 +668,9 @@ ssize_t qemu_send_packet_async(NetClientState *sender,
|
||||||
buf, size, sent_cb);
|
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)
|
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
|
||||||
|
|
|
@ -108,11 +108,12 @@ static void slirp_smb_cleanup(SlirpState *s);
|
||||||
static inline void slirp_smb_cleanup(SlirpState *s) { }
|
static inline void slirp_smb_cleanup(SlirpState *s) { }
|
||||||
#endif
|
#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;
|
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)
|
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 = {
|
static const SlirpCb slirp_cb = {
|
||||||
.output = net_slirp_output,
|
.send_packet = net_slirp_send_packet,
|
||||||
.guest_error = net_slirp_guest_error,
|
.guest_error = net_slirp_guest_error,
|
||||||
.clock_get_ns = net_slirp_clock_get_ns,
|
.clock_get_ns = net_slirp_clock_get_ns,
|
||||||
.timer_new = net_slirp_timer_new,
|
.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);
|
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);
|
return qemu_chr_fe_write_all(chr, buf, len);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
typedef struct Slirp Slirp;
|
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);
|
typedef void (*SlirpTimerCb)(void *opaque);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,10 +23,13 @@ typedef void (*SlirpTimerCb)(void *opaque);
|
||||||
*/
|
*/
|
||||||
typedef struct SlirpCb {
|
typedef struct SlirpCb {
|
||||||
/*
|
/*
|
||||||
* Send an ethernet frame to the guest network. The opaque parameter
|
* Send an ethernet frame to the guest network. The opaque
|
||||||
* is the one given to slirp_init().
|
* 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. */
|
/* Print a message for an error due to guest misbehavior. */
|
||||||
void (*guest_error)(const char *msg);
|
void (*guest_error)(const char *msg);
|
||||||
/* Return the virtual clock value in nanoseconds */
|
/* Return the virtual clock value in nanoseconds */
|
||||||
|
|
|
@ -162,5 +162,5 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||||
*pchecksum = htonl(checksum);
|
*pchecksum = htonl(checksum);
|
||||||
ncsi_rsp_len += 4;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -800,7 +800,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||||
rah->ar_sip = ah->ar_tip;
|
rah->ar_sip = ah->ar_tip;
|
||||||
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
|
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
|
||||||
rah->ar_tip = ah->ar_sip;
|
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;
|
break;
|
||||||
case ARPOP_REPLY:
|
case ARPOP_REPLY:
|
||||||
|
@ -900,7 +900,7 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
|
||||||
/* target IP */
|
/* target IP */
|
||||||
rah->ar_tip = iph->ip_dst.s_addr;
|
rah->ar_tip = iph->ip_dst.s_addr;
|
||||||
slirp->client_ipaddr = iph->ip_dst;
|
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;
|
ifm->resolution_requested = true;
|
||||||
|
|
||||||
/* Expire request and drop outgoing packet after 1 second */
|
/* 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[0], eh->h_dest[1], eh->h_dest[2],
|
||||||
eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
|
eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
|
||||||
memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,3 +1152,15 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
tcp_output(sototcpcb(so));
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -269,4 +269,6 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
||||||
struct socket *
|
struct socket *
|
||||||
slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue