diff options
-rw-r--r-- | vnet/vnet/devices/af_packet/af_packet.c | 2 | ||||
-rw-r--r-- | vnet/vnet/devices/af_packet/device.c | 39 |
2 files changed, 32 insertions, 9 deletions
diff --git a/vnet/vnet/devices/af_packet/af_packet.c b/vnet/vnet/devices/af_packet/af_packet.c index b41eaf3ba82..e3ed3857982 100644 --- a/vnet/vnet/devices/af_packet/af_packet.c +++ b/vnet/vnet/devices/af_packet/af_packet.c @@ -115,7 +115,7 @@ create_packet_v2_sock(u8 * name, tpacket_req_t * rx_req, tpacket_req_t * tx_req, int opt = 1; if ((err = setsockopt(*fd, SOL_PACKET, PACKET_LOSS, &opt, sizeof(opt))) < 0) { - DBG_SOCK("Failed to set rx packet interface version"); + DBG_SOCK("Failed to set packet tx ring error handling option"); ret = VNET_API_ERROR_SYSCALL_ERROR_1; goto error; } diff --git a/vnet/vnet/devices/af_packet/device.c b/vnet/vnet/devices/af_packet/device.c index 0671d9e247d..f572632ce37 100644 --- a/vnet/vnet/devices/af_packet/device.c +++ b/vnet/vnet/devices/af_packet/device.c @@ -26,8 +26,11 @@ #include <vnet/devices/af_packet/af_packet.h> -#define foreach_af_packet_tx_func_error \ -_(FRAME_NOT_READY, "tx frame not ready") +#define foreach_af_packet_tx_func_error \ +_(FRAME_NOT_READY, "tx frame not ready") \ +_(TXRING_EAGAIN, "tx sendto temporary failure") \ +_(TXRING_FATAL, "tx sendto fatal failure") \ +_(TXRING_OVERRUN, "tx ring overrun") typedef enum { #define _(f,s) AF_PACKET_TX_ERROR_##f, @@ -96,7 +99,7 @@ af_packet_interface_tx (vlib_main_t * vm, tph = (struct tpacket2_hdr *) (block_start + tx_frame * frame_size); - if(tph->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING)) + if (PREDICT_FALSE(tph->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING))) { frame_not_ready++; goto next; @@ -116,21 +119,41 @@ af_packet_interface_tx (vlib_main_t * vm, tph->tp_status = TP_STATUS_SEND_REQUEST; n_sent++; next: + /* check if we've exhausted the ring */ + if (PREDICT_FALSE(frame_not_ready + n_sent == frame_num)) + break; + tx_frame = (tx_frame + 1) % frame_num; } CLIB_MEMORY_BARRIER(); - if (n_sent) + if (PREDICT_TRUE(n_sent)) { apif->next_tx_frame = tx_frame; - if (sendto(apif->fd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1) - clib_unix_error("tx sendto failure"); + + if (PREDICT_FALSE(sendto(apif->fd, NULL, 0, + MSG_DONTWAIT, NULL, 0) == -1)) + { + /* Uh-oh, drop & move on, but count whether it was fatal or not. + * Note that we have no reliable way to properly determine the + * disposition of the packets we just enqueued for delivery. + */ + vlib_error_count (vm, node->node_index, + unix_error_is_fatal(errno) ? + AF_PACKET_TX_ERROR_TXRING_FATAL : + AF_PACKET_TX_ERROR_TXRING_EAGAIN, + n_sent); + } } - if (frame_not_ready) + if (PREDICT_FALSE(frame_not_ready)) vlib_error_count (vm, node->node_index, AF_PACKET_TX_ERROR_FRAME_NOT_READY, - frame_not_ready); + frame_not_ready); + + if (PREDICT_FALSE(frame_not_ready + n_sent == frame_num)) + vlib_error_count (vm, node->node_index, AF_PACKET_TX_ERROR_TXRING_OVERRUN, + n_left); vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors); return frame->n_vectors; |