armada: initial DSA support 94/41694/18
authorDamjan Marion <[email protected]>
Wed, 23 Oct 2024 14:18:18 +0000 (16:18 +0200)
committerDamjan Marion <[email protected]>
Thu, 7 Nov 2024 15:49:49 +0000 (16:49 +0100)
Type: feature
Change-Id: Ic6578e0ded33ca3c6590c8e6127ec11a0f5b3057
Signed-off-by: Damjan Marion <[email protected]>
src/plugins/dev_armada/pp2/format.c
src/plugins/dev_armada/pp2/init.c
src/plugins/dev_armada/pp2/port.c
src/plugins/dev_armada/pp2/pp2.h
src/plugins/dev_armada/pp2/rx.c
src/plugins/dev_armada/pp2/tx.c

index 37d482b..42c4114 100644 (file)
@@ -152,9 +152,24 @@ format_mvpp2_rx_desc (u8 *s, va_list *args)
     s = format (s, " ");
 
   foreach_pp2_rx_desc_field;
+#undef _
   return s;
 }
 
+u8 *
+format_mv_dsa_tag (u8 *s, va_list *args)
+{
+  mv_dsa_tag_t *tag = va_arg (*args, mv_dsa_tag_t *);
+  u32 cnt = 0;
+
+#define _(b, n)                                                               \
+  if (#n[0] != '_')                                                           \
+    s = format (s, "%s" #n " %u", cnt++ ? " " : "", tag->n);
+  foreach_mv_dsa_tag_field
+#undef _
+    return s;
+}
+
 u8 *
 format_mvpp2_rx_trace (u8 *s, va_list *args)
 {
@@ -162,15 +177,22 @@ format_mvpp2_rx_trace (u8 *s, va_list *args)
   vlib_node_t *node = va_arg (*args, vlib_node_t *);
   mvpp2_rx_trace_t *t = va_arg (*args, mvpp2_rx_trace_t *);
   vnet_main_t *vnm = vnet_get_main ();
-  u32 hw_if_index = t->rxq->port->intf.hw_if_index;
-  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
   u32 indent = format_get_indent (s);
   struct pp2_ppio_desc *d = &t->desc;
 
-  s = format (s, "pp2: %v (%d) next-node %U", hi->name, hw_if_index,
-             format_vlib_next_node_name, vm, node->index, t->rxq->next_index);
+  if (t->sw_if_index != CLIB_U32_MAX)
+    s = format (s, "pp2: %U (%d) next-node %U", format_vnet_sw_if_index_name,
+               vnm, t->sw_if_index, t->sw_if_index,
+               format_vlib_next_node_name, vm, node->index, t->next_index);
+  else
+    s = format (s, "pp2: next-node %U", format_vlib_next_node_name, vm,
+               node->index, t->next_index);
+
   s = format (s, "\n%U%U", format_white_space, indent + 2,
              format_mvpp2_rx_desc, d);
+  if (t->dsa_tag.as_u32)
+    s = format (s, "\n%Udsa tag: %U", format_white_space, indent + 2,
+               format_mv_dsa_tag, &t->dsa_tag);
 
   return s;
 }
index 30fef34..4333dbb 100644 (file)
@@ -201,6 +201,7 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
   vnet_dev_rv_t rv = VNET_DEV_OK;
   vnet_dev_bus_platform_device_data_t *dd = vnet_dev_get_bus_data (dev);
   clib_dt_node_t *sc;
+  clib_dt_node_t *sw = 0;
   int pp_id = -1;
 
   if (!clib_dt_node_is_compatible (dd->node, "marvell,armada-7k-pp22"))
@@ -219,12 +220,55 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
   if (pp_id < 0)
     return VNET_DEV_ERR_UNKNOWN_DEVICE;
 
+  foreach_clib_dt_tree_node (n, clib_dt_get_root_node (sc))
+    if (clib_dt_node_is_compatible (n, "marvell,mv88e6190") ||
+       clib_dt_node_is_compatible (n, "marvell,mv88e6393x"))
+      {
+       clib_dt_node_t *ports;
+       sw = n;
+       log_debug (dev, "found mv88e6190 compatible switch at %v", n->path);
+       ports = clib_dt_get_child_node (sw, "ports");
+       foreach_clib_dt_child_node (pn, ports)
+         {
+           u32 reg = CLIB_U32_MAX;
+           char *label = "(no label)";
+           clib_dt_property_t *p;
+           clib_dt_node_t *n;
+
+           p = clib_dt_get_node_property_by_name (pn, "reg");
+           if (p)
+             reg = clib_dt_property_get_u32 (p);
+           p = clib_dt_get_node_property_by_name (pn, "label");
+           if (p)
+             label = clib_dt_property_get_string (p);
+
+           log_debug (dev, "port %u label %s", reg, label);
+
+           n = clib_dt_dereference_node (pn, "phy-handle");
+           if (n)
+             log_debug (dev, "  phy is %v", n->path);
+
+           n = clib_dt_dereference_node (pn, "sfp");
+           if (n)
+             log_debug (dev, "  sfp is %v", n->path);
+
+           n = clib_dt_dereference_node (pn, "ethernet");
+           if (n)
+             log_debug (dev, "  connected to %v", n->path);
+
+           p = clib_dt_get_node_property_by_name (pn, "phy-mode");
+           if (p)
+             log_debug (dev, "  phy mode is %s",
+                        clib_dt_property_get_string (p));
+         }
+      }
+
   if ((mvpp2_global_init (vm, dev)) != VNET_DEV_OK)
     return rv;
 
   md->pp_id = pp_id;
 
-  vec_foreach_pointer (cn, dd->node->child_nodes)
+  foreach_clib_dt_child_node (cn, dd->node)
     {
       clib_dt_property_t *p;
       char netdev_name[IFNAMSIZ];
@@ -271,6 +315,28 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
        .ppio_id = ppio_id,
       };
 
+      if (sw)
+       {
+         clib_dt_node_t *ports = clib_dt_get_child_node (sw, "ports");
+         if (ports)
+           foreach_clib_dt_child_node (sp, ports)
+             {
+               clib_dt_node_t *eth;
+
+               eth = clib_dt_dereference_node (sp, "ethernet");
+
+               if (cn != eth)
+                 continue;
+
+               mvpp2_port.is_dsa = 1;
+               mvpp2_port.switch_node = sw;
+               mvpp2_port.switch_port_node = sp;
+               log_debug (dev, "port is connected to switch port %v",
+                          sp->path);
+               break;
+             }
+       }
+
       vnet_dev_port_add_args_t port_add_args = {
         .port = {
           .attr = {
@@ -278,12 +344,15 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
             .max_rx_queues = PP2_PPIO_MAX_NUM_INQS,
             .max_tx_queues = PP2_PPIO_MAX_NUM_OUTQS,
             .max_supported_rx_frame_size = 9216,
+           .caps.secondary_interfaces = mvpp2_port.is_dsa != 0,
           },
           .ops = {
             .init = mvpp2_port_init,
             .deinit = mvpp2_port_deinit,
             .start = mvpp2_port_start,
             .stop = mvpp2_port_stop,
+           .add_sec_if = mvpp2_port_add_sec_if,
+           .del_sec_if = mvpp2_port_del_sec_if,
             .config_change = mvpp2_port_cfg_change,
             .config_change_validate = mvpp2_port_cfg_change_validate,
             .format_status = format_mvpp2_port_status,
@@ -291,6 +360,10 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
           },
           .data_size = sizeof (mvpp2_port_t),
           .initial_data = &mvpp2_port,
+         .sec_if_args = VNET_DEV_ARGS (
+           VNET_DEV_ARG_UINT32 (MVPP2_SEC_IF_ARG_DSA_SWITCH, "dsa_switch", "DSA source switch ID", .max= 31),
+           VNET_DEV_ARG_UINT32 (MVPP2_SEC_IF_ARG_DSA_PORT, "dsa_port", "DSA source switch port ID", .max = 31)
+         ),
         },
     .rx_node = &mvpp2_rx_node,
     .tx_node = &mvpp2_tx_node,
index 29594f2..63a212e 100644 (file)
@@ -76,6 +76,9 @@ mvpp2_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
 
   log_debug (dev, "port %u %U", port->port_id, format_pp2_ppio_link_info, &li);
 
+  for (u32 i = 0; i < VLIB_FRAME_SIZE; i++)
+    mp->desc_ptrs[i] = mp->descs + i;
+
   mvpp2_port_add_counters (vm, port);
 
 done:
@@ -206,6 +209,68 @@ mvpp2_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
     }
 }
 
+vnet_dev_rv_t
+mvpp2_port_add_sec_if (vlib_main_t *vm, vnet_dev_port_t *port, void *p)
+{
+  vnet_dev_port_interface_t *sif = p;
+  mvpp2_port_t *mp = vnet_dev_get_port_data (port);
+  u32 port_id = CLIB_U32_MAX, switch_id = 0, index;
+
+  if (mp->is_dsa == 0)
+    return VNET_DEV_ERR_NOT_SUPPORTED;
+
+  foreach_vnet_dev_args (a, sif)
+    {
+      switch (a->id)
+       {
+       case MVPP2_SEC_IF_ARG_DSA_PORT:
+         if (a->val_set)
+           port_id = vnet_dev_arg_get_uint32 (a);
+         break;
+       case MVPP2_SEC_IF_ARG_DSA_SWITCH:
+         switch_id = vnet_dev_arg_get_uint32 (a);
+         break;
+       default:
+         break;
+       }
+    }
+
+  if (port_id == CLIB_U32_MAX)
+    {
+      log_err (port->dev, "missing dsa_port argument");
+      return VNET_DEV_ERR_INVALID_ARG;
+    }
+
+  log_debug (port->dev, "switch %u port %u", switch_id, port_id);
+
+  mv_dsa_tag_t tag = {
+    .tag_type = MV_DSA_TAG_TYPE_FROM_CPU,
+    .src_port_or_lag = port_id,
+    .src_dev = switch_id,
+  };
+
+  index = switch_id << 5 | port_id;
+
+  sif->user_data = tag.as_u32;
+  uword_bitmap_set_bits_at_index (mp->valid_dsa_src_bitmap, index, 1);
+  mp->dsa_to_sec_if[index] = sif->index;
+  return VNET_DEV_OK;
+}
+
+vnet_dev_rv_t
+mvpp2_port_del_sec_if (vlib_main_t *vm, vnet_dev_port_t *port, void *p)
+{
+  vnet_dev_port_interface_t *sif = p;
+  mvpp2_port_t *mp = vnet_dev_get_port_data (port);
+  mv_dsa_tag_t tag = { .as_u32 = sif->user_data };
+  u32 index = tag.src_dev << 5 | tag.src_port_or_lag;
+
+  log_debug (port->dev, "switch %u port %u", tag.src_dev, tag.src_port_or_lag);
+
+  uword_bitmap_clear_bits_at_index (mp->valid_dsa_src_bitmap, index, 1);
+  return VNET_DEV_OK;
+}
+
 vnet_dev_rv_t
 mvpp2_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
                                vnet_dev_port_cfg_change_req_t *req)
