Update the netdev_class so that struct ofpbuf * is passed to rx_recv() to provide both the data and size of the data to read a packet into.
On success, update struct ofpbuf size inside netdev_class rx_recv implementation and return 0. This moves logic from the caller. On error a negative error code is returned, this behaviour is unchanged by this patch. This patch should not have any behavioural changes. This patch is in preparation for the netdev-linux variant of rx_recv() making use of headroom in the struct ofpbuf * parameter to push a VLAN tag obtained from auxdata. Signed-off-by: Simon Horman <ho...@verge.net.au> --- v3 * On success, update struct ofpbuf size inside netdev_class rx_recv implementation and return 0. This moves logic from the caller. * Document that it is recommended that the struct ofpbuf should provide extra tailroom for a VLAN header. This will be used by a subsequent patch. * Update BSD code v2 * First post --- lib/netdev-bsd.c | 24 ++++++++++++++---------- lib/netdev-dummy.c | 9 +++++---- lib/netdev-linux.c | 16 ++++++++++------ lib/netdev-provider.h | 18 ++++++++++++------ lib/netdev.c | 4 +--- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index 442c384..37b2a02 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -568,20 +568,21 @@ proc_pkt(u_char *args_, const struct pcap_pkthdr *hdr, const u_char *packet) * from rx->pcap. */ static int -netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, void *data, size_t size) +netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, struct ofpbuf *buffer) { struct pcap_arg arg; int ret; /* prepare the pcap argument to store the packet */ - arg.size = size; - arg.data = data; + arg.size = ofpbuf_tailroom(buffer); + arg.data = buffer->data; for (;;) { ret = pcap_dispatch(rx->pcap_handle, 1, proc_pkt, (u_char *) &arg); if (ret > 0) { - return arg.retval; /* arg.retval < 0 is handled in the caller */ + buffer->size += retval; + return 0; } if (ret == -1) { if (errno == EINTR) { @@ -599,12 +600,15 @@ netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, void *data, size_t size) * 'rx->fd' is initialized with the tap file descriptor. */ static int -netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, void *data, size_t size) +netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, struct ofpbuf *buffer) { + size_t size = ofpbuf_tailroom(buffer); + for (;;) { - ssize_t retval = read(rx->fd, data, size); + ssize_t retval = read(rx->fd, buffer->data, size); if (retval >= 0) { - return retval; + buffer->size += retval; + return 0; } else if (errno != EINTR) { if (errno != EAGAIN) { VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s", @@ -616,13 +620,13 @@ netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, void *data, size_t size) } static int -netdev_bsd_rx_recv(struct netdev_rx *rx_, void *data, size_t size) +netdev_bsd_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer) { struct netdev_rx_bsd *rx = netdev_rx_bsd_cast(rx_); return (rx->pcap_handle - ? netdev_rx_bsd_recv_pcap(rx, data, size) - : netdev_rx_bsd_recv_tap(rx, data, size)); + ? netdev_rx_bsd_recv_pcap(rx, buffer) + : netdev_rx_bsd_recv_tap(rx, buffer)); } /* diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 9515021..51b77db 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -445,7 +445,7 @@ netdev_dummy_rx_dealloc(struct netdev_rx *rx_) } static int -netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size) +netdev_dummy_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer) { struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_); struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev); @@ -465,9 +465,10 @@ netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size) return -EAGAIN; } - if (packet->size <= size) { - memcpy(buffer, packet->data, packet->size); - retval = packet->size; + if (packet->size <= ofpbuf_tailroom(buffer)) { + memcpy(buffer->data, packet->data, packet->size); + buffer->size += packet->size; + retval = 0; ovs_mutex_lock(&netdev->mutex); netdev->stats.rx_packets++; diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 9bdbbdf..ffaaa3b 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -849,25 +849,29 @@ netdev_linux_rx_dealloc(struct netdev_rx *rx_) } static int -netdev_linux_rx_recv(struct netdev_rx *rx_, void *data, size_t size) +netdev_linux_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer) { struct netdev_rx_linux *rx = netdev_rx_linux_cast(rx_); ssize_t retval; + size_t size = ofpbuf_tailroom(buffer); do { retval = (rx->is_tap - ? read(rx->fd, data, size) - : recv(rx->fd, data, size, MSG_TRUNC)); + ? read(rx->fd, buffer->data, size) + : recv(rx->fd, buffer->data, size, MSG_TRUNC)); } while (retval < 0 && errno == EINTR); - if (retval >= 0) { - return retval > size ? -EMSGSIZE : retval; - } else { + if (retval < 0) { if (errno != EAGAIN) { VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s", ovs_strerror(errno), netdev_rx_get_name(rx_)); } return -errno; + } else if (retval > size) { + return -EMSGSIZE; + } else { + buffer->size += retval; + return 0; } } diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 40ba944..6eec315 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -634,16 +634,22 @@ struct netdev_class { void (*rx_destruct)(struct netdev_rx *); void (*rx_dealloc)(struct netdev_rx *); - /* Attempts to receive a packet from 'rx' into the 'size' bytes in - * 'buffer'. If successful, returns the number of bytes in the received - * packet, otherwise a negative errno value. Returns -EAGAIN immediately - * if no packet is ready to be received. + /* Attempts to receive a packet from 'rx' into 'buffer'. + * If successful, returns 0 and increments the 'size' field of 'buffer' + * by the number of bytes in the received packet, otherwise a negative + * errno value. Returns -EAGAIN immediately if no packet is ready to + * be received. * * Must return -EMSGSIZE, and discard the packet, if the received packet - * is longer than 'size' bytes. + * is longer than the tailroom of 'buffer'. + * + * It is advised that the tailroom of 'buffer' should be + * VLAN_HEADER_LEN bytes longer than the expected maximum packet size + * to allow space for an out of band VLAN header to be added to the + * packet. * * Specify NULL if this */ - int (*rx_recv)(struct netdev_rx *rx, void *buffer, size_t size); + int (*rx_recv)(struct netdev_rx *rx, struct ofpbuf *buffer); /* Registers with the poll loop to wake up from the next call to * poll_block() when a packet is ready to be received with netdev_rx_recv() diff --git a/lib/netdev.c b/lib/netdev.c index 1bcd80f..276bf84 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -550,11 +550,9 @@ netdev_rx_recv(struct netdev_rx *rx, struct ofpbuf *buffer) ovs_assert(buffer->size == 0); ovs_assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN); - retval = rx->netdev->netdev_class->rx_recv(rx, buffer->data, - ofpbuf_tailroom(buffer)); + retval = rx->netdev->netdev_class->rx_recv(rx, buffer); if (retval >= 0) { COVERAGE_INC(netdev_received); - buffer->size += retval; if (buffer->size < ETH_TOTAL_MIN) { ofpbuf_put_zeros(buffer, ETH_TOTAL_MIN - buffer->size); } -- 1.8.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev