- * Enable a special flow in a hash RX queue for a given VLAN index.
- *
- * @param hash_rxq
- * Pointer to hash RX queue structure.
- * @param flow_type
- * Special flow type.
- * @param vlan_index
- * VLAN index to use.
- *
- * @return
- * 0 on success, errno value on failure.
- */
-static int
-hash_rxq_special_flow_enable_vlan(struct hash_rxq *hash_rxq,
- enum hash_rxq_flow_type flow_type,
- unsigned int vlan_index)
-{
- struct priv *priv = hash_rxq->priv;
- struct ibv_exp_flow *flow;
- FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
- struct ibv_exp_flow_attr *attr = &data->attr;
- struct ibv_exp_flow_spec_eth *spec = &data->spec;
- const uint8_t *mac;
- const uint8_t *mask;
- unsigned int vlan_enabled = (priv->vlan_filter_n &&
- special_flow_init[flow_type].per_vlan);
- unsigned int vlan_id = priv->vlan_filter[vlan_index];
-
- /* Check if flow is relevant for this hash_rxq. */
- if (!(special_flow_init[flow_type].hash_types & (1 << hash_rxq->type)))
- return 0;
- /* Check if flow already exists. */
- if (hash_rxq->special_flow[flow_type][vlan_index] != NULL)
- return 0;
-
- /*
- * No padding must be inserted by the compiler between attr and spec.
- * This layout is expected by libibverbs.
- */
- assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
- priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
- /* The first specification must be Ethernet. */
- assert(spec->type == IBV_EXP_FLOW_SPEC_ETH);
- assert(spec->size == sizeof(*spec));
-
- mac = special_flow_init[flow_type].dst_mac_val;
- mask = special_flow_init[flow_type].dst_mac_mask;
- *spec = (struct ibv_exp_flow_spec_eth){
- .type = IBV_EXP_FLOW_SPEC_ETH,
- .size = sizeof(*spec),
- .val = {
- .dst_mac = {
- mac[0], mac[1], mac[2],
- mac[3], mac[4], mac[5],
- },
- .vlan_tag = (vlan_enabled ? htons(vlan_id) : 0),
- },
- .mask = {
- .dst_mac = {
- mask[0], mask[1], mask[2],
- mask[3], mask[4], mask[5],
- },
- .vlan_tag = (vlan_enabled ? htons(0xfff) : 0),
- },
- };
-
- errno = 0;
- flow = ibv_exp_create_flow(hash_rxq->qp, attr);
- if (flow == NULL) {
- /* It's not clear whether errno is always set in this case. */
- ERROR("%p: flow configuration failed, errno=%d: %s",
- (void *)hash_rxq, errno,
- (errno ? strerror(errno) : "Unknown error"));
- if (errno)
- return errno;
- return EINVAL;
- }
- hash_rxq->special_flow[flow_type][vlan_index] = flow;
- DEBUG("%p: special flow %s (index %d) VLAN %u (index %u) enabled",
- (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type,
- vlan_id, vlan_index);
- return 0;
-}
-
-/**
- * Disable a special flow in a hash RX queue for a given VLAN index.
- *
- * @param hash_rxq
- * Pointer to hash RX queue structure.
- * @param flow_type
- * Special flow type.
- * @param vlan_index
- * VLAN index to use.
- */
-static void
-hash_rxq_special_flow_disable_vlan(struct hash_rxq *hash_rxq,
- enum hash_rxq_flow_type flow_type,
- unsigned int vlan_index)
-{
- struct ibv_exp_flow *flow =
- hash_rxq->special_flow[flow_type][vlan_index];
-
- if (flow == NULL)
- return;
- claim_zero(ibv_exp_destroy_flow(flow));
- hash_rxq->special_flow[flow_type][vlan_index] = NULL;
- DEBUG("%p: special flow %s (index %d) VLAN %u (index %u) disabled",
- (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type,
- hash_rxq->priv->vlan_filter[vlan_index], vlan_index);
-}
-
-/**
- * Enable a special flow in a hash RX queue.
- *
- * @param hash_rxq
- * Pointer to hash RX queue structure.
- * @param flow_type
- * Special flow type.
- * @param vlan_index
- * VLAN index to use.
- *
- * @return
- * 0 on success, errno value on failure.
- */
-static int
-hash_rxq_special_flow_enable(struct hash_rxq *hash_rxq,
- enum hash_rxq_flow_type flow_type)
-{
- struct priv *priv = hash_rxq->priv;
- unsigned int i = 0;
- int ret;
-
- assert((unsigned int)flow_type < RTE_DIM(hash_rxq->special_flow));
- assert(RTE_DIM(hash_rxq->special_flow[flow_type]) ==
- RTE_DIM(priv->vlan_filter));
- /* Add a special flow for each VLAN filter when relevant. */
- do {
- ret = hash_rxq_special_flow_enable_vlan(hash_rxq, flow_type, i);
- if (ret) {
- /* Failure, rollback. */
- while (i != 0)
- hash_rxq_special_flow_disable_vlan(hash_rxq,
- flow_type,
- --i);
- return ret;
- }
- } while (special_flow_init[flow_type].per_vlan &&
- ++i < priv->vlan_filter_n);
- return 0;
-}
-
-/**
- * Disable a special flow in a hash RX queue.
- *
- * @param hash_rxq
- * Pointer to hash RX queue structure.
- * @param flow_type
- * Special flow type.
- */
-static void
-hash_rxq_special_flow_disable(struct hash_rxq *hash_rxq,
- enum hash_rxq_flow_type flow_type)
-{
- unsigned int i;
-
- assert((unsigned int)flow_type < RTE_DIM(hash_rxq->special_flow));
- for (i = 0; (i != RTE_DIM(hash_rxq->special_flow[flow_type])); ++i)
- hash_rxq_special_flow_disable_vlan(hash_rxq, flow_type, i);
-}
-
-/**
- * Enable a special flow in all hash RX queues.