net: add an API for 'raw' packets

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 <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Mark McLoughlin 2009-10-22 17:43:41 +01:00 committed by Anthony Liguori
parent c0b8e49c69
commit ca77d17591
3 changed files with 32 additions and 8 deletions

View file

@ -44,6 +44,7 @@ typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender,
void *opaque); void *opaque);
#define QEMU_NET_PACKET_FLAG_NONE 0 #define QEMU_NET_PACKET_FLAG_NONE 0
#define QEMU_NET_PACKET_FLAG_RAW (1<<0)
NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver,
NetPacketDeliverIOV *deliver_iov, NetPacketDeliverIOV *deliver_iov,

37
net.c
View file

@ -478,7 +478,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender,
return size; 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, static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
@ -503,7 +506,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
continue; 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; ret = (ret >= 0) ? ret : len;
} }
@ -541,9 +547,10 @@ void qemu_flush_queued_packets(VLANClientState *vc)
qemu_net_queue_flush(queue); qemu_net_queue_flush(queue);
} }
ssize_t qemu_send_packet_async(VLANClientState *sender, static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender,
const uint8_t *buf, int size, unsigned flags,
NetPacketSent *sent_cb) const uint8_t *buf, int size,
NetPacketSent *sent_cb)
{ {
NetQueue *queue; NetQueue *queue;
@ -562,9 +569,15 @@ ssize_t qemu_send_packet_async(VLANClientState *sender,
queue = sender->vlan->send_queue; queue = sender->vlan->send_queue;
} }
return qemu_net_queue_send(queue, sender, return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
QEMU_NET_PACKET_FLAG_NONE, }
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) void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
@ -572,6 +585,12 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
qemu_send_packet_async(vc, buf, size, NULL); 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, static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov,
int iovcnt) int iovcnt)
{ {
@ -641,6 +660,8 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
continue; continue;
} }
assert(!(flags & QEMU_NET_PACKET_FLAG_RAW));
if (vc->receive_iov) { if (vc->receive_iov) {
len = vc->receive_iov(vc, iov, iovcnt); len = vc->receive_iov(vc, iov, iovcnt);
} else { } else {

2
net.h
View file

@ -45,6 +45,7 @@ typedef void (LinkStatusChanged)(VLANClientState *);
struct VLANClientState { struct VLANClientState {
net_client_type type; net_client_type type;
NetReceive *receive; NetReceive *receive;
NetReceive *receive_raw;
NetReceiveIOV *receive_iov; NetReceiveIOV *receive_iov;
/* Packets may still be sent if this returns zero. It's used to /* Packets may still be sent if this returns zero. It's used to
rate-limit the slirp code. */ rate-limit the slirp code. */
@ -89,6 +90,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov,
ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov, ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov,
int iovcnt, NetPacketSent *sent_cb); int iovcnt, NetPacketSent *sent_cb);
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); 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, ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf,
int size, NetPacketSent *sent_cb); int size, NetPacketSent *sent_cb);
void qemu_purge_queued_packets(VLANClientState *vc); void qemu_purge_queued_packets(VLANClientState *vc);