In the case where a NIC and backend agree on a packet header format, this API allows injecting packets which lack the agreed upon header.
We need this for sending our gratuitous ARP. Signed-off-by: Mark McLoughlin <mar...@redhat.com> --- net-queue.h | 1 + net.c | 37 +++++++++++++++++++++++++++++-------- net.h | 2 ++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/net-queue.h b/net-queue.h index 343760e..a31958e 100644 --- a/net-queue.h +++ b/net-queue.h @@ -44,6 +44,7 @@ typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender, void *opaque); #define QEMU_NET_PACKET_FLAG_NONE 0 +#define QEMU_NET_PACKET_FLAG_RAW (1<<0) NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, NetPacketDeliverIOV *deliver_iov, diff --git a/net.c b/net.c index 30dc402..50d2f83 100644 --- a/net.c +++ b/net.c @@ -463,7 +463,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender, return size; } - return vc->receive(vc, data, size); + if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) + return vc->receive_raw(vc, data, size); + else + return vc->receive(vc, data, size); } static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, @@ -488,7 +491,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, continue; } - len = vc->receive(vc, buf, size); + if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) + len = vc->receive_raw(vc, buf, size); + else + len = vc->receive(vc, buf, size); ret = (ret >= 0) ? ret : len; } @@ -526,9 +532,10 @@ void qemu_flush_queued_packets(VLANClientState *vc) qemu_net_queue_flush(queue); } -ssize_t qemu_send_packet_async(VLANClientState *sender, - const uint8_t *buf, int size, - NetPacketSent *sent_cb) +static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender, + unsigned flags, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) { NetQueue *queue; @@ -547,9 +554,15 @@ ssize_t qemu_send_packet_async(VLANClientState *sender, queue = sender->vlan->send_queue; } - return qemu_net_queue_send(queue, sender, - QEMU_NET_PACKET_FLAG_NONE, - buf, size, sent_cb); + return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); +} + +ssize_t qemu_send_packet_async(VLANClientState *sender, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) +{ + return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE, + buf, size, sent_cb); } void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) @@ -557,6 +570,12 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) qemu_send_packet_async(vc, buf, size, NULL); } +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size) +{ + return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW, + buf, size, NULL); +} + static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, int iovcnt) { @@ -626,6 +645,8 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender, continue; } + assert(!(flags & QEMU_NET_PACKET_FLAG_RAW)); + if (vc->receive_iov) { len = vc->receive_iov(vc, iov, iovcnt); } else { diff --git a/net.h b/net.h index 5f28860..53d813c 100644 --- a/net.h +++ b/net.h @@ -28,6 +28,7 @@ typedef void (LinkStatusChanged)(VLANClientState *); struct VLANClientState { net_client_type type; NetReceive *receive; + NetReceive *receive_raw; NetReceiveIOV *receive_iov; /* Packets may still be sent if this returns zero. It's used to rate-limit the slirp code. */ @@ -72,6 +73,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb); void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size); ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf, int size, NetPacketSent *sent_cb); void qemu_purge_queued_packets(VLANClientState *vc); -- 1.6.2.5