mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
netdev: netdev_send accepts multiple packets
The netdev_send function has been modified to accept multiple packets, to allow netdev providers to amortize locking and queuing costs. This is especially true for netdev-dpdk. Later commits exploit the new API. Signed-off-by: Daniele Di Proietto <ddiproietto@vmware.com> Acked-by: Pravin B Shelar <pshelar@nicira.com>
This commit is contained in:
committed by
Pravin B Shelar
parent
910885540a
commit
f4fd623c4c
@@ -686,14 +686,13 @@ netdev_bsd_rxq_drain(struct netdev_rxq *rxq_)
|
||||
* system or a tap device.
|
||||
*/
|
||||
static int
|
||||
netdev_bsd_send(struct netdev *netdev_, struct dpif_packet *pkt,
|
||||
netdev_bsd_send(struct netdev *netdev_, struct dpif_packet **pkts, int cnt,
|
||||
bool may_steal)
|
||||
{
|
||||
struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
|
||||
const char *name = netdev_get_name(netdev_);
|
||||
const void *data = ofpbuf_data(&pkt->ofpbuf);
|
||||
size_t size = ofpbuf_size(&pkt->ofpbuf);
|
||||
int error;
|
||||
int i;
|
||||
|
||||
ovs_mutex_lock(&dev->mutex);
|
||||
if (dev->tap_fd < 0 && !dev->pcap) {
|
||||
@@ -702,35 +701,43 @@ netdev_bsd_send(struct netdev *netdev_, struct dpif_packet *pkt,
|
||||
error = 0;
|
||||
}
|
||||
|
||||
while (!error) {
|
||||
ssize_t retval;
|
||||
if (dev->tap_fd >= 0) {
|
||||
retval = write(dev->tap_fd, data, size);
|
||||
} else {
|
||||
retval = pcap_inject(dev->pcap, data, size);
|
||||
}
|
||||
if (retval < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
const void *data = ofpbuf_data(&pkts[i]->ofpbuf);
|
||||
size_t size = ofpbuf_size(&pkts[i]->ofpbuf);
|
||||
|
||||
while (!error) {
|
||||
ssize_t retval;
|
||||
if (dev->tap_fd >= 0) {
|
||||
retval = write(dev->tap_fd, data, size);
|
||||
} else {
|
||||
error = errno;
|
||||
if (error != EAGAIN) {
|
||||
VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: "
|
||||
"%s", name, ovs_strerror(error));
|
||||
}
|
||||
retval = pcap_inject(dev->pcap, data, size);
|
||||
}
|
||||
if (retval < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
error = errno;
|
||||
if (error != EAGAIN) {
|
||||
VLOG_WARN_RL(&rl, "error sending Ethernet packet on"
|
||||
" %s: %s", name, ovs_strerror(error));
|
||||
}
|
||||
}
|
||||
} else if (retval != size) {
|
||||
VLOG_WARN_RL(&rl, "sent partial Ethernet packet "
|
||||
"(%"PRIuSIZE" bytes of "
|
||||
"%"PRIuSIZE") on %s", retval, size, name);
|
||||
error = EMSGSIZE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (retval != size) {
|
||||
VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIuSIZE" bytes of "
|
||||
"%"PRIuSIZE") on %s", retval, size, name);
|
||||
error = EMSGSIZE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ovs_mutex_unlock(&dev->mutex);
|
||||
if (may_steal) {
|
||||
dpif_packet_delete(pkt);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
dpif_packet_delete(pkts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
|
Reference in New Issue
Block a user