-
-/**
- * Unregister a MAC address.
- *
- * @param priv
- * Pointer to private structure.
- */
-void
-mlx4_mac_addr_del(struct priv *priv)
-{
-#ifndef NDEBUG
- uint8_t (*mac)[ETHER_ADDR_LEN] = &priv->mac.addr_bytes;
-#endif
-
- if (!priv->mac_flow)
- return;
- DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x",
- (void *)priv,
- (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]);
- claim_zero(ibv_destroy_flow(priv->mac_flow));
- priv->mac_flow = NULL;
-}
-
-/**
- * Register a MAC address.
- *
- * The MAC address is registered in queue 0.
- *
- * @param priv
- * Pointer to private structure.
- *
- * @return
- * 0 on success, negative errno value otherwise and rte_errno is set.
- */
-int
-mlx4_mac_addr_add(struct priv *priv)
-{
- uint8_t (*mac)[ETHER_ADDR_LEN] = &priv->mac.addr_bytes;
- struct rxq *rxq;
- struct ibv_flow *flow;
-
- /* If device isn't started, this is all we need to do. */
- if (!priv->started)
- return 0;
- if (priv->isolated)
- return 0;
- if (*priv->rxqs && (*priv->rxqs)[0])
- rxq = (*priv->rxqs)[0];
- else
- return 0;
-
- /* Allocate flow specification on the stack. */
- struct __attribute__((packed)) {
- struct ibv_flow_attr attr;
- struct ibv_flow_spec_eth spec;
- } data;
- struct ibv_flow_attr *attr = &data.attr;
- struct ibv_flow_spec_eth *spec = &data.spec;
-
- if (priv->mac_flow)
- mlx4_mac_addr_del(priv);
- /*
- * 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);
- *attr = (struct ibv_flow_attr){
- .type = IBV_FLOW_ATTR_NORMAL,
- .priority = 3,
- .num_of_specs = 1,
- .port = priv->port,
- .flags = 0
- };
- *spec = (struct ibv_flow_spec_eth){
- .type = IBV_FLOW_SPEC_ETH,
- .size = sizeof(*spec),
- .val = {
- .dst_mac = {
- (*mac)[0], (*mac)[1], (*mac)[2],
- (*mac)[3], (*mac)[4], (*mac)[5]
- },
- },
- .mask = {
- .dst_mac = "\xff\xff\xff\xff\xff\xff",
- }
- };
- DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x",
- (void *)priv,
- (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]);
- /* Create related flow. */
- flow = ibv_create_flow(rxq->qp, attr);
- if (flow == NULL) {
- rte_errno = errno ? errno : EINVAL;
- ERROR("%p: flow configuration failed, errno=%d: %s",
- (void *)rxq, rte_errno, strerror(errno));
- return -rte_errno;
- }
- assert(priv->mac_flow == NULL);
- priv->mac_flow = flow;
- return 0;
-}