IP6 SR multicast replicator
[vpp.git] / vnet / vnet / devices / dpdk / device.c
index 7821ebe..20c8b8f 100644 (file)
@@ -77,7 +77,7 @@ dpdk_set_mc_filter (vnet_hw_interface_t * hi,
   }
 }
 
-static struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b)
+struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b)
 {
   vlib_main_t * vm = vlib_get_main();
   vlib_buffer_main_t * bm = vm->buffer_main;
@@ -135,7 +135,7 @@ static struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b)
       rte_pktmbuf_data_len (new_mb) = pkt_mb->data_len;
       copy_bytes = pkt_mb->data_len + RTE_PKTMBUF_HEADROOM;
       ASSERT(copy_bytes <= pkt_mb->buf_len);
-      memcpy(new_mb->buf_addr, pkt_mb->buf_addr, copy_bytes);
+      clib_memcpy(new_mb->buf_addr, pkt_mb->buf_addr, copy_bytes);
 
       prev_mb_next = &new_mb->next;
       pkt_mb = pkt_mb->next;
@@ -147,6 +147,74 @@ static struct rte_mbuf * dpdk_replicate_packet_mb (vlib_buffer_t * b)
   return first_mb;
 }
 
+struct rte_mbuf * dpdk_zerocopy_replicate_packet_mb (vlib_buffer_t * b)
+{
+  vlib_main_t * vm = vlib_get_main();
+  vlib_buffer_main_t * bm = vm->buffer_main;
+  struct rte_mbuf * first_mb = 0, * new_mb, * pkt_mb, ** prev_mb_next = 0;
+  u8 nb_segs, nb_segs_left;
+  unsigned socket_id = rte_socket_id();
+
+  ASSERT (bm->pktmbuf_pools[socket_id]);
+  pkt_mb = rte_mbuf_from_vlib_buffer(b);
+  nb_segs = pkt_mb->nb_segs;
+  for (nb_segs_left = nb_segs; nb_segs_left; nb_segs_left--)
+    {
+      if (PREDICT_FALSE(pkt_mb == 0))
+       {
+         clib_warning ("Missing %d mbuf chain segment(s):   "
+                       "(nb_segs = %d, nb_segs_left = %d)!",
+                       nb_segs - nb_segs_left, nb_segs, nb_segs_left);
+         if (first_mb)
+           rte_pktmbuf_free(first_mb);
+         return NULL;
+       }
+      new_mb = rte_pktmbuf_clone(pkt_mb, bm->pktmbuf_pools[socket_id]);
+      if (PREDICT_FALSE(new_mb == 0))
+       {
+         if (first_mb)
+           rte_pktmbuf_free(first_mb);
+         return NULL;
+       }
+      
+      /*
+       * Copy packet info into 1st segment.
+       */
+      if (first_mb == 0)
+       {
+         first_mb = new_mb;
+         rte_pktmbuf_pkt_len (first_mb) = pkt_mb->pkt_len;
+         first_mb->nb_segs = pkt_mb->nb_segs;
+         first_mb->port = pkt_mb->port;
+#ifdef DAW_FIXME // TX Offload support TBD
+         first_mb->vlan_macip = pkt_mb->vlan_macip;
+         first_mb->hash = pkt_mb->hash;
+         first_mb->ol_flags = pkt_mb->ol_flags
+#endif
+       }
+      else
+       {
+         ASSERT(prev_mb_next != 0);
+         *prev_mb_next = new_mb;
+       }
+      
+      /*
+       * Copy packet segment data into new mbuf segment.
+       */
+      rte_pktmbuf_data_len (new_mb) = pkt_mb->data_len;
+
+      prev_mb_next = &new_mb->next;
+      pkt_mb = pkt_mb->next;
+    }
+
+  ASSERT(pkt_mb == 0);
+  __rte_mbuf_sanity_check(first_mb, 1);
+
+  return first_mb;
+
+
+}
+
 static void
 dpdk_tx_trace_buffer (dpdk_main_t * dm,
                      vlib_node_runtime_t * node,
@@ -165,9 +233,9 @@ dpdk_tx_trace_buffer (dpdk_main_t * dm,
   t0->queue_index = queue_id;
   t0->device_index = xd->device_index;
   t0->buffer_index = buffer_index;
-  memcpy (&t0->mb, mb, sizeof (t0->mb));
-  memcpy (&t0->buffer, buffer, sizeof (buffer[0]) - sizeof (buffer->pre_data));
-  memcpy (t0->buffer.pre_data, buffer->data + buffer->current_data,
+  clib_memcpy (&t0->mb, mb, sizeof (t0->mb));
+  clib_memcpy (&t0->buffer, buffer, sizeof (buffer[0]) - sizeof (buffer->pre_data));
+  clib_memcpy (t0->buffer.pre_data, buffer->data + buffer->current_data,
          sizeof (t0->buffer.pre_data));
 }
 
@@ -608,37 +676,37 @@ dpdk_interface_tx (vlib_main_t * vm,
       if (PREDICT_FALSE(any_clone != 0))
         {
           if (PREDICT_FALSE(b0->clone_count != 0))
-        {
-          struct rte_mbuf * mb0_new = dpdk_replicate_packet_mb (b0);
-          if (PREDICT_FALSE(mb0_new == 0))
-            {
-              vlib_error_count (vm, node->node_index,
-                    DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
-              b0->flags |= VLIB_BUFFER_REPL_FAIL;
-            }
-          else
-            mb0 = mb0_new;
-          vec_add1 (dm->recycle[my_cpu], bi0);
-        }
+           {
+             struct rte_mbuf * mb0_new = dpdk_replicate_packet_mb (b0);
+             if (PREDICT_FALSE(mb0_new == 0))
+               {
+                 vlib_error_count (vm, node->node_index,
+                                   DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
+                 b0->flags |= VLIB_BUFFER_REPL_FAIL;
+               }
+             else
+               mb0 = mb0_new;
+             vec_add1 (dm->recycle[my_cpu], bi0);
+           }
           if (PREDICT_FALSE(b1->clone_count != 0))
-        {
-          struct rte_mbuf * mb1_new = dpdk_replicate_packet_mb (b1);
-          if (PREDICT_FALSE(mb1_new == 0))
-            {
-              vlib_error_count (vm, node->node_index,
-                    DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
-              b1->flags |= VLIB_BUFFER_REPL_FAIL;
-            }
-          else
-            mb1 = mb1_new;
-          vec_add1 (dm->recycle[my_cpu], bi1);
-        }
-    }
+           {
+             struct rte_mbuf * mb1_new = dpdk_replicate_packet_mb (b1);
+             if (PREDICT_FALSE(mb1_new == 0))
+               {
+                 vlib_error_count (vm, node->node_index,
+                                   DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
+                 b1->flags |= VLIB_BUFFER_REPL_FAIL;
+               }
+             else
+               mb1 = mb1_new;
+             vec_add1 (dm->recycle[my_cpu], bi1);
+           }
+       }
 
       delta0 = PREDICT_FALSE(b0->flags & VLIB_BUFFER_REPL_FAIL) ? 0 :
-    vlib_buffer_length_in_chain (vm, b0) - (i16) mb0->pkt_len;
+       vlib_buffer_length_in_chain (vm, b0) - (i16) mb0->pkt_len;
       delta1 = PREDICT_FALSE(b1->flags & VLIB_BUFFER_REPL_FAIL) ? 0 :
-    vlib_buffer_length_in_chain (vm, b1) - (i16) mb1->pkt_len;
+       vlib_buffer_length_in_chain (vm, b1) - (i16) mb1->pkt_len;
       
       new_data_len0 = (u16)((i16) mb0->data_len + delta0);
       new_data_len1 = (u16)((i16) mb1->data_len + delta1);
@@ -653,23 +721,23 @@ dpdk_interface_tx (vlib_main_t * vm,
       mb1->pkt_len = new_pkt_len1;
 
       mb0->data_off = (PREDICT_FALSE(b0->flags & VLIB_BUFFER_REPL_FAIL)) ?
-          mb0->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b0->current_data);
+       mb0->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b0->current_data);
       mb1->data_off = (PREDICT_FALSE(b1->flags & VLIB_BUFFER_REPL_FAIL)) ?
-          mb1->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b1->current_data);
+       mb1->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b1->current_data);
 
       if (PREDICT_FALSE(node->flags & VLIB_NODE_FLAG_TRACE))
-    {
+       {
           if (b0->flags & VLIB_BUFFER_IS_TRACED)
-              dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi0, b0);
+           dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi0, b0);
           if (b1->flags & VLIB_BUFFER_IS_TRACED)
-              dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi1, b1);
-    }
+           dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi1, b1);
+       }
 
       if (PREDICT_TRUE(any_clone == 0))
         {
-      tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
+         tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
           i++;
-      tx_vector[i % DPDK_TX_RING_SIZE] = mb1;
+         tx_vector[i % DPDK_TX_RING_SIZE] = mb1;
           i++;
         }
       else
