15129044dSC.J. Collier/*-
25129044dSC.J. Collier *   BSD LICENSE
35129044dSC.J. Collier *
45129044dSC.J. Collier *   Copyright 2015 6WIND S.A.
55129044dSC.J. Collier *   Copyright 2015 Mellanox.
65129044dSC.J. Collier *
75129044dSC.J. Collier *   Redistribution and use in source and binary forms, with or without
85129044dSC.J. Collier *   modification, are permitted provided that the following conditions
95129044dSC.J. Collier *   are met:
105129044dSC.J. Collier *
115129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
125129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
135129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
145129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in
155129044dSC.J. Collier *       the documentation and/or other materials provided with the
165129044dSC.J. Collier *       distribution.
175129044dSC.J. Collier *     * Neither the name of 6WIND S.A. nor the names of its
185129044dSC.J. Collier *       contributors may be used to endorse or promote products derived
195129044dSC.J. Collier *       from this software without specific prior written permission.
205129044dSC.J. Collier *
215129044dSC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225129044dSC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235129044dSC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245129044dSC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255129044dSC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265129044dSC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275129044dSC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285129044dSC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295129044dSC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305129044dSC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315129044dSC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier#include <stddef.h>
355129044dSC.J. Collier#include <assert.h>
365129044dSC.J. Collier#include <stdint.h>
375129044dSC.J. Collier#include <string.h>
385129044dSC.J. Collier#include <inttypes.h>
395129044dSC.J. Collier#include <errno.h>
405129044dSC.J. Collier#include <netinet/in.h>
415129044dSC.J. Collier#include <sys/ioctl.h>
425129044dSC.J. Collier#include <arpa/inet.h>
435129044dSC.J. Collier
445129044dSC.J. Collier/* Verbs header. */
455129044dSC.J. Collier/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
465129044dSC.J. Collier#ifdef PEDANTIC
47c300e355SChristian Ehrhardt#pragma GCC diagnostic ignored "-Wpedantic"
485129044dSC.J. Collier#endif
495129044dSC.J. Collier#include <infiniband/verbs.h>
505129044dSC.J. Collier#ifdef PEDANTIC
51c300e355SChristian Ehrhardt#pragma GCC diagnostic error "-Wpedantic"
525129044dSC.J. Collier#endif
535129044dSC.J. Collier
545129044dSC.J. Collier/* DPDK headers don't like -pedantic. */
555129044dSC.J. Collier#ifdef PEDANTIC
56c300e355SChristian Ehrhardt#pragma GCC diagnostic ignored "-Wpedantic"
575129044dSC.J. Collier#endif
585129044dSC.J. Collier#include <rte_ether.h>
595129044dSC.J. Collier#include <rte_ethdev.h>
605129044dSC.J. Collier#include <rte_common.h>
615129044dSC.J. Collier#ifdef PEDANTIC
62c300e355SChristian Ehrhardt#pragma GCC diagnostic error "-Wpedantic"
635129044dSC.J. Collier#endif
645129044dSC.J. Collier
655129044dSC.J. Collier#include "mlx5.h"
665129044dSC.J. Collier#include "mlx5_utils.h"
675129044dSC.J. Collier#include "mlx5_rxtx.h"
685129044dSC.J. Collier#include "mlx5_defs.h"
695129044dSC.J. Collier
705129044dSC.J. Collier/**
715129044dSC.J. Collier * Get MAC address by querying netdevice.
725129044dSC.J. Collier *
735129044dSC.J. Collier * @param[in] priv
745129044dSC.J. Collier *   struct priv for the requested device.
755129044dSC.J. Collier * @param[out] mac
765129044dSC.J. Collier *   MAC address output buffer.
775129044dSC.J. Collier *
785129044dSC.J. Collier * @return
795129044dSC.J. Collier *   0 on success, -1 on failure and errno is set.
805129044dSC.J. Collier */
815129044dSC.J. Collierint
825129044dSC.J. Collierpriv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN])
835129044dSC.J. Collier{
845129044dSC.J. Collier	struct ifreq request;
855129044dSC.J. Collier
865129044dSC.J. Collier	if (priv_ifreq(priv, SIOCGIFHWADDR, &request))
875129044dSC.J. Collier		return -1;
885129044dSC.J. Collier	memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
895129044dSC.J. Collier	return 0;
905129044dSC.J. Collier}
915129044dSC.J. Collier
925129044dSC.J. Collier/**
935129044dSC.J. Collier * Delete MAC flow steering rule.
945129044dSC.J. Collier *
955129044dSC.J. Collier * @param hash_rxq
965129044dSC.J. Collier *   Pointer to hash RX queue structure.
975129044dSC.J. Collier * @param mac_index
985129044dSC.J. Collier *   MAC address index.
995129044dSC.J. Collier * @param vlan_index
1005129044dSC.J. Collier *   VLAN index to use.
1015129044dSC.J. Collier */
1025129044dSC.J. Collierstatic void
1035129044dSC.J. Collierhash_rxq_del_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
1045129044dSC.J. Collier		      unsigned int vlan_index)
1055129044dSC.J. Collier{
1065129044dSC.J. Collier#ifndef NDEBUG
1075129044dSC.J. Collier	const uint8_t (*mac)[ETHER_ADDR_LEN] =
1085129044dSC.J. Collier		(const uint8_t (*)[ETHER_ADDR_LEN])
1095129044dSC.J. Collier		hash_rxq->priv->mac[mac_index].addr_bytes;
1105129044dSC.J. Collier#endif
1115129044dSC.J. Collier
1125129044dSC.J. Collier	assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
1135129044dSC.J. Collier	assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
1145129044dSC.J. Collier	if (hash_rxq->mac_flow[mac_index][vlan_index] == NULL)
1155129044dSC.J. Collier		return;
1165129044dSC.J. Collier	DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
1175129044dSC.J. Collier	      " VLAN index %u",
1185129044dSC.J. Collier	      (void *)hash_rxq,
1195129044dSC.J. Collier	      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
1205129044dSC.J. Collier	      mac_index,
1215129044dSC.J. Collier	      vlan_index);
1225129044dSC.J. Collier	claim_zero(ibv_exp_destroy_flow(hash_rxq->mac_flow
1235129044dSC.J. Collier					[mac_index][vlan_index]));
1245129044dSC.J. Collier	hash_rxq->mac_flow[mac_index][vlan_index] = NULL;
1255129044dSC.J. Collier}
1265129044dSC.J. Collier
1275129044dSC.J. Collier/**
1285129044dSC.J. Collier * Unregister a MAC address from a hash RX queue.
1295129044dSC.J. Collier *
1305129044dSC.J. Collier * @param hash_rxq
1315129044dSC.J. Collier *   Pointer to hash RX queue structure.
1325129044dSC.J. Collier * @param mac_index
1335129044dSC.J. Collier *   MAC address index.
1345129044dSC.J. Collier */
1355129044dSC.J. Collierstatic void
1365129044dSC.J. Collierhash_rxq_mac_addr_del(struct hash_rxq *hash_rxq, unsigned int mac_index)
1375129044dSC.J. Collier{
1385129044dSC.J. Collier	unsigned int i;
1395129044dSC.J. Collier
1405129044dSC.J. Collier	assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
1415129044dSC.J. Collier	for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow[mac_index])); ++i)
1425129044dSC.J. Collier		hash_rxq_del_mac_flow(hash_rxq, mac_index, i);
1435129044dSC.J. Collier}
1445129044dSC.J. Collier
1455129044dSC.J. Collier/**
1465129044dSC.J. Collier * Unregister all MAC addresses from a hash RX queue.
1475129044dSC.J. Collier *
1485129044dSC.J. Collier * @param hash_rxq
1495129044dSC.J. Collier *   Pointer to hash RX queue structure.
1505129044dSC.J. Collier */
1515129044dSC.J. Colliervoid
1525129044dSC.J. Collierhash_rxq_mac_addrs_del(struct hash_rxq *hash_rxq)
1535129044dSC.J. Collier{
1545129044dSC.J. Collier	unsigned int i;
1555129044dSC.J. Collier
1565129044dSC.J. Collier	for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow)); ++i)
1575129044dSC.J. Collier		hash_rxq_mac_addr_del(hash_rxq, i);
1585129044dSC.J. Collier}
1595129044dSC.J. Collier
1605129044dSC.J. Collier/**
1615129044dSC.J. Collier * Unregister a MAC address.
1625129044dSC.J. Collier *
1635129044dSC.J. Collier * This is done for each hash RX queue.
1645129044dSC.J. Collier *
1655129044dSC.J. Collier * @param priv
1665129044dSC.J. Collier *   Pointer to private structure.
1675129044dSC.J. Collier * @param mac_index
1685129044dSC.J. Collier *   MAC address index.
1695129044dSC.J. Collier */
1705129044dSC.J. Collierstatic void
1715129044dSC.J. Collierpriv_mac_addr_del(struct priv *priv, unsigned int mac_index)
1725129044dSC.J. Collier{
1735129044dSC.J. Collier	unsigned int i;
1745129044dSC.J. Collier
1755129044dSC.J. Collier	assert(mac_index < RTE_DIM(priv->mac));
1765129044dSC.J. Collier	if (!BITFIELD_ISSET(priv->mac_configured, mac_index))
1775129044dSC.J. Collier		return;
1785129044dSC.J. Collier	for (i = 0; (i != priv->hash_rxqs_n); ++i)
1795129044dSC.J. Collier		hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[i], mac_index);
1805129044dSC.J. Collier	BITFIELD_RESET(priv->mac_configured, mac_index);
1815129044dSC.J. Collier}
1825129044dSC.J. Collier
1835129044dSC.J. Collier/**
1845129044dSC.J. Collier * Unregister all MAC addresses from all hash RX queues.
1855129044dSC.J. Collier *
1865129044dSC.J. Collier * @param priv
1875129044dSC.J. Collier *   Pointer to private structure.
1885129044dSC.J. Collier */
1895129044dSC.J. Colliervoid
1905129044dSC.J. Collierpriv_mac_addrs_disable(struct priv *priv)
1915129044dSC.J. Collier{
1925129044dSC.J. Collier	unsigned int i;
1935129044dSC.J. Collier
1945129044dSC.J. Collier	for (i = 0; (i != priv->hash_rxqs_n); ++i)
1955129044dSC.J. Collier		hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[i]);
1965129044dSC.J. Collier}
1975129044dSC.J. Collier
1985129044dSC.J. Collier/**
1995129044dSC.J. Collier * DPDK callback to remove a MAC address.
2005129044dSC.J. Collier *
2015129044dSC.J. Collier * @param dev
2025129044dSC.J. Collier *   Pointer to Ethernet device structure.
2035129044dSC.J. Collier * @param index
2045129044dSC.J. Collier *   MAC address index.
2055129044dSC.J. Collier */
2065129044dSC.J. Colliervoid
2075129044dSC.J. Colliermlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
2085129044dSC.J. Collier{
2095129044dSC.J. Collier	struct priv *priv = dev->data->dev_private;
2105129044dSC.J. Collier
2115129044dSC.J. Collier	if (mlx5_is_secondary())
2125129044dSC.J. Collier		return;
2135129044dSC.J. Collier
2145129044dSC.J. Collier	priv_lock(priv);
2155129044dSC.J. Collier	DEBUG("%p: removing MAC address from index %" PRIu32,
2165129044dSC.J. Collier	      (void *)dev, index);
2175129044dSC.J. Collier	if (index >= RTE_DIM(priv->mac))
2185129044dSC.J. Collier		goto end;
2195129044dSC.J. Collier	priv_mac_addr_del(priv, index);
2205129044dSC.J. Collierend:
2215129044dSC.J. Collier	priv_unlock(priv);
2225129044dSC.J. Collier}
2235129044dSC.J. Collier
2245129044dSC.J. Collier/**
2255129044dSC.J. Collier * Add MAC flow steering rule.
2265129044dSC.J. Collier *
2275129044dSC.J. Collier * @param hash_rxq
2285129044dSC.J. Collier *   Pointer to hash RX queue structure.
2295129044dSC.J. Collier * @param mac_index
2305129044dSC.J. Collier *   MAC address index to register.
2315129044dSC.J. Collier * @param vlan_index
2325129044dSC.J. Collier *   VLAN index to use.
2335129044dSC.J. Collier *
2345129044dSC.J. Collier * @return
2355129044dSC.J. Collier *   0 on success, errno value on failure.
2365129044dSC.J. Collier */
2375129044dSC.J. Collierstatic int
2385129044dSC.J. Collierhash_rxq_add_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
2395129044dSC.J. Collier		      unsigned int vlan_index)
2405129044dSC.J. Collier{
2415129044dSC.J. Collier	struct ibv_exp_flow *flow;
2425129044dSC.J. Collier	struct priv *priv = hash_rxq->priv;
2435129044dSC.J. Collier	const uint8_t (*mac)[ETHER_ADDR_LEN] =
2445129044dSC.J. Collier			(const uint8_t (*)[ETHER_ADDR_LEN])
2455129044dSC.J. Collier			priv->mac[mac_index].addr_bytes;
2465129044dSC.J. Collier	FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
2475129044dSC.J. Collier	struct ibv_exp_flow_attr *attr = &data->attr;
2485129044dSC.J. Collier	struct ibv_exp_flow_spec_eth *spec = &data->spec;
2495129044dSC.J. Collier	unsigned int vlan_enabled = !!priv->vlan_filter_n;
2505129044dSC.J. Collier	unsigned int vlan_id = priv->vlan_filter[vlan_index];
2515129044dSC.J. Collier
2525129044dSC.J. Collier	assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
2535129044dSC.J. Collier	assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
2545129044dSC.J. Collier	if (hash_rxq->mac_flow[mac_index][vlan_index] != NULL)
2555129044dSC.J. Collier		return 0;
2565129044dSC.J. Collier	/*
2575129044dSC.J. Collier	 * No padding must be inserted by the compiler between attr and spec.
2585129044dSC.J. Collier	 * This layout is expected by libibverbs.
2595129044dSC.J. Collier	 */
2605129044dSC.J. Collier	assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
2615129044dSC.J. Collier	priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
2625129044dSC.J. Collier	/* The first specification must be Ethernet. */
2635129044dSC.J. Collier	assert(spec->type == IBV_EXP_FLOW_SPEC_ETH);
2645129044dSC.J. Collier	assert(spec->size == sizeof(*spec));
2655129044dSC.J. Collier	*spec = (struct ibv_exp_flow_spec_eth){
2665129044dSC.J. Collier		.type = IBV_EXP_FLOW_SPEC_ETH,
2675129044dSC.J. Collier		.size = sizeof(*spec),
2685129044dSC.J. Collier		.val = {
2695129044dSC.J. Collier			.dst_mac = {
2705129044dSC.J. Collier				(*mac)[0], (*mac)[1], (*mac)[2],
2715129044dSC.J. Collier				(*mac)[3], (*mac)[4], (*mac)[5]
2725129044dSC.J. Collier			},
2735129044dSC.J. Collier			.vlan_tag = (vlan_enabled ? htons(vlan_id) : 0),
2745129044dSC.J. Collier		},
2755129044dSC.J. Collier		.mask = {
2765129044dSC.J. Collier			.dst_mac = "\xff\xff\xff\xff\xff\xff",
2775129044dSC.J. Collier			.vlan_tag = (vlan_enabled ? htons(0xfff) : 0),
2785129044dSC.J. Collier		},
2795129044dSC.J. Collier	};
2805129044dSC.J. Collier	DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
2815129044dSC.J. Collier	      " VLAN index %u filtering %s, ID %u",
2825129044dSC.J. Collier	      (void *)hash_rxq,
2835129044dSC.J. Collier	      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
2845129044dSC.J. Collier	      mac_index,
2855129044dSC.J. Collier	      vlan_index,
2865129044dSC.J. Collier	      (vlan_enabled ? "enabled" : "disabled"),
2875129044dSC.J. Collier	      vlan_id);
2885129044dSC.J. Collier	/* Create related flow. */
2895129044dSC.J. Collier	errno = 0;
2905129044dSC.J. Collier	flow = ibv_exp_create_flow(hash_rxq->qp, attr);
2915129044dSC.J. Collier	if (flow == NULL) {
2925129044dSC.J. Collier		/* It's not clear whether errno is always set in this case. */
2935129044dSC.J. Collier		ERROR("%p: flow configuration failed, errno=%d: %s",
2945129044dSC.J. Collier		      (void *)hash_rxq, errno,
2955129044dSC.J. Collier		      (errno ? strerror(errno) : "Unknown error"));
2965129044dSC.J. Collier		if (errno)
2975129044dSC.J. Collier			return errno;
2985129044dSC.J. Collier		return EINVAL;
2995129044dSC.J. Collier	}
3005129044dSC.J. Collier	hash_rxq->mac_flow[mac_index][vlan_index] = flow;
3015129044dSC.J. Collier	return 0;
3025129044dSC.J. Collier}
3035129044dSC.J. Collier
3045129044dSC.J. Collier/**
3055129044dSC.J. Collier * Register a MAC address in a hash RX queue.
3065129044dSC.J. Collier *
3075129044dSC.J. Collier * @param hash_rxq
3085129044dSC.J. Collier *   Pointer to hash RX queue structure.
3095129044dSC.J. Collier * @param mac_index
3105129044dSC.J. Collier *   MAC address index to register.
3115129044dSC.J. Collier *
3125129044dSC.J. Collier * @return
3135129044dSC.J. Collier *   0 on success, errno value on failure.
3145129044dSC.J. Collier */
3155129044dSC.J. Collierstatic int
3165129044dSC.J. Collierhash_rxq_mac_addr_add(struct hash_rxq *hash_rxq, unsigned int mac_index)
3175129044dSC.J. Collier{
3185129044dSC.J. Collier	struct priv *priv = hash_rxq->priv;
3195129044dSC.J. Collier	unsigned int i = 0;
3205129044dSC.J. Collier	int ret;
3215129044dSC.J. Collier
3225129044dSC.J. Collier	assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
3235129044dSC.J. Collier	assert(RTE_DIM(hash_rxq->mac_flow[mac_index]) ==
3245129044dSC.J. Collier	       RTE_DIM(priv->vlan_filter));
3255129044dSC.J. Collier	/* Add a MAC address for each VLAN filter, or at least once. */
3265129044dSC.J. Collier	do {
3275129044dSC.J. Collier		ret = hash_rxq_add_mac_flow(hash_rxq, mac_index, i);
3285129044dSC.J. Collier		if (ret) {
3295129044dSC.J. Collier			/* Failure, rollback. */
3305129044dSC.J. Collier			while (i != 0)
3315129044dSC.J. Collier				hash_rxq_del_mac_flow(hash_rxq, mac_index,
3325129044dSC.J. Collier						      --i);
3335129044dSC.J. Collier			return ret;
3345129044dSC.J. Collier		}
3355129044dSC.J. Collier	} while (++i < priv->vlan_filter_n);
3365129044dSC.J. Collier	return 0;
3375129044dSC.J. Collier}
3385129044dSC.J. Collier
3395129044dSC.J. Collier/**
3405129044dSC.J. Collier * Register all MAC addresses in a hash RX queue.
3415129044dSC.J. Collier *
3425129044dSC.J. Collier * @param hash_rxq
3435129044dSC.J. Collier *   Pointer to hash RX queue structure.
3445129044dSC.J. Collier *
3455129044dSC.J. Collier * @return
3465129044dSC.J. Collier *   0 on success, errno value on failure.
3475129044dSC.J. Collier */
3485129044dSC.J. Collierint
3495129044dSC.J. Collierhash_rxq_mac_addrs_add(struct hash_rxq *hash_rxq)
3505129044dSC.J. Collier{
3515129044dSC.J. Collier	struct priv *priv = hash_rxq->priv;
3525129044dSC.J. Collier	unsigned int i;
3535129044dSC.J. Collier	int ret;
3545129044dSC.J. Collier
3555129044dSC.J. Collier	assert(RTE_DIM(priv->mac) == RTE_DIM(hash_rxq->mac_flow));
3565129044dSC.J. Collier	for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
3575129044dSC.J. Collier		if (!BITFIELD_ISSET(priv->mac_configured, i))
3585129044dSC.J. Collier			continue;
3595129044dSC.J. Collier		ret = hash_rxq_mac_addr_add(hash_rxq, i);
3605129044dSC.J. Collier		if (!ret)
3615129044dSC.J. Collier			continue;
3625129044dSC.J. Collier		/* Failure, rollback. */
3635129044dSC.J. Collier		while (i != 0)
3645129044dSC.J. Collier			hash_rxq_mac_addr_del(hash_rxq, --i);
3655129044dSC.J. Collier		assert(ret > 0);
3665129044dSC.J. Collier		return ret;
3675129044dSC.J. Collier	}
3685129044dSC.J. Collier	return 0;
3695129044dSC.J. Collier}
3705129044dSC.J. Collier
3715129044dSC.J. Collier/**
3725129044dSC.J. Collier * Register a MAC address.
3735129044dSC.J. Collier *
3745129044dSC.J. Collier * This is done for each hash RX queue.
3755129044dSC.J. Collier *
3765129044dSC.J. Collier * @param priv
3775129044dSC.J. Collier *   Pointer to private structure.
3785129044dSC.J. Collier * @param mac_index
3795129044dSC.J. Collier *   MAC address index to use.
3805129044dSC.J. Collier * @param mac
3815129044dSC.J. Collier *   MAC address to register.
3825129044dSC.J. Collier *
3835129044dSC.J. Collier * @return
3845129044dSC.J. Collier *   0 on success, errno value on failure.
3855129044dSC.J. Collier */
3865129044dSC.J. Collierint
3875129044dSC.J. Collierpriv_mac_addr_add(struct priv *priv, unsigned int mac_index,
3885129044dSC.J. Collier		  const uint8_t (*mac)[ETHER_ADDR_LEN])
3895129044dSC.J. Collier{
3905129044dSC.J. Collier	unsigned int i;
3915129044dSC.J. Collier	int ret;
3925129044dSC.J. Collier
3935129044dSC.J. Collier	assert(mac_index < RTE_DIM(priv->mac));
3945129044dSC.J. Collier	/* First, make sure this address isn't already configured. */
3955129044dSC.J. Collier	for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
3965129044dSC.J. Collier		/* Skip this index, it's going to be reconfigured. */
3975129044dSC.J. Collier		if (i == mac_index)
3985129044dSC.J. Collier			continue;
3995129044dSC.J. Collier		if (!BITFIELD_ISSET(priv->mac_configured, i))
4005129044dSC.J. Collier			continue;
4015129044dSC.J. Collier		if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac)))
4025129044dSC.J. Collier			continue;
4035129044dSC.J. Collier		/* Address already configured elsewhere, return with error. */
4045129044dSC.J. Collier		return EADDRINUSE;
4055129044dSC.J. Collier	}
4065129044dSC.J. Collier	if (BITFIELD_ISSET(priv->mac_configured, mac_index))
4075129044dSC.J. Collier		priv_mac_addr_del(priv, mac_index);
4085129044dSC.J. Collier	priv->mac[mac_index] = (struct ether_addr){
4095129044dSC.J. Collier		{
4105129044dSC.J. Collier			(*mac)[0], (*mac)[1], (*mac)[2],
4115129044dSC.J. Collier			(*mac)[3], (*mac)[4], (*mac)[5]
4125129044dSC.J. Collier		}
4135129044dSC.J. Collier	};
4145129044dSC.J. Collier	if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
4155129044dSC.J. Collier		goto end;
4165129044dSC.J. Collier	for (i = 0; (i != priv->hash_rxqs_n); ++i) {
4175129044dSC.J. Collier		ret = hash_rxq_mac_addr_add(&(*priv->hash_rxqs)[i], mac_index);
4185129044dSC.J. Collier		if (!ret)
4195129044dSC.J. Collier			continue;
4205129044dSC.J. Collier		/* Failure, rollback. */
4215129044dSC.J. Collier		while (i != 0)
4225129044dSC.J. Collier			hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[--i],
4235129044dSC.J. Collier					      mac_index);
4245129044dSC.J. Collier		return ret;
4255129044dSC.J. Collier	}
4265129044dSC.J. Collierend:
4275129044dSC.J. Collier	BITFIELD_SET(priv->mac_configured, mac_index);
4285129044dSC.J. Collier	return 0;
4295129044dSC.J. Collier}
4305129044dSC.J. Collier
4315129044dSC.J. Collier/**
4325129044dSC.J. Collier * Register all MAC addresses in all hash RX queues.
4335129044dSC.J. Collier *
4345129044dSC.J. Collier * @param priv
4355129044dSC.J. Collier *   Pointer to private structure.
4365129044dSC.J. Collier *
4375129044dSC.J. Collier * @return
4385129044dSC.J. Collier *   0 on success, errno value on failure.
4395129044dSC.J. Collier */
4405129044dSC.J. Collierint
4415129044dSC.J. Collierpriv_mac_addrs_enable(struct priv *priv)
4425129044dSC.J. Collier{
4435129044dSC.J. Collier	unsigned int i;
4445129044dSC.J. Collier	int ret;
4455129044dSC.J. Collier
4465129044dSC.J. Collier	if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
4475129044dSC.J. Collier		return 0;
4485129044dSC.J. Collier	for (i = 0; (i != priv->hash_rxqs_n); ++i) {
4495129044dSC.J. Collier		ret = hash_rxq_mac_addrs_add(&(*priv->hash_rxqs)[i]);
4505129044dSC.J. Collier		if (!ret)
4515129044dSC.J. Collier			continue;
4525129044dSC.J. Collier		/* Failure, rollback. */
4535129044dSC.J. Collier		while (i != 0)
4545129044dSC.J. Collier			hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[--i]);
4555129044dSC.J. Collier		assert(ret > 0);
4565129044dSC.J. Collier		return ret;
4575129044dSC.J. Collier	}
4585129044dSC.J. Collier	return 0;
4595129044dSC.J. Collier}
4605129044dSC.J. Collier
4615129044dSC.J. Collier/**
4625129044dSC.J. Collier * DPDK callback to add a MAC address.
4635129044dSC.J. Collier *
4645129044dSC.J. Collier * @param dev
4655129044dSC.J. Collier *   Pointer to Ethernet device structure.
4665129044dSC.J. Collier * @param mac_addr
4675129044dSC.J. Collier *   MAC address to register.
4685129044dSC.J. Collier * @param index
4695129044dSC.J. Collier *   MAC address index.
4705129044dSC.J. Collier * @param vmdq
4715129044dSC.J. Collier *   VMDq pool index to associate address with (ignored).
4725129044dSC.J. Collier */
4735129044dSC.J. Colliervoid
4745129044dSC.J. Colliermlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
4755129044dSC.J. Collier		  uint32_t index, uint32_t vmdq)
4765129044dSC.J. Collier{
4775129044dSC.J. Collier	struct priv *priv = dev->data->dev_private;
4785129044dSC.J. Collier
4795129044dSC.J. Collier	if (mlx5_is_secondary())
4805129044dSC.J. Collier		return;
4815129044dSC.J. Collier
4825129044dSC.J. Collier	(void)vmdq;
4835129044dSC.J. Collier	priv_lock(priv);
4845129044dSC.J. Collier	DEBUG("%p: adding MAC address at index %" PRIu32,
4855129044dSC.J. Collier	      (void *)dev, index);
4865129044dSC.J. Collier	if (index >= RTE_DIM(priv->mac))
4875129044dSC.J. Collier		goto end;
4885129044dSC.J. Collier	priv_mac_addr_add(priv, index,
4895129044dSC.J. Collier			  (const uint8_t (*)[ETHER_ADDR_LEN])
4905129044dSC.J. Collier			  mac_addr->addr_bytes);
4915129044dSC.J. Collierend:
4925129044dSC.J. Collier	priv_unlock(priv);
4935129044dSC.J. Collier}
4945129044dSC.J. Collier
4955129044dSC.J. Collier/**
4965129044dSC.J. Collier * DPDK callback to set primary MAC address.
4975129044dSC.J. Collier *
4985129044dSC.J. Collier * @param dev
4995129044dSC.J. Collier *   Pointer to Ethernet device structure.
5005129044dSC.J. Collier * @param mac_addr
5015129044dSC.J. Collier *   MAC address to register.
5025129044dSC.J. Collier */
5035129044dSC.J. Colliervoid
5045129044dSC.J. Colliermlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
5055129044dSC.J. Collier{
5065129044dSC.J. Collier	DEBUG("%p: setting primary MAC address", (void *)dev);
5075129044dSC.J. Collier	mlx5_mac_addr_remove(dev, 0);
5085129044dSC.J. Collier	mlx5_mac_addr_add(dev, mac_addr, 0, 0);
5095129044dSC.J. Collier}
510