index 7be3c72..160bfd2 100644 (file)
@@ -8,6 +8,7 @@
 #include <vppinfra/clib.h>
 #include <vppinfra/error_bootstrap.h>
 #include <vppinfra/format.h>
+#include <vppinfra/devicetree.h>
 #include <vnet/vnet.h>
 #include <vnet/dev/dev.h>
 
 #define MVPP2_NUM_BPOOLS       16
 #define MVPP2_MAX_THREADS      4
 #define MRVL_PP2_BUFF_BATCH_SZ 32
+#define MV_DSA_N_SRC          32
+
+#define foreach_mv_dsa_tag_field                                              \
+  _ (12, vid)                                                                 \
+  _ (1, _zero13)                                                              \
+  _ (3, pri)                                                                  \
+  _ (1, cfi_dei)                                                              \
+  _ (1, _unused17)                                                            \
+  _ (1, src_is_lag)                                                           \
+  _ (5, src_port_or_lag)                                                      \
+  _ (5, src_dev)                                                              \
+  _ (1, src_tagged)                                                           \
+  _ (2, tag_type)
+
+typedef enum
+{
+  MV_DSA_TAG_TYPE_TO_CPU = 0,
+  MV_DSA_TAG_TYPE_FROM_CPU = 1,
+  MV_DSA_TAG_TYPE_TO_SNIFFER = 2,
+  MV_DSA_TAG_TYPE_FORWARD = 3
+} mv_dsa_tag_type_t;
+
+typedef enum
+{
+  MVPP2_SEC_IF_ARG_DSA_SWITCH,
+  MVPP2_SEC_IF_ARG_DSA_PORT
+} mvpp2_sec_if_args_t;
+
+typedef union
+{
+  struct
+  {
+#define _(b, n) u32 (n) : (b);
+    foreach_mv_dsa_tag_field
+#undef _
+  };
+  u32 as_u32;
+} mv_dsa_tag_t;
+
+STATIC_ASSERT_SIZEOF (mv_dsa_tag_t, 4);
+
+static_always_inline mv_dsa_tag_t
+mv_dsa_tag_read (void *p)
+{
+  return (mv_dsa_tag_t){ .as_u32 = clib_net_to_host_u32 (*(u32u *) p) };
+}
+
+static_always_inline void
+mv_dsa_tag_write (void *p, mv_dsa_tag_t tag)
+{
+  ((mv_dsa_tag_t *) p)->as_u32 = clib_host_to_net_u32 (tag.as_u32);
+}
 
 typedef struct
 {
@@ -49,6 +102,13 @@ typedef struct
   struct pp2_ppio *ppio;
   u8 ppio_id;
   struct pp2_ppio_link_info last_link_info;
+  clib_dt_node_t *switch_node;
+  clib_dt_node_t *switch_port_node;
+
+  struct pp2_ppio_desc descs[VLIB_FRAME_SIZE];
+  struct pp2_ppio_desc *desc_ptrs[VLIB_FRAME_SIZE];
+  uword valid_dsa_src_bitmap[1024 / uword_bits];
+  u16 dsa_to_sec_if[1024];
 } mvpp2_port_t;
 
 typedef struct
