diff options
-rw-r--r-- | src/plugins/dev_armada/pp2/format.c | 30 | ||||
-rw-r--r-- | src/plugins/dev_armada/pp2/init.c | 75 | ||||
-rw-r--r-- | src/plugins/dev_armada/pp2/port.c | 65 | ||||
-rw-r--r-- | src/plugins/dev_armada/pp2/pp2.h | 68 | ||||
-rw-r--r-- | src/plugins/dev_armada/pp2/rx.c | 265 | ||||
-rw-r--r-- | src/plugins/dev_armada/pp2/tx.c | 23 |
6 files changed, 441 insertions, 85 deletions
diff --git a/src/plugins/dev_armada/pp2/format.c b/src/plugins/dev_armada/pp2/format.c index 37d482b5ce8..42c4114c512 100644 --- a/src/plugins/dev_armada/pp2/format.c +++ b/src/plugins/dev_armada/pp2/format.c @@ -152,25 +152,47 @@ 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) { vlib_main_t *vm = va_arg (*args, vlib_main_t *); 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; } diff --git a/src/plugins/dev_armada/pp2/init.c b/src/plugins/dev_armada/pp2/init.c index 30fef34cd39..4333dbb352f 100644 --- a/src/plugins/dev_armada/pp2/init.c +++ b/src/plugins/dev_armada/pp2/init.c @@ -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, diff --git a/src/plugins/dev_armada/pp2/port.c b/src/plugins/dev_armada/pp2/port.c index 29594f2a84d..63a212e80c2 100644 --- a/src/plugins/dev_armada/pp2/port.c +++ b/src/plugins/dev_armada/pp2/port.c @@ -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: @@ -207,6 +210,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) { diff --git a/src/plugins/dev_armada/pp2/pp2.h b/src/plugins/dev_armada/pp2/pp2.h index 7be3c721bec..160bfd20c5c 100644 --- a/src/plugins/dev_armada/pp2/pp2.h +++ b/src/plugins/dev_armada/pp2/pp2.h @@ -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> @@ -29,6 +30,58 @@ #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") \ diff --git a/src/plugins/dev_armada/pp2/rx.c b/src/plugins/dev_armada/pp2/rx.c index 81101ef9313..5b0e8d35000 100644 --- a/src/plugins/dev_armada/pp2/rx.c +++ b/src/plugins/dev_armada/pp2/rx.c @@ -5,104 +5,219 @@ #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; } diff --git a/src/plugins/dev_armada/pp2/tx.c b/src/plugins/dev_armada/pp2/tx.c index 1e6675c9746..583eec71d60 100644 --- a/src/plugins/dev_armada/pp2/tx.c +++ b/src/plugins/dev_armada/pp2/tx.c @@ -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); |