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
|
of_set_vlan_vid = Y
|
||||||
passthru = Y
|
passthru = Y
|
||||||
port_id = Y
|
port_id = Y
|
||||||
|
port_representor = Y
|
||||||
|
represented_port = Y
|
||||||
queue = Y
|
queue = Y
|
||||||
rss = Y
|
rss = Y
|
||||||
vxlan_decap = Y
|
vxlan_decap = Y
|
||||||
|
@ -1242,6 +1242,35 @@ vf_egress_port_id_action(struct enic_flowman *fm,
|
|||||||
return 0;
|
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 */
|
/* Translate flow actions to flowman TCAM entry actions */
|
||||||
static int
|
static int
|
||||||
enic_fm_copy_action(struct enic_flowman *fm,
|
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 */
|
vnic_h = enic->fm_vnic_handle; /* This port */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ENICPMD_LOG(DEBUG, "port id %u", port->id);
|
ret = enic_fm_check_transfer_dst(enic, port->id, &dev,
|
||||||
if (!rte_eth_dev_is_valid_port(port->id)) {
|
error);
|
||||||
return rte_flow_error_set(error, EINVAL,
|
if (ret)
|
||||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
return ret;
|
||||||
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");
|
|
||||||
}
|
|
||||||
vnic_h = pmd_priv(dev)->fm_vnic_handle;
|
vnic_h = pmd_priv(dev)->fm_vnic_handle;
|
||||||
overlap |= PORT_ID;
|
overlap |= PORT_ID;
|
||||||
/*
|
/*
|
||||||
@ -1560,6 +1575,48 @@ enic_fm_copy_action(struct enic_flowman *fm,
|
|||||||
ovlan |= rte_be_to_cpu_16(vid->vlan_vid);
|
ovlan |= rte_be_to_cpu_16(vid->vlan_vid);
|
||||||
break;
|
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:
|
default:
|
||||||
goto unsupported;
|
goto unsupported;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user