@@ -65,7 +125,9 @@ typedef struct
 typedef struct
 {
   struct pp2_ppio_desc desc;
-  vnet_dev_rx_queue_t *rxq;
+  u32 sw_if_index;
+  u16 next_index;
+  mv_dsa_tag_t dsa_tag;
 } mvpp2_rx_trace_t;
 
 /* counters.c */
@@ -81,12 +143,15 @@ format_function_t format_mvpp2_port_status;
 format_function_t format_mvpp2_dev_info;
 format_function_t format_mvpp2_rx_trace;
 format_function_t format_mvpp2_rx_desc;
+format_function_t format_mv_dsa_tag;
 
 /* port.c */
 vnet_dev_port_op_t mvpp2_port_init;
 vnet_dev_port_op_no_rv_t mvpp2_port_deinit;
 vnet_dev_port_op_t mvpp2_port_start;
 vnet_dev_port_op_no_rv_t mvpp2_port_stop;
+vnet_dev_port_op_with_ptr_t mvpp2_port_add_sec_if;
+vnet_dev_port_op_with_ptr_t mvpp2_port_del_sec_if;
 vnet_dev_rv_t mvpp2_port_cfg_change (vlib_main_t *, vnet_dev_port_t *,
                                     vnet_dev_port_cfg_change_req_t *);
 vnet_dev_rv_t