@@ -677,16 +745,16 @@ dpdk_interface_tx (vlib_main_t * vm,
           /* cloning was done, need to check for failure */
           if (PREDICT_TRUE((b0->flags & VLIB_BUFFER_REPL_FAIL) == 0))
             {
-          tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
+             tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
               i++;
             }
           if (PREDICT_TRUE((b1->flags & VLIB_BUFFER_REPL_FAIL) == 0))
             {
-          tx_vector[i % DPDK_TX_RING_SIZE] = mb1;
+             tx_vector[i % DPDK_TX_RING_SIZE] = mb1;
               i++;
             }
         }
-
+      
       n_left -= 2;
     }
   while (n_left > 0)
@@ -705,21 +773,21 @@ dpdk_interface_tx (vlib_main_t * vm,
 
       mb0 = rte_mbuf_from_vlib_buffer(b0);
       if (PREDICT_FALSE(b0->clone_count != 0))
-    {
-      struct rte_mbuf * mb0_new = dpdk_replicate_packet_mb (b0);
-      if (PREDICT_FALSE(mb0_new == 0))
-        {
-          vlib_error_count (vm, node->node_index,
-                DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
-          b0->flags |= VLIB_BUFFER_REPL_FAIL;
-        }
-      else
-        mb0 = mb0_new;
-      vec_add1 (dm->recycle[my_cpu], bi0);
-    }
+       {
+         struct rte_mbuf * mb0_new = dpdk_replicate_packet_mb (b0);
+         if (PREDICT_FALSE(mb0_new == 0))
+           {
+             vlib_error_count (vm, node->node_index,
+                               DPDK_TX_FUNC_ERROR_REPL_FAIL, 1);
+             b0->flags |= VLIB_BUFFER_REPL_FAIL;
+           }
+         else
+           mb0 = mb0_new;
+         vec_add1 (dm->recycle[my_cpu], bi0);
+       }
 
       delta0 = PREDICT_FALSE(b0->flags & VLIB_BUFFER_REPL_FAIL) ? 0 :
-    vlib_buffer_length_in_chain (vm, b0) - (i16) mb0->pkt_len;
+       vlib_buffer_length_in_chain (vm, b0) - (i16) mb0->pkt_len;
       
       new_data_len0 = (u16)((i16) mb0->data_len + delta0);
       new_pkt_len0 = (u16)((i16) mb0->pkt_len + delta0);
@@ -728,15 +796,15 @@ dpdk_interface_tx (vlib_main_t * vm,
       mb0->data_len = new_data_len0;
       mb0->pkt_len = new_pkt_len0;
       mb0->data_off = (PREDICT_FALSE(b0->flags & VLIB_BUFFER_REPL_FAIL)) ?
-          mb0->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b0->current_data);
+       mb0->data_off : (u16)(RTE_PKTMBUF_HEADROOM + b0->current_data);
 
       if (PREDICT_FALSE(node->flags & VLIB_NODE_FLAG_TRACE))
-          if (b0->flags & VLIB_BUFFER_IS_TRACED)
-              dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi0, b0);
+       if (b0->flags & VLIB_BUFFER_IS_TRACED)
+         dpdk_tx_trace_buffer (dm, node, xd, queue_id, bi0, b0);
 
       if (PREDICT_TRUE((b0->flags & VLIB_BUFFER_REPL_FAIL) == 0))
         {
-      tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
+         tx_vector[i % DPDK_TX_RING_SIZE] = mb0;
           i++;
         }
       n_left--;
@@ -783,15 +851,15 @@ dpdk_interface_tx (vlib_main_t * vm,
           vlib_increment_simple_counter (cm, my_cpu, xd->vlib_sw_if_index, n_packets);
 
           vlib_error_count (vm, node->node_index, DPDK_TX_FUNC_ERROR_PKT_DROP,
-                n_packets);
+                           n_packets);
 
           while (n_packets--)
             rte_pktmbuf_free (tx_vector[ring->tx_tail + n_packets]);
         }
 
         /* Reset head/tail to avoid unnecessary wrap */
