[3/3] common/cnxk: add egress mirror support
Checks
Commit Message
From: Satha Rao <skoteshwar@marvell.com>
Added ROC api to send packets on multiple links when egress mirror
enabled.
Signed-off-by: Satha Rao <skoteshwar@marvell.com>
Reviewed-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
Reviewed-by: Satheesh Paul <psatheesh@marvell.com>
---
drivers/common/cnxk/roc_nix.h | 2 +
drivers/common/cnxk/roc_nix_tm_ops.c | 70 ++++++++++++++++++++++++++++
drivers/common/cnxk/roc_npc.c | 26 +++++++++++
drivers/common/cnxk/version.map | 1 +
4 files changed, 99 insertions(+)
@@ -755,6 +755,8 @@ int __roc_api roc_nix_tm_mark_config(struct roc_nix *roc_nix,
int mark_red);
uint64_t __roc_api roc_nix_tm_mark_format_get(struct roc_nix *roc_nix,
uint64_t *flags);
+int __roc_api roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func,
+ bool enable);
/* Ingress Policer API */
int __roc_api roc_nix_bpf_timeunit_get(struct roc_nix *roc_nix,
@@ -1316,3 +1316,73 @@ roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
return false;
return true;
}
+
+static inline struct nix *
+pf_func_to_nix_get(uint16_t pf_func)
+{
+ struct roc_nix *roc_nix_tmp = NULL;
+ struct roc_nix_list *nix_list;
+
+ nix_list = roc_idev_nix_list_get();
+ if (nix_list == NULL)
+ return NULL;
+
+ /* Find the NIX of given pf_func */
+ TAILQ_FOREACH(roc_nix_tmp, nix_list, next) {
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix_tmp);
+
+ if (nix->dev.pf_func == pf_func)
+ return nix;
+ }
+
+ return NULL;
+}
+
+int
+roc_nix_tm_egress_link_cfg_set(struct roc_nix *roc_nix, uint64_t dst_pf_func, bool enable)
+{
+ struct nix *src_nix = roc_nix_to_nix_priv(roc_nix), *dst_nix;
+ struct mbox *mbox = (&src_nix->dev)->mbox;
+ struct nix_txschq_config *req = NULL;
+ struct nix_tm_node_list *list;
+ struct nix_tm_node *node;
+ int rc = 0, k;
+
+ dst_nix = pf_func_to_nix_get(dst_pf_func);
+ if (!dst_nix)
+ return -EINVAL;
+
+ if (dst_nix == src_nix)
+ return 0;
+
+ list = nix_tm_node_list(src_nix, src_nix->tm_tree);
+ TAILQ_FOREACH(node, list, node) {
+ if (node->hw_lvl != src_nix->tm_link_cfg_lvl)
+ continue;
+
+ if (!(node->flags & NIX_TM_NODE_HWRES))
+ continue;
+
+ /* Allocating TL3 request */
+ req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
+ req->lvl = src_nix->tm_link_cfg_lvl;
+ k = 0;
+
+ /* Enable PFC/pause on the identified TL3 */
+ req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, dst_nix->tx_link);
+ if (enable)
+ req->regval[k] |= BIT_ULL(12);
+ else
+ req->regval[k] &= ~(BIT_ULL(12));
+ req->regval_mask[k] = ~(BIT_ULL(12));
+ k++;
+
+ req->num_regs = k;
+ rc = mbox_process(mbox);
+ mbox_put(mbox);
+ if (rc)
+ goto err;
+ }
+err:
+ return rc;
+}
@@ -1595,6 +1595,21 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
goto err_exit;
}
+ /* If Egress mirror requested then enable TL3_TL2_LINK_CFG */
+ if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+ if (flow->mcast_pf_funcs[0] == npc->pf_func)
+ rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+ flow->mcast_pf_funcs[1], true);
+ else
+ rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+ flow->mcast_pf_funcs[0], true);
+ if (rc) {
+ plt_err("Adding egress mirror failed");
+ *errcode = rc;
+ goto err_exit;
+ }
+ }
+
rc = npc_rss_action_program(roc_npc, actions, flow);
if (rc != 0) {
*errcode = rc;
@@ -1706,6 +1721,17 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
return rc;
}
+ /* Disable egress mirror rule */
+ if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
+ if (flow->mcast_pf_funcs[0] == npc->pf_func)
+ rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+ flow->mcast_pf_funcs[1], false);
+ else
+ rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
+ flow->mcast_pf_funcs[0], false);
+ if (rc)
+ plt_err("Failed to remove egress mirror rule");
+ }
if (flow->is_sampling_rule)
roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
@@ -355,6 +355,7 @@ INTERNAL {
roc_nix_switch_hdr_set;
roc_nix_eeprom_info_get;
roc_nix_smq_flush;
+ roc_nix_tm_egress_link_cfg_set;
roc_nix_tm_dump;
roc_nix_tm_err_to_rte_err;
roc_nix_tm_fini;