@@ -135,6 +200,7 @@ typedef enum
      "pp2_bpool_get_num_buffs error")                                         \
   _ (BPOOL_PUT_BUFFS, bpool_put_buffs, ERROR, "pp2_bpool_put_buffs error")    \
   _ (BUFFER_ALLOC, buffer_alloc, ERROR, "buffer alloc error")                 \
+  _ (UNKNOWN_DSA_SRC, unknown_dsa_src, ERROR, "unknown DSA source")           \
   _ (MAC_CE, mac_ce, ERROR, "MAC error (CRC error)")                          \
   _ (MAC_OR, mac_or, ERROR, "overrun error")                                  \
   _ (MAC_RSVD, mac_rsvd, ERROR, "unknown MAC error")                          \
index 81101ef..5b0e8d3 100644 (file)
 #include <vlib/vlib.h>
 #include <vnet/dev/dev.h>
 #include <vnet/ethernet/ethernet.h>
+#include <vppinfra/vector/mask_compare.h>
+#include <vppinfra/vector/compress.h>
 
 #include <dev_armada/pp2/pp2.h>
 
-static_always_inline void
-mvpp2_rx_trace (vlib_main_t *vm, vlib_node_runtime_t *node,
-               vnet_dev_rx_queue_t *rxq, vlib_buffer_t *b0, uword *n_trace,
-               struct pp2_ppio_desc *d)
+static_always_inline vlib_buffer_t *
+desc_to_vlib_buffer (vlib_main_t *vm, struct pp2_ppio_desc *d)
 {
-  if (PREDICT_TRUE (vlib_trace_buffer (vm, node, rxq->next_index, b0,
-                                      /* follow_chain */ 0)))
+  return vlib_get_buffer (vm, pp2_ppio_inq_desc_get_cookie (d));
+}
+
+static_always_inline u64
+mrvl_pp2_rx_one_if (vlib_main_t *vm, vlib_node_runtime_t *node,
+                   vnet_dev_rx_queue_t *rxq,
+                   vnet_dev_rx_queue_if_rt_data_t *if_rt_data,
+                   struct pp2_ppio_desc **desc_ptrs, u32 n_desc,
+                   i32 current_data, i32 len_adj, mv_dsa_tag_t tag)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  u64 n_rx_bytes = 0;
+  vlib_buffer_t *b0, *b1;
+  u32 n_trace, n_left = n_desc;
+  u32 buffer_indices[VLIB_FRAME_SIZE], *bi = buffer_indices;
+  struct pp2_ppio_desc **dp = desc_ptrs;
+  u32 next_index = if_rt_data->next_index;
+  vlib_buffer_template_t bt = if_rt_data->buffer_template;
+  u32 sw_if_index = if_rt_data->sw_if_index;
+
+  bt.current_data = current_data;
+
+  for (; n_left >= 4; dp += 2, bi += 2, n_left -= 2)
     {
-      mvpp2_rx_trace_t *tr;
-      vlib_set_trace_count (vm, node, --(*n_trace));
-      tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
-      tr->desc = *d;
-      tr->rxq = rxq;
+      clib_prefetch_store (desc_to_vlib_buffer (vm, dp[2]));
+      clib_prefetch_store (desc_to_vlib_buffer (vm, dp[3]));
+      b0 = desc_to_vlib_buffer (vm, dp[0]);
+      b1 = desc_to_vlib_buffer (vm, dp[1]);
+      bi[0] = pp2_ppio_inq_desc_get_cookie (dp[0]);
+      bi[1] = pp2_ppio_inq_desc_get_cookie (dp[1]);
+      b0->template = bt;
+      b1->template = bt;
+
+      n_rx_bytes += b0->current_length =
+       pp2_ppio_inq_desc_get_pkt_len (dp[0]) + len_adj;
+      n_rx_bytes += b1->current_length =
+       pp2_ppio_inq_desc_get_pkt_len (dp[1]) + len_adj;
+    }
+
+  for (; n_left; dp++, bi++, n_left--)
+    {
+      b0 = desc_to_vlib_buffer (vm, dp[0]);
+      bi[0] = pp2_ppio_inq_desc_get_cookie (dp[0]);
+      b0->template = bt;
+
+      n_rx_bytes += b0->current_length =
+       pp2_ppio_inq_desc_get_pkt_len (dp[0]) + len_adj;
     }