-        ring->tx_head = 0;
-        ring->tx_tail = 0;
+      ring->tx_head = 0;
+      ring->tx_tail = 0;
     }
 
   /* Recycle replicated buffers */
@@ -813,9 +881,9 @@ static int dpdk_device_renumber (vnet_hw_interface_t * hi,
   dpdk_device_t * xd = vec_elt_at_index (dm->devices, hi->dev_instance);
 
   if (!xd || xd->dev_type != VNET_DPDK_DEV_VHOST_USER) {
-      clib_warning("cannot renumber non-vhost-user interface (sw_if_index: %d)",
-              hi->sw_if_index);
-      return 0;
+    clib_warning("cannot renumber non-vhost-user interface (sw_if_index: %d)",
+                hi->sw_if_index);
+    return 0;
   }
 
   xd->vu_if_id = new_dev_instance;
@@ -841,10 +909,10 @@ static void dpdk_clear_hw_interface_counters (u32 instance)
        */
       dpdk_update_counters (xd, vlib_time_now (dm->vlib_main));
 
-      memcpy (&xd->last_cleared_stats, &xd->stats, sizeof(xd->stats));
-      memcpy (xd->last_cleared_xstats, xd->xstats,
-          vec_len(xd->last_cleared_xstats) *
-          sizeof(xd->last_cleared_xstats[0]));
+      clib_memcpy (&xd->last_cleared_stats, &xd->stats, sizeof(xd->stats));
+      clib_memcpy (xd->last_cleared_xstats, xd->xstats,
+             vec_len(xd->last_cleared_xstats) *
+             sizeof(xd->last_cleared_xstats[0]));
     }
   else
     {
@@ -860,8 +928,8 @@ static void dpdk_clear_hw_interface_counters (u32 instance)
   if (PREDICT_FALSE(xd->dev_type == VNET_DPDK_DEV_VHOST_USER)) {
     int i;
     for (i = 0; i < xd->rx_q_used * VIRTIO_QNUM; i++) {
-        xd->vu_intf->vrings[i].packets = 0;
-        xd->vu_intf->vrings[i].bytes = 0;
+      xd->vu_intf->vrings[i].packets = 0;
+      xd->vu_intf->vrings[i].bytes = 0;
     }
   }
 }
