@@ -20,6 +20,7 @@ sources = files(
'roc_cpt_debug.c',
'roc_dev.c',
'roc_dpi.c',
+ 'roc_eswitch.c',
'roc_hash.c',
'roc_idev.c',
'roc_irq.c',
@@ -117,4 +117,7 @@
/* MACsec */
#include "roc_mcs.h"
+/* Eswitch */
+#include "roc_eswitch.h"
+
#endif /* _ROC_API_H_ */
new file mode 100644
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#include <arpa/inet.h>
+
+#include "roc_api.h"
+#include "roc_priv.h"
+
+static int
+eswitch_vlan_rx_cfg(uint16_t pcifunc, struct mbox *mbox)
+{
+ struct nix_vtag_config *vtag_cfg;
+ int rc;
+
+ vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox_get(mbox));
+ if (!vtag_cfg) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* config strip, capture and size */
+ vtag_cfg->hdr.pcifunc = pcifunc;
+ vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
+ vtag_cfg->cfg_type = VTAG_RX; /* rx vlan cfg */
+ vtag_cfg->rx.vtag_type = NIX_RX_VTAG_TYPE0;
+ vtag_cfg->rx.strip_vtag = true;
+ vtag_cfg->rx.capture_vtag = true;
+
+ rc = mbox_process(mbox);
+ if (rc)
+ goto exit;
+
+ rc = 0;
+exit:
+ mbox_put(mbox);
+ return rc;
+}
+
+static int
+eswitch_vlan_tx_cfg(struct roc_npc_flow *flow, uint16_t pcifunc, struct mbox *mbox,
+ uint16_t vlan_tci, uint16_t *vidx)
+{
+ struct nix_vtag_config *vtag_cfg;
+ struct nix_vtag_config_rsp *rsp;
+ int rc;
+
+ union {
+ uint64_t reg;
+ struct nix_tx_vtag_action_s act;
+ } tx_vtag_action;
+
+ vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox_get(mbox));
+ if (!vtag_cfg) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Insert vlan tag */
+ vtag_cfg->hdr.pcifunc = pcifunc;
+ vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
+ vtag_cfg->cfg_type = VTAG_TX; /* tx vlan cfg */
+ vtag_cfg->tx.cfg_vtag0 = true;
+ vtag_cfg->tx.vtag0 = (((uint32_t)ROC_ESWITCH_VLAN_TPID << 16) | vlan_tci);
+
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto exit;
+
+ if (rsp->vtag0_idx < 0) {
+ plt_err("Failed to config TX VTAG action");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ *vidx = rsp->vtag0_idx;
+ tx_vtag_action.reg = 0;
+ tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
+ tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
+ tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
+ tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR;
+
+ flow->vtag_action = tx_vtag_action.reg;
+
+ rc = 0;
+exit:
+ mbox_put(mbox);
+ return rc;
+}
+
+int
+roc_eswitch_npc_mcam_tx_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow, uint16_t pcifunc,
+ uint32_t vlan_tci)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+ struct npc_install_flow_req *req;
+ struct npc_install_flow_rsp *rsp;
+ struct mbox *mbox = npc->mbox;
+ uint16_t vidx = 0, lbkid;
+ int rc;
+
+ rc = eswitch_vlan_tx_cfg(flow, roc_npc->pf_func, mbox, vlan_tci, &vidx);
+ if (rc) {
+ plt_err("Failed to configure VLAN TX, err %d", rc);
+ goto fail;
+ }
+
+ req = mbox_alloc_msg_npc_install_flow(mbox_get(mbox));
+ if (!req) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ lbkid = 0;
+ req->hdr.pcifunc = roc_npc->pf_func; /* Eswitch PF is requester */
+ req->vf = pcifunc;
+ req->entry = flow->mcam_id;
+ req->intf = NPC_MCAM_TX;
+ req->op = NIX_TX_ACTIONOP_UCAST_CHAN;
+ req->index = (lbkid << 8) | ROC_ESWITCH_LBK_CHAN;
+ req->set_cntr = 1;
+ req->vtag0_def = vidx;
+ req->vtag0_op = 1;
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto exit;
+
+ flow->nix_intf = NIX_INTF_TX;
+exit:
+ mbox_put(mbox);
+fail:
+ return rc;
+}
+
+static int
+eswitch_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+ struct nix_vtag_config *vtag_cfg;
+ struct nix_vtag_config_rsp *rsp;
+ struct mbox *mbox = npc->mbox;
+ int rc = 0;
+
+ union {
+ uint64_t reg;
+ struct nix_tx_vtag_action_s act;
+ } tx_vtag_action;
+
+ tx_vtag_action.reg = flow->vtag_action;
+ vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox_get(mbox));
+
+ if (vtag_cfg == NULL) {
+ rc = -ENOSPC;
+ goto exit;
+ }
+
+ vtag_cfg->cfg_type = VTAG_TX;
+ vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
+ vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def;
+ vtag_cfg->tx.free_vtag0 = true;
+
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto exit;
+
+ rc = rsp->hdr.rc;
+exit:
+ mbox_put(mbox);
+ return rc;
+}
+
+int
+roc_eswitch_npc_mcam_delete_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+ uint16_t pcifunc)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+ struct npc_delete_flow_req *req;
+ struct msg_rsp *rsp;
+ struct mbox *mbox = npc->mbox;
+ int rc = 0;
+
+ /* Removing the VLAN TX config */
+ if (flow->nix_intf == NIX_INTF_TX) {
+ rc = eswitch_vtag_cfg_delete(roc_npc, flow);
+ if (rc)
+ plt_err("Failed to delete TX vtag config");
+ }
+
+ req = mbox_alloc_msg_npc_delete_flow(mbox_get(mbox));
+ if (!req) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ req->entry = flow->mcam_id;
+ req->vf = pcifunc;
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto exit;
+
+ rc = rsp->hdr.rc;
+exit:
+ mbox_put(mbox);
+ return rc;
+}
+
+int
+roc_eswitch_npc_mcam_rx_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow, uint16_t pcifunc,
+ uint16_t vlan_tci, uint16_t vlan_tci_mask)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+ struct npc_install_flow_req *req;
+ struct npc_install_flow_rsp *rsp;
+ struct mbox *mbox = npc->mbox;
+ bool is_esw_dev;
+ int rc;
+
+ /* For ESW PF/VF */
+ is_esw_dev = (dev_get_pf(roc_npc->pf_func) == dev_get_pf(pcifunc));
+ /* VLAN Rx config */
+ if (is_esw_dev) {
+ rc = eswitch_vlan_rx_cfg(roc_npc->pf_func, mbox);
+ if (rc) {
+ plt_err("Failed to configure VLAN RX rule, err %d", rc);
+ goto fail;
+ }
+ }
+
+ req = mbox_alloc_msg_npc_install_flow(mbox_get(mbox));
+ if (!req) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ req->vf = pcifunc;
+ /* Action */
+ req->op = NIX_RX_ACTIONOP_DEFAULT;
+ req->index = 0;
+ req->entry = flow->mcam_id;
+ req->hdr.pcifunc = roc_npc->pf_func; /* Eswitch PF is requester */
+ req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_VLAN_ETYPE_CTAG);
+ req->vtag0_valid = true;
+ /* For ESW PF/VF using configured vlan rx cfg while for other
+ * representees using standard vlan_type = 7 which is strip.
+ */
+ req->vtag0_type = is_esw_dev ? NIX_RX_VTAG_TYPE0 : NIX_RX_VTAG_TYPE7;
+ req->packet.vlan_etype = ROC_ESWITCH_VLAN_TPID;
+ req->mask.vlan_etype = 0xFFFF;
+ req->packet.vlan_tci = ntohs(vlan_tci & 0xFFFF);
+ req->mask.vlan_tci = ntohs(vlan_tci_mask);
+
+ req->channel = ROC_ESWITCH_LBK_CHAN;
+ req->chan_mask = 0xffff;
+ req->intf = NPC_MCAM_RX;
+ req->set_cntr = 1;
+ req->cntr_val = flow->ctr_id;
+
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto exit;
+
+ flow->nix_intf = NIX_INTF_RX;
+exit:
+ mbox_put(mbox);
+fail:
+ return rc;
+}
+
+int
+roc_eswitch_npc_rss_action_configure(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+ uint32_t flowkey_cfg, uint16_t *reta_tbl)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+ struct roc_nix *roc_nix = roc_npc->roc_nix;
+ uint32_t rss_grp_idx;
+ uint8_t flowkey_algx;
+ int rc;
+
+ rc = npc_rss_free_grp_get(npc, &rss_grp_idx);
+ /* RSS group :0 is not usable for flow rss action */
+ if (rc < 0 || rss_grp_idx == 0)
+ return -ENOSPC;
+
+ /* Populating reta table for the specific RSS group */
+ rc = roc_nix_rss_reta_set(roc_nix, rss_grp_idx, reta_tbl);
+ if (rc) {
+ plt_err("Failed to init rss table rc = %d", rc);
+ return rc;
+ }
+
+ rc = roc_nix_rss_flowkey_set(roc_nix, &flowkey_algx, flowkey_cfg, rss_grp_idx,
+ flow->mcam_id);
+ if (rc) {
+ plt_err("Failed to set rss hash function rc = %d", rc);
+ return rc;
+ }
+
+ plt_bitmap_set(npc->rss_grp_entries, rss_grp_idx);
+
+ flow->npc_action &= (~(0xfULL));
+ flow->npc_action |= NIX_RX_ACTIONOP_RSS;
+ flow->npc_action |=
+ ((uint64_t)(flowkey_algx & NPC_RSS_ACT_ALG_MASK) << NPC_RSS_ACT_ALG_OFFSET) |
+ ((uint64_t)(rss_grp_idx & NPC_RSS_ACT_GRP_MASK) << NPC_RSS_ACT_GRP_OFFSET);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#ifndef __ROC_ESWITCH_H__
+#define __ROC_ESWITCH_H__
+
+#define ROC_ESWITCH_VLAN_TPID 0x8100
+#define ROC_ESWITCH_LBK_CHAN 63
+
+/* NPC */
+int __roc_api roc_eswitch_npc_mcam_rx_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+ uint16_t pcifunc, uint16_t vlan_tci,
+ uint16_t vlan_tci_mask);
+int __roc_api roc_eswitch_npc_mcam_tx_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+ uint16_t pcifunc, uint32_t vlan_tci);
+int __roc_api roc_eswitch_npc_mcam_delete_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+ uint16_t pcifunc);
+int __roc_api roc_eswitch_npc_rss_action_configure(struct roc_npc *roc_npc,
+ struct roc_npc_flow *flow, uint32_t flowkey_cfg,
+ uint16_t *reta_tbl);
+#endif /* __ROC_ESWITCH_H__ */
@@ -388,6 +388,18 @@ enum rvu_af_status {
RVU_INVALID_VF_ID = -256,
};
+/* For NIX RX vtag action */
+enum nix_rx_vtag0_type {
+ NIX_RX_VTAG_TYPE0,
+ NIX_RX_VTAG_TYPE1,
+ NIX_RX_VTAG_TYPE2,
+ NIX_RX_VTAG_TYPE3,
+ NIX_RX_VTAG_TYPE4,
+ NIX_RX_VTAG_TYPE5,
+ NIX_RX_VTAG_TYPE6,
+ NIX_RX_VTAG_TYPE7,
+};
+
struct ready_msg_rsp {
struct mbox_msghdr hdr;
uint16_t __io sclk_freq; /* SCLK frequency */
@@ -2446,6 +2458,8 @@ enum header_fields {
NPC_DMAC,
NPC_SMAC,
NPC_ETYPE,
+ NPC_VLAN_ETYPE_CTAG, /* 0x8100 */
+ NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
NPC_OUTER_VID,
NPC_TOS,
NPC_SIP_IPV4,
@@ -2474,12 +2488,27 @@ struct flow_msg {
uint32_t __io ip4dst;
uint32_t __io ip6dst[4];
};
+ union {
+ uint32_t spi;
+ };
uint8_t __io tos;
uint8_t __io ip_ver;
uint8_t __io ip_proto;
uint8_t __io tc;
uint16_t __io sport;
uint16_t __io dport;
+ union {
+ uint8_t __io ip_flag;
+ uint8_t __io next_header;
+ };
+ uint16_t __io vlan_itci;
+ uint8_t __io icmp_type;
+ uint8_t __io icmp_code;
+ uint16_t __io tcp_flags;
+ uint32_t __io gtpu_teid;
+ uint32_t __io gtpc_teid;
+ uint32_t __io mpls_lse[4];
+ uint16_t __io sq_id;
};
struct npc_install_flow_req {
@@ -2489,6 +2518,7 @@ struct npc_install_flow_req {
uint64_t __io features;
uint16_t __io entry;
uint16_t __io channel;
+ uint16_t __io chan_mask;
uint8_t __io intf;
uint8_t __io set_cntr;
uint8_t __io default_rule;
@@ -2511,6 +2541,8 @@ struct npc_install_flow_req {
uint8_t __io vtag0_op;
uint16_t __io vtag1_def;
uint8_t __io vtag1_op;
+ /* old counter value */
+ uint16_t __io cntr_val;
};
struct npc_install_flow_rsp {
@@ -2525,6 +2557,7 @@ struct npc_delete_flow_req {
uint16_t __io start; /*Disable range of entries */
uint16_t __io end;
uint8_t __io all; /* PF + VFs */
+ uint16_t __io vf; /* Requesting VF */
};
struct npc_mcam_read_entry_req {
@@ -77,8 +77,23 @@ roc_npc_inl_mcam_clear_counter(uint32_t ctr_id)
}
int
-roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id,
- uint64_t *count)
+roc_npc_mcam_alloc_counter(struct roc_npc *roc_npc, uint16_t *ctr_id)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+ return npc_mcam_alloc_counter(npc->mbox, ctr_id);
+}
+
+int
+roc_npc_get_free_mcam_entry(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
+{
+ struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+ return npc_get_free_mcam_entry(npc->mbox, flow, npc);
+}
+
+int
+roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *count)
{
struct npc *npc = roc_npc_to_npc_priv(roc_npc);
@@ -157,14 +172,13 @@ roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc)
}
int
-roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry,
- int *alloc_entry, int req_count, int priority,
- int *resp_count)
+roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, int *alloc_entry, int req_count,
+ int priority, int *resp_count, bool is_conti)
{
struct npc *npc = roc_npc_to_npc_priv(roc_npc);
return npc_mcam_alloc_entries(npc->mbox, ref_entry, alloc_entry, req_count, priority,
- resp_count, 0);
+ resp_count, is_conti);
}
int
@@ -431,7 +431,8 @@ int __roc_api roc_npc_mcam_enable_all_entries(struct roc_npc *roc_npc, bool enab
int __roc_api roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
struct roc_npc_flow *ref_mcam, int prio, int *resp_count);
int __roc_api roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, int *alloc_entry,
- int req_count, int priority, int *resp_count);
+ int req_count, int priority, int *resp_count,
+ bool is_conti);
int __roc_api roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
bool enable);
int __roc_api roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam);
@@ -442,6 +443,8 @@ int __roc_api roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc);
int __roc_api roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id);
int __roc_api roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *count);
int __roc_api roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id);
+int __roc_api roc_npc_mcam_alloc_counter(struct roc_npc *roc_npc, uint16_t *ctr_id);
+int __roc_api roc_npc_get_free_mcam_entry(struct roc_npc *roc_npc, struct roc_npc_flow *flow);
int __roc_api roc_npc_inl_mcam_read_counter(uint32_t ctr_id, uint64_t *count);
int __roc_api roc_npc_inl_mcam_clear_counter(uint32_t ctr_id);
int __roc_api roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc);
@@ -4,7 +4,7 @@
#include "roc_api.h"
#include "roc_priv.h"
-static int
+int
npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
{
struct npc_mcam_alloc_counter_req *req;
@@ -432,6 +432,7 @@ roc_npc_to_npc_priv(struct roc_npc *npc)
return (struct npc *)npc->reserved;
}
+int npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr);
int npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id);
int npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count);
int npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id);
@@ -480,7 +481,6 @@ uint64_t npc_get_kex_capability(struct npc *npc);
int npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
const struct roc_npc_flow_item_ipv6 *ipv6_mask,
struct npc_parse_state *pst, uint8_t type);
-int npc_rss_free_grp_get(struct npc *npc, uint32_t *grp);
int npc_rss_action_configure(struct roc_npc *roc_npc, const struct roc_npc_action_rss *rss,
uint8_t *alg_idx, uint32_t *rss_grp, uint32_t mcam_id);
int npc_rss_action_program(struct roc_npc *roc_npc, const struct roc_npc_action actions[],
@@ -496,4 +496,5 @@ void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc);
int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, const struct roc_npc_action_age *age,
struct roc_npc_flow *flow);
void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc);
+int npc_rss_free_grp_get(struct npc *npc, uint32_t *pos);
#endif /* _ROC_NPC_PRIV_H_ */
@@ -91,6 +91,10 @@ INTERNAL {
roc_dpi_disable;
roc_dpi_enable;
roc_error_msg_get;
+ roc_eswitch_npc_mcam_delete_rule;
+ roc_eswitch_npc_mcam_rx_rule;
+ roc_eswitch_npc_mcam_tx_rule;
+ roc_eswitch_npc_rss_action_configure;
roc_hash_md5_gen;
roc_hash_sha1_gen;
roc_hash_sha256_gen;
@@ -449,6 +453,7 @@ INTERNAL {
roc_npc_flow_dump;
roc_npc_flow_mcam_dump;
roc_npc_flow_parse;
+ roc_npc_get_free_mcam_entry;
roc_npc_get_low_priority_mcam;
roc_npc_init;
roc_npc_kex_capa_get;
@@ -456,6 +461,7 @@ INTERNAL {
roc_npc_mark_actions_sub_return;
roc_npc_vtag_actions_get;
roc_npc_vtag_actions_sub_return;
+ roc_npc_mcam_alloc_counter;
roc_npc_mcam_alloc_entries;
roc_npc_mcam_alloc_entry;
roc_npc_mcam_clear_counter;