+
+  /* trace */
+  n_trace = vlib_get_trace_count (vm, node);
+  if (PREDICT_FALSE (n_trace > 0))
+    {
+      for (u32 i = 0; i < n_desc && n_trace > 0; i++)
+       {
+         vlib_buffer_t *b = desc_to_vlib_buffer (vm, desc_ptrs[i]);
+         if (PREDICT_TRUE (vlib_trace_buffer (vm, node, next_index, b,
+                                              /* follow_chain */ 0)))
+           {
+             mvpp2_rx_trace_t *tr;
+             tr = vlib_add_trace (vm, node, b, sizeof (*tr));
+             tr->desc = *desc_ptrs[i];
+             tr->next_index = next_index;
+             tr->sw_if_index = sw_if_index;
+             tr->dsa_tag = tag;
+             n_trace--;
+           }
+       }
+      vlib_set_trace_count (vm, node, n_trace);
+    }
+  vlib_buffer_enqueue_to_single_next (vm, node, buffer_indices, next_index,
+                                     n_desc);
+
+  vlib_increment_combined_counter (
+    vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
+    vm->thread_index, sw_if_index, n_desc, n_rx_bytes);
+
+  return n_rx_bytes;
 }
 
 static_always_inline uword
 mrvl_pp2_rx_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
                    vlib_frame_t *frame, vnet_dev_rx_queue_t *rxq)
 {
-  vnet_main_t *vnm = vnet_get_main ();
   vnet_dev_port_t *port = rxq->port;
-  vnet_dev_t *dev = port->dev;
-  mvpp2_device_t *md = vnet_dev_get_data (dev);
   mvpp2_port_t *mp = vnet_dev_get_port_data (port);
-  vlib_buffer_template_t bt = rxq->buffer_template;
-  u32 thread_index = vm->thread_index;
-  uword n_trace = vlib_get_trace_count (vm, node);
-  u32 next_index = rxq->next_index;
-  u32 n_rx_packets = 0, n_rx_bytes = 0;
-  struct pp2_hif *hif = md->hif[thread_index];
-  struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d;
-  struct pp2_bpool *bpool = md->thread[thread_index].bpool;
-  struct buff_release_entry *bre = md->thread[thread_index].bre;
+  mv_dsa_tag_t dsa_tags[VLIB_FRAME_SIZE];
   u16 n_desc = VLIB_FRAME_SIZE;
-  u32 buffers[VLIB_FRAME_SIZE];
-  u32 n_bufs, *bi, i;
-  vlib_buffer_t *b0, *b1;
+  vlib_buffer_t *b;
+  u32 i;
 
   if (PREDICT_FALSE (
-       pp2_ppio_recv (mp->ppio, 0, rxq->queue_id, descs, &n_desc)))
+       pp2_ppio_recv (mp->ppio, 0, rxq->queue_id, mp->descs, &n_desc)))
     {
       vlib_error_count (vm, node->node_index, MVPP2_RX_NODE_CTR_PPIO_RECV, 1);
-      n_desc = 0;
+      return 0;
     }
 
