+ tpacket_req3_t *rx_req = 0;
+ tpacket_req3_t *tx_req = 0;
+ int ret, fd = -1;
+ af_packet_ring_t ring = { 0 };
+ u8 *ring_addr = 0;
+ u32 rx_frames_per_block, tx_frames_per_block;
+ u32 rx_frame_size, tx_frame_size;
+ u32 i = 0;
+
+ if (rx_queue)
+ {
+ rx_frames_per_block = arg->rx_frames_per_block ?
+ arg->rx_frames_per_block :
+ AF_PACKET_DEFAULT_RX_FRAMES_PER_BLOCK;
+
+ rx_frame_size = arg->rx_frame_size ? arg->rx_frame_size :
+ AF_PACKET_DEFAULT_RX_FRAME_SIZE;
+ vec_validate (rx_queue->rx_req, 0);
+ rx_queue->rx_req->tp_block_size = rx_frame_size * rx_frames_per_block;
+ rx_queue->rx_req->tp_frame_size = rx_frame_size;
+ rx_queue->rx_req->tp_block_nr = AF_PACKET_RX_BLOCK_NR;
+ rx_queue->rx_req->tp_frame_nr =
+ AF_PACKET_RX_BLOCK_NR * rx_frames_per_block;
+ rx_queue->rx_req->tp_retire_blk_tov = 1; // 1 ms block timout
+ rx_queue->rx_req->tp_feature_req_word = 0;
+ rx_queue->rx_req->tp_sizeof_priv = 0;
+ rx_req = rx_queue->rx_req;
+ }
+
+ if (tx_queue)
+ {
+ tx_frames_per_block = arg->tx_frames_per_block ?
+ arg->tx_frames_per_block :
+ AF_PACKET_DEFAULT_TX_FRAMES_PER_BLOCK;
+ tx_frame_size = arg->tx_frame_size ? arg->tx_frame_size :
+ AF_PACKET_DEFAULT_TX_FRAME_SIZE;
+
+ vec_validate (tx_queue->tx_req, 0);
+ tx_queue->tx_req->tp_block_size = tx_frame_size * tx_frames_per_block;
+ tx_queue->tx_req->tp_frame_size = tx_frame_size;
+ tx_queue->tx_req->tp_block_nr = AF_PACKET_TX_BLOCK_NR;
+ tx_queue->tx_req->tp_frame_nr =
+ AF_PACKET_TX_BLOCK_NR * tx_frames_per_block;
+ tx_queue->tx_req->tp_retire_blk_tov = 0;
+ tx_queue->tx_req->tp_sizeof_priv = 0;
+ tx_queue->tx_req->tp_feature_req_word = 0;
+ tx_req = tx_queue->tx_req;
+ }
+
+ if (rx_queue || tx_queue)
+ {
+ ret = create_packet_v3_sock (apif->host_if_index, rx_req, tx_req, &fd,
+ &ring, apif->dev_instance, &arg->flags);
+
+ if (ret != 0)
+ goto error;
+
+ vec_add1 (apif->rings, ring);
+ ring_addr = ring.ring_start_addr;
+ }
+
+ if (rx_queue)
+ {
+ rx_queue->fd = fd;
+ vec_validate (rx_queue->rx_ring, rx_queue->rx_req->tp_block_nr - 1);
+ vec_foreach_index (i, rx_queue->rx_ring)
+ {
+ rx_queue->rx_ring[i] =
+ ring_addr + i * rx_queue->rx_req->tp_block_size;
+ }
+
+ rx_queue->next_rx_block = 0;
+ rx_queue->queue_id = queue_id;
+ rx_queue->is_rx_pending = 0;
+ ring_addr = ring_addr + rx_queue->rx_req->tp_block_size *
+ rx_queue->rx_req->tp_block_nr;
+ }
+
+ if (tx_queue)
+ {
+ tx_queue->fd = fd;
+ vec_validate (tx_queue->tx_ring, tx_queue->tx_req->tp_block_nr - 1);
+ vec_foreach_index (i, tx_queue->tx_ring)
+ {
+ tx_queue->tx_ring[i] =
+ ring_addr + i * tx_queue->tx_req->tp_block_size;
+ }
+
+ tx_queue->next_tx_frame = 0;
+ tx_queue->queue_id = queue_id;
+ clib_spinlock_init (&tx_queue->lockp);
+ }
+
+ return 0;
+error:
+ vlib_log_err (apm->log_class, "Failed to set queue %u error", queue_id);
+ if (rx_queue)
+ vec_free (rx_queue->rx_req);
+ if (tx_queue)
+ vec_free (tx_queue->tx_req);
+ return ret;
+}
+
+int
+af_packet_device_init (vlib_main_t *vm, af_packet_if_t *apif,
+ af_packet_create_if_arg_t *args)
+{
+ af_packet_main_t *apm = &af_packet_main;
+ af_packet_queue_t *rx_queue = 0;
+ af_packet_queue_t *tx_queue = 0;
+ u16 nq = clib_min (args->num_rxqs, args->num_txqs);
+ u16 i = 0;
+ int ret = 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);
+
+ for (; i < nq; i++)
+ {
+ 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);
+ if (ret != 0)
+ goto error;
+ }
+
+ if (args->num_rxqs > args->num_txqs)
+ {
+ 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);
+ if (ret != 0)
+ goto error;
+ }
+ }
+ else if (args->num_txqs > args->num_rxqs)
+ {
+ 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);
+ if (ret != 0)
+ goto error;
+ }
+ }
+
+ apif->num_rxqs = args->num_rxqs;
+ apif->num_txqs = args->num_txqs;
+
+ return 0;
+error:
+ vlib_log_err (apm->log_class, "Failed to init device error");
+ return ret;
+}
+
+int
+af_packet_create_if (af_packet_create_if_arg_t *arg)
+{
+ af_packet_main_t *apm = &af_packet_main;
+ vlib_main_t *vm = vlib_get_main ();
+ int fd2 = -1;