- VF
+- PORT_ID
+
- DROP
Validating flow rules depends on the firmware variant.
int
sfc_mae_attach(struct sfc_adapter *sa)
{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
struct sfc_mae_switch_port_request switch_port_request = {0};
const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
efx_mport_sel_t entity_mport;
sfc_log_init(sa, "assign RTE switch port");
switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
switch_port_request.entity_mportp = &entity_mport;
+ /*
+ * As of now, the driver does not support representors, so
+ * RTE ethdev MPORT simply matches that of the entity.
+ */
+ switch_port_request.ethdev_mportp = &entity_mport;
+ switch_port_request.ethdev_port_id = sas->port_id;
rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
&switch_port_request,
&mae->switch_port_id);
return efx_mae_action_set_populate_deliver(spec, &mport);
}
+static int
+sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
+ const struct rte_flow_action_port_id *conf,
+ efx_mae_actions_t *spec)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_mae *mae = &sa->mae;
+ efx_mport_sel_t mport;
+ uint16_t port_id;
+ int rc;
+
+ port_id = (conf->original != 0) ? sas->port_id : conf->id;
+
+ rc = sfc_mae_switch_port_by_ethdev(mae->switch_domain_id,
+ port_id, &mport);
+ if (rc != 0)
+ return rc;
+
+ return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
static int
sfc_mae_rule_parse_action(struct sfc_adapter *sa,
const struct rte_flow_action *action,
bundle->actions_mask);
rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
break;
+ case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID,
+ bundle->actions_mask);
+ rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec);
+ break;
case RTE_FLOW_ACTION_TYPE_DROP:
SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
bundle->actions_mask);
* This mapping comprises a port type to ensure that RTE switch port ID
* of a represented entity and that of its representor are different in
* the case when the entity gets plugged into DPDK and not into a guest.
+ *
+ * Entry data also comprises RTE ethdev's own MPORT. This value
+ * coincides with the entity MPORT in the case of independent ports.
+ * In the case of representors, this ID is not a selector and refers
+ * to an allocatable object (that is, it's likely to change on RTE
+ * ethdev replug). Flow API backend must use this value rather
+ * than entity_mport to support flow rule action PORT_ID.
*/
struct sfc_mae_switch_port {
TAILQ_ENTRY(sfc_mae_switch_port) switch_domain_ports;
+ /** RTE ethdev MPORT */
+ efx_mport_sel_t ethdev_mport;
+ /** RTE ethdev port ID */
+ uint16_t ethdev_port_id;
+
/** Entity (PCIe function) MPORT selector */
efx_mport_sel_t entity_mport;
/** Port type (independent/representor) */
TAILQ_INSERT_TAIL(&domain->ports, port, switch_domain_ports);
done:
+ port->ethdev_mport = *req->ethdev_mportp;
+ port->ethdev_port_id = req->ethdev_port_id;
+
*switch_port_id = port->id;
rte_spinlock_unlock(&sfc_mae_switch.lock);
rte_spinlock_unlock(&sfc_mae_switch.lock);
return rc;
}
+
+/* This function expects to be called only when the lock is held */
+static int
+sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
+ uint16_t ethdev_port_id,
+ efx_mport_sel_t *mport_sel)
+{
+ struct sfc_mae_switch_domain *domain;
+ struct sfc_mae_switch_port *port;
+
+ SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+ if (ethdev_port_id == RTE_MAX_ETHPORTS)
+ return EINVAL;
+
+ domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
+ if (domain == NULL)
+ return EINVAL;
+
+ TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
+ if (port->ethdev_port_id == ethdev_port_id) {
+ *mport_sel = port->ethdev_mport;
+ return 0;
+ }
+ }
+
+ return ENOENT;
+}
+
+int
+sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id,
+ uint16_t ethdev_port_id,
+ efx_mport_sel_t *mport_sel)
+{
+ int rc;
+
+ rte_spinlock_lock(&sfc_mae_switch.lock);
+ rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id,
+ ethdev_port_id, mport_sel);
+ rte_spinlock_unlock(&sfc_mae_switch.lock);
+
+ return rc;
+}
struct sfc_mae_switch_port_request {
enum sfc_mae_switch_port_type type;
const efx_mport_sel_t *entity_mportp;
+ const efx_mport_sel_t *ethdev_mportp;
+ uint16_t ethdev_port_id;
};
int sfc_mae_assign_switch_domain(struct sfc_adapter *sa,
const struct sfc_mae_switch_port_request *req,
uint16_t *switch_port_id);
+int sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id,
+ uint16_t ethdev_port_id,
+ efx_mport_sel_t *mport_sel);
+
#ifdef __cplusplus
}
#endif