@@ -197,8 +197,23 @@ low level hardware resources.
* For Ubuntu, it can be installed using `apt install libjansson-dev`
-- run testpmd with the json file
+- run testpmd with the json file, create two vports and two VF representors
.. code-block:: console
- dpdk-testpmd -c 0x3 -n 4 -a 0000:af:00.6,vport=[0],flow_parser="refpkg.json" -- -i
+ dpdk-testpmd -c 0x3 -n 4 -a 0000:af:00.6,vport=[0-1],representor=vf[0,1],flow_parser="refpkg.json" -- -i
+
+#. Create one flow to forward ETH-IPV4-TCP from I/O port to a local(CPF's) vport. Flow should be created on
+ vport X. Group M should match fxp module. Action port_representor Y means forward packet to local vport Y.
+ If want to send a packet to VF representor, action represented_port can be used::
+
+ .. code-block:: console
+
+ flow create X ingress group M pattern eth dst is 00:01:00:00:03:14 / ipv4 src is 192.168.0.1 \
+ dst is 192.168.0.2 / tcp / end actions port_representor port_id Y / end
+
+#. Send a matched packet, and it should be displayed on PMD::
+
+ .. code-block:: console
+
+ sendp(Ether(dst='00:01:00:00:03:14')/IP(src='192.168.0.1',dst='192.168.0.2')/TCP(),iface="ens25f0")
@@ -81,6 +81,7 @@ New Features
* **Updated Intel cpfl driver.**
* Added support for port representor.
+ * Added support for rte_flow.
Removed Items
-------------
@@ -73,6 +73,7 @@ cpfl_fxp_create(struct rte_eth_dev *dev,
struct cpfl_adapter_ext *ad = itf->adapter;
struct cpfl_rule_info_meta *rim = meta;
struct cpfl_vport *vport;
+ struct cpfl_repr *repr;
if (!rim)
return ret;
@@ -83,6 +84,10 @@ cpfl_fxp_create(struct rte_eth_dev *dev,
* Even index is tx queue and odd index is rx queue.
*/
cpq_id = vport->base.devarg_id * 2;
+ } else if (itf->type == CPFL_ITF_TYPE_REPRESENTOR) {
+ repr = (struct cpfl_repr *)itf;
+ cpq_id = ((repr->repr_id.pf_id + repr->repr_id.vf_id) &
+ (CPFL_TX_CFGQ_NUM - 1)) * 2;
} else {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"fail to find correct control queue");
@@ -122,6 +127,7 @@ cpfl_fxp_destroy(struct rte_eth_dev *dev,
struct cpfl_rule_info_meta *rim;
uint32_t i;
struct cpfl_vport *vport;
+ struct cpfl_repr *repr;
rim = flow->rule;
if (!rim) {
@@ -135,6 +141,10 @@ cpfl_fxp_destroy(struct rte_eth_dev *dev,
if (itf->type == CPFL_ITF_TYPE_VPORT) {
vport = (struct cpfl_vport *)itf;
cpq_id = vport->base.devarg_id * 2;
+ } else if (itf->type == CPFL_ITF_TYPE_REPRESENTOR) {
+ repr = (struct cpfl_repr *)itf;
+ cpq_id = ((repr->repr_id.pf_id + repr->repr_id.vf_id) &
+ (CPFL_TX_CFGQ_NUM - 1)) * 2;
} else {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"fail to find correct control queue");
@@ -257,6 +267,7 @@ cpfl_fxp_parse_action(struct cpfl_itf *itf,
int queue_id = -1;
bool fwd_vsi = false;
bool fwd_q = false;
+ bool is_vsi;
uint32_t i;
struct cpfl_rule_info *rinfo = &rim->rules[index];
union cpfl_action_set *act_set = (void *)rinfo->act_bytes;
@@ -267,6 +278,7 @@ cpfl_fxp_parse_action(struct cpfl_itf *itf,
action_type = action->type;
switch (action_type) {
case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
if (!fwd_vsi)
fwd_vsi = true;
else
@@ -285,12 +297,20 @@ cpfl_fxp_parse_action(struct cpfl_itf *itf,
queue_id = CPFL_INVALID_QUEUE_ID;
}
- dev_id = cpfl_get_vsi_id(dst_itf);
+ is_vsi = (action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR ||
+ dst_itf->type == CPFL_ITF_TYPE_REPRESENTOR);
+ if (is_vsi)
+ dev_id = cpfl_get_vsi_id(dst_itf);
+ else
+ dev_id = cpfl_get_port_id(dst_itf);
if (dev_id == CPFL_INVALID_HW_ID)
goto err;
- *act_set = cpfl_act_fwd_vsi(0, priority, 0, dev_id);
+ if (is_vsi)
+ *act_set = cpfl_act_fwd_vsi(0, priority, 0, dev_id);
+ else
+ *act_set = cpfl_act_fwd_port(0, priority, 0, dev_id);
act_set++;
rinfo->act_byte_len += sizeof(union cpfl_action_set);
break;
@@ -414,6 +434,64 @@ cpfl_is_mod_action(const struct rte_flow_action actions[])
return false;
}
+static bool
+cpfl_fxp_get_metadata_port(struct cpfl_itf *itf,
+ const struct rte_flow_action actions[])
+{
+ const struct rte_flow_action *action;
+ enum rte_flow_action_type action_type;
+ const struct rte_flow_action_ethdev *ethdev;
+ struct cpfl_itf *target_itf;
+ bool ret;
+
+ if (itf->type == CPFL_ITF_TYPE_VPORT) {
+ ret = cpfl_metadata_write_port_id(itf);
+ if (!ret) {
+ PMD_DRV_LOG(ERR, "fail to write port id");
+ return false;
+ }
+ }
+
+ ret = cpfl_metadata_write_sourcevsi(itf);
+ if (!ret) {
+ PMD_DRV_LOG(ERR, "fail to write source vsi id");
+ return false;
+ }
+
+ ret = cpfl_metadata_write_vsi(itf);
+ if (!ret) {
+ PMD_DRV_LOG(ERR, "fail to write vsi id");
+ return false;
+ }
+
+ if (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END)
+ return false;
+
+ for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
+ action_type = action->type;
+ switch (action_type) {
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
+ case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
+ ethdev = (const struct rte_flow_action_ethdev *)action->conf;
+ target_itf = cpfl_get_itf_by_port_id(ethdev->port_id);
+ if (!target_itf) {
+ PMD_DRV_LOG(ERR, "fail to get target_itf by port id");
+ return false;
+ }
+ ret = cpfl_metadata_write_targetvsi(target_itf);
+ if (!ret) {
+ PMD_DRV_LOG(ERR, "fail to write target vsi id");
+ return false;
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+
+ return true;
+}
+
static int
cpfl_fxp_parse_pattern_action(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -430,6 +508,12 @@ cpfl_fxp_parse_pattern_action(struct rte_eth_dev *dev,
struct cpfl_rule_info_meta *rim;
int ret;
+ ret = cpfl_fxp_get_metadata_port(itf, actions);
+ if (!ret) {
+ PMD_DRV_LOG(ERR, "Fail to save metadata.");
+ return -EINVAL;
+ }
+
ret = cpfl_flow_parse_items(itf, adapter->flow_parser, pattern, attr, &pr_action);
if (ret) {
PMD_DRV_LOG(ERR, "No Match pattern support.");
@@ -4,6 +4,8 @@
#include "cpfl_representor.h"
#include "cpfl_rxtx.h"
+#include "cpfl_flow.h"
+#include "cpfl_rules.h"
static int
cpfl_repr_allowlist_update(struct cpfl_adapter_ext *adapter,
@@ -374,6 +376,22 @@ cpfl_repr_link_update(struct rte_eth_dev *ethdev,
return 0;
}
+static int
+cpfl_dev_repr_flow_ops_get(struct rte_eth_dev *dev,
+ const struct rte_flow_ops **ops)
+{
+ if (!dev)
+ return -EINVAL;
+
+#ifdef RTE_HAS_JANSSON
+ *ops = &cpfl_flow_ops;
+#else
+ *ops = NULL;
+ PMD_DRV_LOG(NOTICE, "not support rte_flow, please install json-c library.");
+#endif
+ return 0;
+}
+
static const struct eth_dev_ops cpfl_repr_dev_ops = {
.dev_start = cpfl_repr_dev_start,
.dev_stop = cpfl_repr_dev_stop,
@@ -385,6 +403,7 @@ static const struct eth_dev_ops cpfl_repr_dev_ops = {
.tx_queue_setup = cpfl_repr_tx_queue_setup,
.link_update = cpfl_repr_link_update,
+ .flow_ops_get = cpfl_dev_repr_flow_ops_get,
};
static int
@@ -393,6 +412,7 @@ cpfl_repr_init(struct rte_eth_dev *eth_dev, void *init_param)
struct cpfl_repr *repr = CPFL_DEV_TO_REPR(eth_dev);
struct cpfl_repr_param *param = init_param;
struct cpfl_adapter_ext *adapter = param->adapter;
+ int ret;
repr->repr_id = param->repr_id;
repr->vport_info = param->vport_info;
@@ -402,6 +422,15 @@ cpfl_repr_init(struct rte_eth_dev *eth_dev, void *init_param)
if (repr->vport_info->vport.info.vport_status == CPCHNL2_VPORT_STATUS_ENABLED)
repr->func_up = true;
+ TAILQ_INIT(&repr->itf.flow_list);
+ memset(repr->itf.dma, 0, sizeof(repr->itf.dma));
+ memset(repr->itf.msg, 0, sizeof(repr->itf.msg));
+ ret = cpfl_alloc_dma_mem_batch(&repr->itf.flow_dma, repr->itf.dma,
+ sizeof(union cpfl_rule_cfg_pkt_record),
+ CPFL_FLOW_BATCH_SIZE);
+ if (ret < 0)
+ return ret;
+
eth_dev->dev_ops = &cpfl_repr_dev_ops;
eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;