-  n_rx_packets = n_desc;
+  if (mp->is_dsa)
+    {
+      for (i = 0; i < n_desc; i++)
+       {
+         b = desc_to_vlib_buffer (vm, mp->descs + i);
+         u8 *start = b->data;
+         mv_dsa_tag_t tag = mv_dsa_tag_read (start + 14);
+         dsa_tags[i] = tag;
+         clib_memmove (start + 6, start + 2, 12);
+       }
 
-  for (i = 0; i < n_desc; i++)
-    buffers[i] = pp2_ppio_inq_desc_get_cookie (descs + i);
+      vlib_frame_bitmap_t avail_bmp = {};
+      vlib_frame_bitmap_init (avail_bmp, n_desc);
+      u32 n_avail = n_desc;
 
-  bt.current_data = 2;
+      while (n_avail)
+       {
+         vlib_frame_bitmap_t selected_bmp = {};
+         struct pp2_ppio_desc *sel_descs[VLIB_FRAME_SIZE];
+         mv_dsa_tag_t tag;
+         u32 n_sel, index;
 
-  for (d = descs, bi = buffers; n_desc >= 4; d += 2, bi += 2, n_desc -= 2)
-    {
-      /* prefetch */
-      b0 = vlib_get_buffer (vm, bi[0]);
-      b1 = vlib_get_buffer (vm, bi[1]);
-      b0->template = bt;
-      b1->template = bt;
+         tag = dsa_tags[vlib_frame_bitmap_find_first_set (avail_bmp)];
+         index = tag.src_dev << 5 | tag.src_port_or_lag;
 
-      n_rx_bytes += b0->current_length = pp2_ppio_inq_desc_get_pkt_len (d);
-      n_rx_bytes += b1->current_length = pp2_ppio_inq_desc_get_pkt_len (d + 1);
+         clib_mask_compare_u32 (tag.as_u32, (u32 *) dsa_tags, selected_bmp,
+                                n_desc);
+         n_sel = vlib_frame_bitmap_count_set_bits (selected_bmp);
+         n_avail -= n_sel;
 
-      if (PREDICT_FALSE (n_trace > 0))
-       {
-         mvpp2_rx_trace (vm, node, rxq, b0, &n_trace, d);
-         if (n_trace > 0)
-           mvpp2_rx_trace (vm, node, rxq, b1, &n_trace, d + 1);
-       }
-    }
+         if (uword_bitmap_is_bit_set (mp->valid_dsa_src_bitmap, index))
+           {
+             clib_compress_u64 ((uword *) sel_descs, (uword *) mp->desc_ptrs,
+                                selected_bmp, n_desc);
+             mrvl_pp2_rx_one_if (vm, node, rxq,
+                                 vnet_dev_get_rx_queue_sec_if_rt_data (
+                                   rxq, mp->dsa_to_sec_if[index]),
+                                 sel_descs, n_sel, 6, -4, tag);
+           }
+         else
+           {
+             u32 n_free = 0, buffer_indices[VLIB_FRAME_SIZE];
 
-  for (; n_desc; d++, bi++, n_desc--)
-    {
-      b0 = vlib_get_buffer (vm, bi[0]);
-      b0->template = bt;
+             foreach_vlib_frame_bitmap_set_bit_index (i, selected_bmp)
+               buffer_indices[n_free++] =
+                 pp2_ppio_inq_desc_get_cookie (mp->descs + i);
 
-      n_rx_bytes += b0->current_length = pp2_ppio_inq_desc_get_pkt_len (d);
+             u32 n_trace = vlib_get_trace_count (vm, node);
+             if (PREDICT_FALSE (n_trace > 0))
+               {
+                 foreach_vlib_frame_bitmap_set_bit_index (i, selected_bmp)
+                   {
+                     vlib_buffer_t *b =
+                       desc_to_vlib_buffer (vm, mp->descs + i);
 
-      if (PREDICT_FALSE (n_trace > 0))
-       mvpp2_rx_trace (vm, node, rxq, b0, &n_trace, d);
+                     if (PREDICT_TRUE (vlib_trace_buffer (
+                           vm, node, VNET_DEV_ETH_RX_PORT_NEXT_DROP, b,
+                           /* follow_chain */ 0)))
+                       {
+                         mvpp2_rx_trace_t *tr;
+                         tr = vlib_add_trace (vm, node, b, sizeof (*tr));
+                         tr->desc = mp->descs[i];
+                         tr->next_index = VNET_DEV_ETH_RX_PORT_NEXT_DROP;
+                         tr->sw_if_index = CLIB_U32_MAX;
+                         tr->dsa_tag = dsa_tags[i];
+                         n_trace--;
+                       }
+                     if (n_trace == 0)
+                       break;
+                   }
+                 vlib_set_trace_count (vm, node, n_trace);
+               }
+
+             vlib_buffer_free (vm, buffer_indices, n_free);
+             vlib_error_count (vm, node->node_index,
+                               MVPP2_RX_NODE_CTR_UNKNOWN_DSA_SRC, 1);
+           }
+       }
+    }
+  else
+    {
+      mrvl_pp2_rx_one_if (vm, node, rxq,
+                         vnet_dev_get_rx_queue_if_rt_data (rxq),
+                         mp->desc_ptrs, n_desc, 2, 0, (mv_dsa_tag_t){});
     }
 
-  vlib_buffer_enqueue_to_single_next (vm, node, buffers, next_index,
-                                     n_rx_packets);
+  return n_desc;
+}
 
