static int
create_packet_v3_sock (int host_if_index, tpacket_req3_t *rx_req,
tpacket_req3_t *tx_req, int *fd, af_packet_ring_t *ring,
- u8 *is_cksum_gso_enabled, u32 fanout_id, u8 is_fanout)
+ u32 fanout_id, af_packet_if_flags_t *flags)
{
af_packet_main_t *apm = &af_packet_main;
struct sockaddr_ll sll;
goto error;
}
- int opt2 = 1;
- if (setsockopt (*fd, SOL_PACKET, PACKET_VNET_HDR, &opt2, sizeof (opt2)) < 0)
+ if (*flags & AF_PACKET_IF_FLAGS_CKSUM_GSO)
{
- vlib_log_debug (
- apm->log_class,
- "Failed to set packet vnet hdr error handling option: %s (errno %d)",
- strerror (errno), errno);
+
+ int opt2 = 1;
+ if (setsockopt (*fd, SOL_PACKET, PACKET_VNET_HDR, &opt2, sizeof (opt2)) <
+ 0)
+ {
+ // remove the flag
+ *flags &= ~AF_PACKET_IF_FLAGS_CKSUM_GSO;
+ vlib_log_debug (apm->log_class,
+ "Failed to set packet vnet hdr error handling "
+ "option: %s (errno %d)",
+ strerror (errno), errno);
+ }
}
- else
- *is_cksum_gso_enabled = 1;
#if defined(PACKET_QDISC_BYPASS)
- /* Introduced with Linux 3.14 so the ifdef should eventually be removed */
- if (setsockopt (*fd, SOL_PACKET, PACKET_QDISC_BYPASS, &opt, sizeof (opt)) <
- 0)
- {
- vlib_log_debug (apm->log_class,
- "Failed to set qdisc bypass error "
- "handling option: %s (errno %d)",
- strerror (errno), errno);
- }
+ if (*flags & AF_PACKET_IF_FLAGS_QDISC_BYPASS)
+ /* Introduced with Linux 3.14 so the ifdef should eventually be removed */
+ if (setsockopt (*fd, SOL_PACKET, PACKET_QDISC_BYPASS, &opt, sizeof (opt)) <
+ 0)
+ {
+ // remove the flag
+ *flags &= ~AF_PACKET_IF_FLAGS_QDISC_BYPASS;
+ vlib_log_debug (apm->log_class,
+ "Failed to set qdisc bypass error "
+ "handling option: %s (errno %d)",
+ strerror (errno), errno);
+ }
#endif
- if (is_fanout)
+ if (rx_req)
{
- int fanout = ((fanout_id & 0xffff) | ((PACKET_FANOUT_HASH) << 16));
- if (setsockopt (*fd, SOL_PACKET, PACKET_FANOUT, &fanout,
- sizeof (fanout)) < 0)
+ if (*flags & AF_PACKET_IF_FLAGS_FANOUT)
+ {
+ int fanout = ((fanout_id & 0xffff) | ((PACKET_FANOUT_HASH) << 16));
+ if (setsockopt (*fd, SOL_PACKET, PACKET_FANOUT, &fanout,
+ sizeof (fanout)) < 0)
+ {
+ // remove the flag
+ *flags &= ~AF_PACKET_IF_FLAGS_FANOUT;
+ vlib_log_err (apm->log_class,
+ "Failed to set fanout options: %s (errno %d)",
+ strerror (errno), errno);
+ ret = VNET_API_ERROR_SYSCALL_ERROR_1;
+ goto error;
+ }
+ }
+
+ if (setsockopt (*fd, SOL_PACKET, PACKET_RX_RING, rx_req, req_sz) < 0)
{
vlib_log_err (apm->log_class,
- "Failed to set fanout options: %s (errno %d)",
+ "Failed to set packet rx ring options: %s (errno %d)",
strerror (errno), errno);
ret = VNET_API_ERROR_SYSCALL_ERROR_1;
goto error;
}
}
- if (rx_req)
- if (setsockopt (*fd, SOL_PACKET, PACKET_RX_RING, rx_req, req_sz) < 0)
- {
- vlib_log_err (apm->log_class,
- "Failed to set packet rx ring options: %s (errno %d)",
- strerror (errno), errno);
- ret = VNET_API_ERROR_SYSCALL_ERROR_1;
- goto error;
- }
-
if (tx_req)
if (setsockopt (*fd, SOL_PACKET, PACKET_TX_RING, tx_req, req_sz) < 0)
{
af_packet_queue_init (vlib_main_t *vm, af_packet_if_t *apif,
af_packet_create_if_arg_t *arg,
af_packet_queue_t *rx_queue, af_packet_queue_t *tx_queue,
- u8 queue_id, u8 is_fanout)
+ u8 queue_id)
{
af_packet_main_t *apm = &af_packet_main;
tpacket_req3_t *rx_req = 0;
u32 rx_frames_per_block, tx_frames_per_block;
u32 rx_frame_size, tx_frame_size;
u32 i = 0;
- u8 is_cksum_gso_enabled = 0;
if (rx_queue)
{
if (rx_queue || tx_queue)
{
ret = create_packet_v3_sock (apif->host_if_index, rx_req, tx_req, &fd,
- &ring, &is_cksum_gso_enabled,
- apif->dev_instance, is_fanout);
+ &ring, apif->dev_instance, &arg->flags);
if (ret != 0)
goto error;
tx_queue->next_tx_frame = 0;
tx_queue->queue_id = queue_id;
+ tx_queue->is_tx_pending = 0;
clib_spinlock_init (&tx_queue->lockp);
}
- if (queue_id == 0)
- apif->is_cksum_gso_enabled = is_cksum_gso_enabled;
-
return 0;
error:
vlib_log_err (apm->log_class, "Failed to set queue %u error", queue_id);
u16 nq = clib_min (args->num_rxqs, args->num_txqs);
u16 i = 0;
int ret = 0;
- u8 is_fanout = (args->num_rxqs > 1) ? 1 : 0;
+
+ // enable fanout feature for multi-rxqs
+ if (args->num_rxqs > 1)
+ args->flags |= AF_PACKET_IF_FLAGS_FANOUT;
vec_validate (apif->rx_queues, args->num_rxqs - 1);
vec_validate (apif->tx_queues, args->num_txqs - 1);
{
rx_queue = vec_elt_at_index (apif->rx_queues, i);
tx_queue = vec_elt_at_index (apif->tx_queues, i);
- ret = af_packet_queue_init (vm, apif, args, rx_queue, tx_queue, i,
- is_fanout);
+ ret = af_packet_queue_init (vm, apif, args, rx_queue, tx_queue, i);
if (ret != 0)
goto error;
}
for (; i < args->num_rxqs; i++)
{
rx_queue = vec_elt_at_index (apif->rx_queues, i);
- ret =
- af_packet_queue_init (vm, apif, args, rx_queue, 0, i, is_fanout);
+ ret = af_packet_queue_init (vm, apif, args, rx_queue, 0, i);
if (ret != 0)
goto error;
}
for (; i < args->num_txqs; i++)
{
tx_queue = vec_elt_at_index (apif->tx_queues, i);
- ret = af_packet_queue_init (vm, apif, args, 0, tx_queue, i, 0);
+ ret = af_packet_queue_init (vm, apif, args, 0, tx_queue, i);
if (ret != 0)
goto error;
}
af_packet_set_rx_queues (vm, apif);
af_packet_set_tx_queues (vm, apif);
+ if (arg->flags & AF_PACKET_IF_FLAGS_FANOUT)
+ apif->is_fanout_enabled = 1;
+
+ apif->is_qdisc_bypass_enabled =
+ (arg->flags & AF_PACKET_IF_FLAGS_QDISC_BYPASS);
+
+ if (arg->flags & AF_PACKET_IF_FLAGS_CKSUM_GSO)
+ apif->is_cksum_gso_enabled = 1;
+
if (apif->is_cksum_gso_enabled)
caps |= VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_TX_IP4_CKSUM |
VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM;
fd2 = -1;
}
vec_free (host_if_name_dup);
- memset (apif, 0, sizeof (*apif));
- pool_put (apm->interfaces, apif);
+ if (apif)
+ {
+ memset (apif, 0, sizeof (*apif));
+ pool_put (apm->interfaces, apif);
+ }
return ret;
}