@@ -1073,6 +1073,8 @@
nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
{
int ret;
+ int err;
+ uint64_t ext_features;
unsigned int numa_node;
struct nfp_net_hw *pf_hw;
struct nfp_net_hw *ctrl_hw;
@@ -1114,6 +1116,18 @@
goto vnic_cleanup;
}
+ /* Read the extra features */
+ ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
+ &err);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
+ ret = -EIO;
+ goto pf_cpp_area_cleanup;
+ }
+
+ /* Store the extra features */
+ app_fw_flower->ext_features = ext_features;
+
/* Fill in the PF vNIC and populate app struct */
app_fw_flower->pf_hw = pf_hw;
pf_hw->ctrl_bar = pf_dev->ctrl_bar;
@@ -6,6 +6,21 @@
#ifndef _NFP_FLOWER_H_
#define _NFP_FLOWER_H_
+/* Extra features bitmap. */
+#define NFP_FL_FEATS_GENEVE RTE_BIT64(0)
+#define NFP_FL_NBI_MTU_SETTING RTE_BIT64(1)
+#define NFP_FL_FEATS_GENEVE_OPT RTE_BIT64(2)
+#define NFP_FL_FEATS_VLAN_PCP RTE_BIT64(3)
+#define NFP_FL_FEATS_VF_RLIM RTE_BIT64(4)
+#define NFP_FL_FEATS_FLOW_MOD RTE_BIT64(5)
+#define NFP_FL_FEATS_PRE_TUN_RULES RTE_BIT64(6)
+#define NFP_FL_FEATS_IPV6_TUN RTE_BIT64(7)
+#define NFP_FL_FEATS_VLAN_QINQ RTE_BIT64(8)
+#define NFP_FL_FEATS_QOS_PPS RTE_BIT64(9)
+#define NFP_FL_FEATS_QOS_METER RTE_BIT64(10)
+#define NFP_FL_FEATS_DECAP_V2 RTE_BIT64(11)
+#define NFP_FL_FEATS_HOST_ACK RTE_BIT64(31)
+
/*
* Flower fallback and ctrl path always adds and removes
* 8 bytes of prepended data. Tx descriptors must point
@@ -52,9 +67,18 @@ struct nfp_app_fw_flower {
/* PF representor */
struct nfp_flower_representor *pf_repr;
+ /* Flower extra features */
+ uint64_t ext_features;
+
struct nfp_flow_priv *flow_priv;
};
+static inline bool
+nfp_flower_support_decap_v2(const struct nfp_app_fw_flower *app_fw_flower)
+{
+ return app_fw_flower->ext_features & NFP_FL_FEATS_DECAP_V2;
+}
+
int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
int nfp_secondary_init_app_fw_flower(struct nfp_cpp *cpp);
uint16_t nfp_flower_pf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
@@ -263,6 +263,8 @@
}
msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+ if (!nfp_flower_support_decap_v2(app_fw_flower))
+ msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
memcpy(msg, payload, msg_len);
@@ -292,6 +294,8 @@
}
msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+ if (!nfp_flower_support_decap_v2(app_fw_flower))
+ msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
memcpy(msg, payload, msg_len);
@@ -136,6 +136,21 @@ struct nfp_flower_tun_neigh {
};
/*
+ * Bit 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ * -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---------------------------------------------------------------+
+ * 0 | VLAN_TPID | VLAN_ID |
+ * +---------------------------------------------------------------+
+ * 1 | HOST_CTX |
+ * +---------------------------------------------------------------+
+ */
+struct nfp_flower_tun_neigh_ext {
+ rte_be16_t vlan_tpid;
+ rte_be16_t vlan_tci;
+ rte_be32_t host_ctx;
+};
+
+/*
* NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
* Bit 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
* -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -157,6 +172,7 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
rte_be32_t dst_ipv4;
rte_be32_t src_ipv4;
struct nfp_flower_tun_neigh common;
+ struct nfp_flower_tun_neigh_ext ext;
};
/*
@@ -193,6 +209,7 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
uint8_t dst_ipv6[16];
uint8_t src_ipv6[16];
struct nfp_flower_tun_neigh common;
+ struct nfp_flower_tun_neigh_ext ext;
};
#define NFP_TUN_PRE_TUN_RULE_DEL (1 << 0)
@@ -2402,8 +2402,10 @@ struct nfp_pre_tun_entry {
static int
nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+ struct nfp_fl_rule_metadata *nfp_flow_meta,
struct rte_flow *nfp_flow)
{
+ bool exists = false;
struct nfp_fl_tun *tmp;
struct nfp_fl_tun *tun;
struct nfp_flow_priv *priv;
@@ -2437,11 +2439,17 @@ struct nfp_pre_tun_entry {
LIST_FOREACH(tmp, &priv->nn_list, next) {
if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
tmp->ref_cnt++;
- return 0;
+ exists = true;
+ break;
}
}
- LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+ if (exists) {
+ if (!nfp_flower_support_decap_v2(app_fw_flower))
+ return 0;
+ } else {
+ LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+ }
memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
payload.dst_ipv4 = ipv4->ipv4_src;
@@ -2450,6 +2458,17 @@ struct nfp_pre_tun_entry {
memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
payload.common.port_id = port->in_port;
+ if (nfp_flower_support_decap_v2(app_fw_flower)) {
+ if (meta_tci->tci != 0) {
+ payload.ext.vlan_tci = meta_tci->tci;
+ payload.ext.vlan_tpid = 0x88a8;
+ } else {
+ payload.ext.vlan_tci = 0xffff;
+ payload.ext.vlan_tpid = 0xffff;
+ }
+ payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+ }
+
return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
}
@@ -2510,8 +2529,10 @@ struct nfp_pre_tun_entry {
static int
nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+ struct nfp_fl_rule_metadata *nfp_flow_meta,
struct rte_flow *nfp_flow)
{
+ bool exists = false;
struct nfp_fl_tun *tmp;
struct nfp_fl_tun *tun;
struct nfp_flow_priv *priv;
@@ -2545,11 +2566,17 @@ struct nfp_pre_tun_entry {
LIST_FOREACH(tmp, &priv->nn_list, next) {
if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
tmp->ref_cnt++;
- return 0;
+ exists = true;
+ break;
}
}
- LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+ if (exists) {
+ if (!nfp_flower_support_decap_v2(app_fw_flower))
+ return 0;
+ } else {
+ LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+ }
memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
@@ -2558,6 +2585,17 @@ struct nfp_pre_tun_entry {
memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
payload.common.port_id = port->in_port;
+ if (nfp_flower_support_decap_v2(app_fw_flower)) {
+ if (meta_tci->tci != 0) {
+ payload.ext.vlan_tci = meta_tci->tci;
+ payload.ext.vlan_tpid = 0x88a8;
+ } else {
+ payload.ext.vlan_tci = 0xffff;
+ payload.ext.vlan_tpid = 0xffff;
+ }
+ payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+ }
+
return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
}
@@ -2575,12 +2613,14 @@ struct nfp_pre_tun_entry {
static int
nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
- struct rte_flow *nfp_flow)
+ struct rte_flow *nfp_flow,
+ bool decap_flag)
{
int ret;
bool flag = false;
struct nfp_fl_tun *tmp;
struct nfp_fl_tun *tun;
+ struct nfp_flower_in_port *port;
tun = &nfp_flow->tun;
LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
@@ -2608,6 +2648,40 @@ struct nfp_pre_tun_entry {
}
}
+ if (!decap_flag)
+ return 0;
+
+ port = (struct nfp_flower_in_port *)(nfp_flow->payload.unmasked_data +
+ sizeof(struct nfp_fl_rule_metadata) +
+ sizeof(struct nfp_flower_meta_tci));
+
+ if (tmp->payload.v6_flag != 0) {
+ struct nfp_flower_cmsg_tun_neigh_v6 nn_v6;
+ memset(&nn_v6, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+ memcpy(nn_v6.dst_ipv6, tmp->payload.dst.dst_ipv6, sizeof(nn_v6.dst_ipv6));
+ memcpy(nn_v6.src_ipv6, tmp->payload.src.src_ipv6, sizeof(nn_v6.src_ipv6));
+ memcpy(nn_v6.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+ memcpy(nn_v6.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+ nn_v6.common.port_id = port->in_port;
+
+ ret = nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &nn_v6);
+ } else {
+ struct nfp_flower_cmsg_tun_neigh_v4 nn_v4;
+ memset(&nn_v4, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+ nn_v4.dst_ipv4 = tmp->payload.dst.dst_ipv4;
+ nn_v4.src_ipv4 = tmp->payload.src.src_ipv4;
+ memcpy(nn_v4.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+ memcpy(nn_v4.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+ nn_v4.common.port_id = port->in_port;
+
+ ret = nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &nn_v4);
+ }
+
+ if (ret != 0) {
+ PMD_DRV_LOG(DEBUG, "Failed to send the nn entry");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -2895,12 +2969,14 @@ struct nfp_pre_tun_entry {
goto free_entry;
}
- ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
- nfp_mac_idx, true);
- if (ret != 0) {
- PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
- ret = -EINVAL;
- goto free_entry;
+ if (!nfp_flower_support_decap_v2(repr->app_fw_flower)) {
+ ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+ nfp_mac_idx, true);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+ ret = -EINVAL;
+ goto free_entry;
+ }
}
find_entry->ref_cnt = 1U;
@@ -2951,18 +3027,20 @@ struct nfp_pre_tun_entry {
return -EINVAL;
}
- ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
- nfp_mac_idx, false);
- if (ret != 0) {
- PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
- return -EINVAL;
+ if (!nfp_flower_support_decap_v2(app_fw_flower)) {
+ ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+ nfp_mac_idx, false);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+ return -EINVAL;
+ }
}
meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
- return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+ return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
else
- return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
+ return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
}
static int
@@ -3662,11 +3740,11 @@ struct nfp_pre_tun_entry {
break;
case NFP_FLOW_ENCAP:
/* Delete the entry from nn table */
- ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+ ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, false);
break;
case NFP_FLOW_DECAP:
/* Delete the entry from nn table */
- ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+ ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, true);
if (ret != 0)
goto exit;