net/enic: support meta flow actions to overrule destinations
Add support for actions PORT_REPRESENTOR and REPRESENTED_PORT based on the existing support for action PORT_ID. Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> Acked-by: Hyong Youb Kim <hyonkim@cisco.com>
This commit is contained in:
parent
640b44aa5c
commit
54bd4ebe8b
@ -62,6 +62,8 @@ of_set_vlan_pcp = Y
|
||||
of_set_vlan_vid = Y
|
||||
passthru = Y
|
||||
port_id = Y
|
||||
port_representor = Y
|
||||
represented_port = Y
|
||||
queue = Y
|
||||
rss = Y
|
||||
vxlan_decap = Y
|
||||
|
@ -1242,6 +1242,35 @@ vf_egress_port_id_action(struct enic_flowman *fm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
enic_fm_check_transfer_dst(struct enic *enic, uint16_t dst_port_id,
|
||||
struct rte_eth_dev **dst_dev,
|
||||
struct rte_flow_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev;
|
||||
|
||||
ENICPMD_LOG(DEBUG, "port id %u", dst_port_id);
|
||||
if (!rte_eth_dev_is_valid_port(dst_port_id)) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "invalid port_id");
|
||||
}
|
||||
dev = &rte_eth_devices[dst_port_id];
|
||||
if (!dev_is_enic(dev)) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "port_id is not enic");
|
||||
}
|
||||
if (enic->switch_domain_id != pmd_priv(dev)->switch_domain_id) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "destination and source ports are not in the same switch domain");
|
||||
}
|
||||
|
||||
*dst_dev = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Translate flow actions to flowman TCAM entry actions */
|
||||
static int
|
||||
enic_fm_copy_action(struct enic_flowman *fm,
|
||||
@ -1446,24 +1475,10 @@ enic_fm_copy_action(struct enic_flowman *fm,
|
||||
vnic_h = enic->fm_vnic_handle; /* This port */
|
||||
break;
|
||||
}
|
||||
ENICPMD_LOG(DEBUG, "port id %u", port->id);
|
||||
if (!rte_eth_dev_is_valid_port(port->id)) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "invalid port_id");
|
||||
}
|
||||
dev = &rte_eth_devices[port->id];
|
||||
if (!dev_is_enic(dev)) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "port_id is not enic");
|
||||
}
|
||||
if (enic->switch_domain_id !=
|
||||
pmd_priv(dev)->switch_domain_id) {
|
||||
return rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
NULL, "destination and source ports are not in the same switch domain");
|
||||
}
|
||||
ret = enic_fm_check_transfer_dst(enic, port->id, &dev,
|
||||
error);
|
||||
if (ret)
|
||||
return ret;
|
||||
vnic_h = pmd_priv(dev)->fm_vnic_handle;
|
||||
overlap |= PORT_ID;
|
||||
/*
|
||||
@ -1560,6 +1575,48 @@ enic_fm_copy_action(struct enic_flowman *fm,
|
||||
ovlan |= rte_be_to_cpu_16(vid->vlan_vid);
|
||||
break;
|
||||
}
|
||||
case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR: {
|
||||
const struct rte_flow_action_ethdev *ethdev;
|
||||
struct rte_eth_dev *dev;
|
||||
|
||||
ethdev = actions->conf;
|
||||
ret = enic_fm_check_transfer_dst(enic, ethdev->port_id,
|
||||
&dev, error);
|
||||
if (ret)
|
||||
return ret;
|
||||
vnic_h = pmd_priv(dev)->fm_vnic_handle;
|
||||
overlap |= PORT_ID;
|
||||
/*
|
||||
* Action PORT_REPRESENTOR implies ingress destination.
|
||||
* Noting to do. We add an implicit stree at the
|
||||
* end if needed.
|
||||
*/
|
||||
ingress = 1;
|
||||
break;
|
||||
}
|
||||
case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
|
||||
const struct rte_flow_action_ethdev *ethdev;
|
||||
struct rte_eth_dev *dev;
|
||||
|
||||
if (overlap & PORT_ID) {
|
||||
ENICPMD_LOG(DEBUG, "cannot have multiple egress PORT_ID actions");
|
||||
goto unsupported;
|
||||
}
|
||||
ethdev = actions->conf;
|
||||
ret = enic_fm_check_transfer_dst(enic, ethdev->port_id,
|
||||
&dev, error);
|
||||
if (ret)
|
||||
return ret;
|
||||
vnic_h = pmd_priv(dev)->fm_vnic_handle;
|
||||
overlap |= PORT_ID;
|
||||
/* Action REPRESENTED_PORT: always egress destination */
|
||||
ingress = 0;
|
||||
ret = vf_egress_port_id_action(fm, dev, vnic_h, &fm_op,
|
||||
error);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unsupported;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user