-  vlib_increment_combined_counter (
-    vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
-    thread_index, port->intf.sw_if_index, n_rx_packets, n_rx_bytes);
+static_always_inline void
+mrvl_pp2_rx_refill (vlib_main_t *vm, vlib_node_runtime_t *node,
+                   vnet_dev_rx_queue_t *rxq)
+{
+  vnet_dev_port_t *port = rxq->port;
+  vnet_dev_t *dev = port->dev;
+  mvpp2_device_t *md = vnet_dev_get_data (dev);
+  u32 thread_index = vm->thread_index;
+  struct pp2_hif *hif = md->hif[thread_index];
+  struct pp2_bpool *bpool = md->thread[thread_index].bpool;
+  struct buff_release_entry *bre = md->thread[thread_index].bre;
+  u32 n_bufs, *bi;
 
   if (PREDICT_FALSE (pp2_bpool_get_num_buffs (bpool, &n_bufs)))
     {
       vlib_error_count (vm, node->node_index,
                        MVPP2_RX_NODE_CTR_BPOOL_GET_NUM_BUFFS, 1);
-      goto done;
+      return;
     }
 
   n_bufs = rxq->size - n_bufs;
@@ -110,18 +225,18 @@ mrvl_pp2_rx_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
     {
       u16 n_alloc, i;
       struct buff_release_entry *e = bre;
+      u32 buffer_indices[MRVL_PP2_BUFF_BATCH_SZ];
 
-      n_alloc = vlib_buffer_alloc (vm, buffers, MRVL_PP2_BUFF_BATCH_SZ);
-      i = n_alloc;
+      n_alloc = vlib_buffer_alloc (vm, buffer_indices, MRVL_PP2_BUFF_BATCH_SZ);
 
       if (PREDICT_FALSE (n_alloc == 0))
        {
          vlib_error_count (vm, node->node_index,
                            MVPP2_RX_NODE_CTR_BUFFER_ALLOC, 1);
-         goto done;
+         return;
        }
 
-      for (bi = buffers; i--; e++, bi++)
+      for (i = n_alloc, bi = buffer_indices; i--; e++, bi++)
        {
 
          vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
@@ -129,23 +244,16 @@ mrvl_pp2_rx_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
          e->buff.cookie = bi[0];
        }
 
-      i = n_alloc;
-      if (PREDICT_FALSE (pp2_bpool_put_buffs (hif, bre, &i)))
+      if (PREDICT_FALSE (pp2_bpool_put_buffs (hif, bre, &n_alloc)))
        {
          vlib_error_count (vm, node->node_index,
                            MVPP2_RX_NODE_CTR_BPOOL_PUT_BUFFS, 1);
-         vlib_buffer_free (vm, buffers, n_alloc);
-         goto done;
+         vlib_buffer_free (vm, buffer_indices, n_alloc);
+         return;
        }
 
-      if (PREDICT_FALSE (i != n_alloc))
-       vlib_buffer_free (vm, buffers + i, n_alloc - i);
-
-      n_bufs -= i;
+      n_bufs -= n_alloc;
     }
-
-done:
-  return n_rx_packets;
 }
 
 VNET_DEV_NODE_FN (mvpp2_rx_node)