@@ -1256,6 +1324,60 @@ dpdk_get_hw_interface_stats (u32 hw_if_index, struct rte_eth_stats* dest)
 
   dpdk_update_counters (xd, vlib_time_now (dm->vlib_main));
 
-  memcpy(dest, &xd->stats, sizeof(xd->stats));
+  clib_memcpy(dest, &xd->stats, sizeof(xd->stats));
   return (0);
 }
+
+/*
+ * Return the number of dpdk mbufs
+ */
+u32 dpdk_num_mbufs (void)
+{
+  dpdk_main_t * dm = &dpdk_main;
+
+  return dm->num_mbufs;
+}
+
+/*
+ * Return the io_thread_release
+ */
+int dpdk_io_thread_release (void)
+{
+  dpdk_main_t * dm = &dpdk_main;
+
+  return dm->io_thread_release;
+}
+
+/*
+ * Return the pmd type for a given hardware interface
+ */
+dpdk_pmd_t dpdk_get_pmd_type (vnet_hw_interface_t *hi)
+{
+  dpdk_main_t   * dm = &dpdk_main;
+  dpdk_device_t * xd;
+
+  assert (hi);
+
+  xd = vec_elt_at_index (dm->devices, hi->dev_instance);
+
+  assert (xd);
+
+  return xd->pmd;
+}
+
+/*
+ * Return the cpu socket for a given hardware interface
+ */
+i8 dpdk_get_cpu_socket (vnet_hw_interface_t *hi)
+{
+  dpdk_main_t   * dm = &dpdk_main;
+  dpdk_device_t * xd;
+
+  assert (hi);
+
+  xd = vec_elt_at_index(dm->devices, hi->dev_instance);
+
+  assert (xd);
+
+  return xd->cpu_socket;
+}