atomic_read(&rc->ref_cnt, &ref_cnt);
if (!ref_cnt) {
hmap_remove(&netdev_classes, &rc->hmap_node);
+ atomic_destroy(&rc->ref_cnt);
free(rc);
error = 0;
} else {
}
}
+/* Attempts to open a netdev_rx handle for obtaining packets received on
+ * 'netdev'. On success, returns 0 and stores a nonnull 'netdev_rx *' into
+ * '*rxp'. On failure, returns a positive errno value and stores NULL into
+ * '*rxp'.
+ *
+ * Some kinds of network devices might not support receiving packets. This
+ * function returns EOPNOTSUPP in that case.*/
int
netdev_rx_open(struct netdev *netdev, struct netdev_rx **rxp)
OVS_EXCLUDED(netdev_mutex)
return error;
}
+/* Closes 'rx'. */
void
netdev_rx_close(struct netdev_rx *rx)
OVS_EXCLUDED(netdev_mutex)
}
}
+/* Attempts to receive a packet from 'rx' into the tailroom of 'buffer', which
+ * must initially be empty. If successful, returns 0 and increments
+ * 'buffer->size' by the number of bytes in the received packet, otherwise a
+ * positive errno value.
+ *
+ * Returns EAGAIN immediately if no packet is ready to be received.
+ *
+ * Returns EMSGSIZE, and discards the packet, if the received packet is longer
+ * than 'ofpbuf_tailroom(buffer)'.
+ *
+ * Implementations may make use of VLAN_HEADER_LEN bytes of tailroom to
+ * add a VLAN header which is obtained out-of-band to the packet. If
+ * this occurs then VLAN_HEADER_LEN bytes of tailroom will no longer be
+ * available for the packet, otherwise it may be used for the packet
+ * itself.
+ *
+ * It is advised that the tailroom of 'buffer' should be
+ * VLAN_HEADER_LEN bytes longer than the MTU to allow space for an
+ * out-of-band VLAN header to be added to the packet. At the very least,
+ * 'buffer' must have at least ETH_TOTAL_MIN bytes of tailroom.
+ *
+ * This function may be set to null if it would always return EOPNOTSUPP
+ * anyhow. */
int
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));
- if (retval >= 0) {
+ retval = rx->netdev->netdev_class->rx_recv(rx, buffer);
+ if (!retval) {
COVERAGE_INC(netdev_received);
- buffer->size += retval;
if (buffer->size < ETH_TOTAL_MIN) {
ofpbuf_put_zeros(buffer, ETH_TOTAL_MIN - buffer->size);
}
return 0;
} else {
- return -retval;
+ return retval;
}
}
+/* Arranges for poll_block() to wake up when a packet is ready to be received
+ * on 'rx'. */
void
netdev_rx_wait(struct netdev_rx *rx)
{
rx->netdev->netdev_class->rx_wait(rx);
}
+/* Discards any packets ready to be received on 'rx'. */
int
netdev_rx_drain(struct netdev_rx *rx)
{