@@ -153,6 +261,9 @@ VNET_DEV_NODE_FN (mvpp2_rx_node)
 {
   u32 n_rx = 0;
   foreach_vnet_dev_rx_queue_runtime (rxq, node)
-    n_rx += mrvl_pp2_rx_inline (vm, node, frame, rxq);
+    {
+      n_rx += mrvl_pp2_rx_inline (vm, node, frame, rxq);
+      mrvl_pp2_rx_refill (vm, node, rxq);
+    }
   return n_rx;
 }
index 1e6675c..583eec7 100644 (file)
@@ -12,6 +12,7 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
 {
   vnet_dev_tx_node_runtime_t *rt = vnet_dev_get_tx_node_runtime (node);
+  vnet_dev_instance_t *ins = vnet_dev_get_dev_instance (rt->dev_instance);
   vnet_dev_tx_queue_t *txq = rt->tx_queue;
   vnet_dev_port_t *port = txq->port;
   vnet_dev_t *dev = port->dev;
@@ -27,6 +28,24 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
   struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d = descs;
   u16 sz = txq->size;
   u16 mask = sz - 1;
+  i16 len_adj = 0;
+
+  if (ins->is_primary_if == 0)
+    {
+      vnet_dev_port_interface_t *sif =
+       vnet_dev_port_get_sec_if_by_index (port, ins->sec_if_index);
+
+      mv_dsa_tag_t tag = { .as_u32 = sif->user_data };
+
+      for (u32 i = 0; i < n_vectors; i++)
+       {
+         vlib_buffer_t *b = vlib_get_buffer (vm, buffers[i]);
+         u8 *start = vlib_buffer_get_current (b);
+         clib_memmove (start - 4, start, 12);
+         mv_dsa_tag_write (start + 8, tag);
+       }
+      len_adj = 4;
+    }
 
   if (mtq->n_enq)
     {
@@ -51,9 +70,9 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
       u64 paddr = vlib_buffer_get_pa (vm, b0);
 
       pp2_ppio_outq_desc_reset (d);
-      pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data);
+      pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data - len_adj);
       pp2_ppio_outq_desc_set_pkt_offset (d, 0);
-      pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length);
+      pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length + len_adj);
     }
 
   buffers = vlib_frame_vector_args (frame);