199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2018 Gaëtan Rivet
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson
599a2dd95SBruce Richardson #include <string.h>
699a2dd95SBruce Richardson
799a2dd95SBruce Richardson #include <rte_class.h>
899a2dd95SBruce Richardson #include <rte_compat.h>
999a2dd95SBruce Richardson #include <rte_errno.h>
1099a2dd95SBruce Richardson #include <rte_kvargs.h>
1199a2dd95SBruce Richardson #include <rte_log.h>
1299a2dd95SBruce Richardson
1399a2dd95SBruce Richardson #include "rte_ethdev.h"
1499a2dd95SBruce Richardson #include "rte_ethdev_core.h"
1599a2dd95SBruce Richardson #include "ethdev_driver.h"
1699a2dd95SBruce Richardson #include "ethdev_private.h"
1799a2dd95SBruce Richardson
1899a2dd95SBruce Richardson enum eth_params {
1999a2dd95SBruce Richardson RTE_ETH_PARAM_MAC,
2099a2dd95SBruce Richardson RTE_ETH_PARAM_REPRESENTOR,
2199a2dd95SBruce Richardson RTE_ETH_PARAM_MAX,
2299a2dd95SBruce Richardson };
2399a2dd95SBruce Richardson
2499a2dd95SBruce Richardson static const char * const eth_params_keys[] = {
2599a2dd95SBruce Richardson [RTE_ETH_PARAM_MAC] = "mac",
2699a2dd95SBruce Richardson [RTE_ETH_PARAM_REPRESENTOR] = "representor",
2799a2dd95SBruce Richardson [RTE_ETH_PARAM_MAX] = NULL,
2899a2dd95SBruce Richardson };
2999a2dd95SBruce Richardson
3099a2dd95SBruce Richardson struct eth_dev_match_arg {
3199a2dd95SBruce Richardson struct rte_device *device;
3299a2dd95SBruce Richardson struct rte_kvargs *kvlist;
3399a2dd95SBruce Richardson };
3499a2dd95SBruce Richardson
3599a2dd95SBruce Richardson #define eth_dev_match_arg(d, k) \
3699a2dd95SBruce Richardson (&(const struct eth_dev_match_arg) { \
3799a2dd95SBruce Richardson .device = (d), \
3899a2dd95SBruce Richardson .kvlist = (k), \
3999a2dd95SBruce Richardson })
4099a2dd95SBruce Richardson
4199a2dd95SBruce Richardson static int
eth_mac_cmp(const char * key __rte_unused,const char * value,void * opaque)4299a2dd95SBruce Richardson eth_mac_cmp(const char *key __rte_unused,
4399a2dd95SBruce Richardson const char *value, void *opaque)
4499a2dd95SBruce Richardson {
4599a2dd95SBruce Richardson struct rte_ether_addr mac;
4699a2dd95SBruce Richardson const struct rte_eth_dev_data *data = opaque;
4799a2dd95SBruce Richardson struct rte_eth_dev_info dev_info;
4899a2dd95SBruce Richardson uint32_t index;
4999a2dd95SBruce Richardson
5099a2dd95SBruce Richardson /* Parse devargs MAC address. */
5199a2dd95SBruce Richardson if (rte_ether_unformat_addr(value, &mac) < 0)
5299a2dd95SBruce Richardson return -1; /* invalid devargs value */
5399a2dd95SBruce Richardson
5499a2dd95SBruce Richardson /* Return 0 if devargs MAC is matching one of the device MACs. */
5599a2dd95SBruce Richardson rte_eth_dev_info_get(data->port_id, &dev_info);
5699a2dd95SBruce Richardson for (index = 0; index < dev_info.max_mac_addrs; index++)
5799a2dd95SBruce Richardson if (rte_is_same_ether_addr(&mac, &data->mac_addrs[index]))
5899a2dd95SBruce Richardson return 0;
5999a2dd95SBruce Richardson return -1; /* no match */
6099a2dd95SBruce Richardson }
6199a2dd95SBruce Richardson
6299a2dd95SBruce Richardson static int
eth_representor_cmp(const char * key __rte_unused,const char * value,void * opaque)6399a2dd95SBruce Richardson eth_representor_cmp(const char *key __rte_unused,
6499a2dd95SBruce Richardson const char *value, void *opaque)
6599a2dd95SBruce Richardson {
6699a2dd95SBruce Richardson int ret;
6799a2dd95SBruce Richardson char *values;
6899a2dd95SBruce Richardson const struct rte_eth_dev *edev = opaque;
6999a2dd95SBruce Richardson const struct rte_eth_dev_data *data = edev->data;
7099a2dd95SBruce Richardson struct rte_eth_devargs eth_da;
7199a2dd95SBruce Richardson uint16_t id, nc, np, nf, i, c, p, f;
7299a2dd95SBruce Richardson
7399a2dd95SBruce Richardson if ((data->dev_flags & RTE_ETH_DEV_REPRESENTOR) == 0)
7499a2dd95SBruce Richardson return -1; /* not a representor port */
7599a2dd95SBruce Richardson
7699a2dd95SBruce Richardson /* Parse devargs representor values. */
7799a2dd95SBruce Richardson values = strdup(value);
7899a2dd95SBruce Richardson if (values == NULL)
7999a2dd95SBruce Richardson return -1;
8099a2dd95SBruce Richardson memset(ð_da, 0, sizeof(eth_da));
8199a2dd95SBruce Richardson ret = rte_eth_devargs_parse_representor_ports(values, ð_da);
8299a2dd95SBruce Richardson free(values);
8399a2dd95SBruce Richardson if (ret != 0)
8499a2dd95SBruce Richardson return -1; /* invalid devargs value */
8599a2dd95SBruce Richardson
8699a2dd95SBruce Richardson if (eth_da.nb_mh_controllers == 0 && eth_da.nb_ports == 0 &&
8799a2dd95SBruce Richardson eth_da.nb_representor_ports == 0)
8899a2dd95SBruce Richardson return -1;
8999a2dd95SBruce Richardson nc = eth_da.nb_mh_controllers > 0 ? eth_da.nb_mh_controllers : 1;
9099a2dd95SBruce Richardson np = eth_da.nb_ports > 0 ? eth_da.nb_ports : 1;
9199a2dd95SBruce Richardson nf = eth_da.nb_representor_ports > 0 ? eth_da.nb_representor_ports : 1;
9299a2dd95SBruce Richardson
93*5906be5aSAndrew Rybchenko /* Return 0 if representor ID is matching one of the values. */
9499a2dd95SBruce Richardson for (i = 0; i < nc * np * nf; ++i) {
9599a2dd95SBruce Richardson c = i / (np * nf);
9699a2dd95SBruce Richardson p = (i / nf) % np;
9799a2dd95SBruce Richardson f = i % nf;
98ff4e52efSViacheslav Galaktionov if (rte_eth_representor_id_get(edev->data->backer_port_id,
9999a2dd95SBruce Richardson eth_da.type,
10099a2dd95SBruce Richardson eth_da.nb_mh_controllers == 0 ? -1 :
10199a2dd95SBruce Richardson eth_da.mh_controllers[c],
10299a2dd95SBruce Richardson eth_da.nb_ports == 0 ? -1 : eth_da.ports[p],
10399a2dd95SBruce Richardson eth_da.nb_representor_ports == 0 ? -1 :
10499a2dd95SBruce Richardson eth_da.representor_ports[f],
10599a2dd95SBruce Richardson &id) < 0)
10699a2dd95SBruce Richardson continue;
10799a2dd95SBruce Richardson if (data->representor_id == id)
10899a2dd95SBruce Richardson return 0;
10999a2dd95SBruce Richardson }
11099a2dd95SBruce Richardson return -1; /* no match */
11199a2dd95SBruce Richardson }
11299a2dd95SBruce Richardson
11399a2dd95SBruce Richardson static int
eth_dev_match(const struct rte_eth_dev * edev,const void * _arg)11499a2dd95SBruce Richardson eth_dev_match(const struct rte_eth_dev *edev,
11599a2dd95SBruce Richardson const void *_arg)
11699a2dd95SBruce Richardson {
11799a2dd95SBruce Richardson int ret;
11899a2dd95SBruce Richardson const struct eth_dev_match_arg *arg = _arg;
11999a2dd95SBruce Richardson const struct rte_kvargs *kvlist = arg->kvlist;
12099a2dd95SBruce Richardson unsigned int pair;
12199a2dd95SBruce Richardson
12299a2dd95SBruce Richardson if (edev->state == RTE_ETH_DEV_UNUSED)
12399a2dd95SBruce Richardson return -1;
12499a2dd95SBruce Richardson if (arg->device != NULL && arg->device != edev->device)
12599a2dd95SBruce Richardson return -1;
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson ret = rte_kvargs_process(kvlist,
12899a2dd95SBruce Richardson eth_params_keys[RTE_ETH_PARAM_MAC],
12999a2dd95SBruce Richardson eth_mac_cmp, edev->data);
13099a2dd95SBruce Richardson if (ret != 0)
13199a2dd95SBruce Richardson return -1;
13299a2dd95SBruce Richardson
13399a2dd95SBruce Richardson ret = rte_kvargs_process(kvlist,
13499a2dd95SBruce Richardson eth_params_keys[RTE_ETH_PARAM_REPRESENTOR],
13599a2dd95SBruce Richardson eth_representor_cmp, (void *)(uintptr_t)edev);
13699a2dd95SBruce Richardson if (ret != 0)
13799a2dd95SBruce Richardson return -1;
13899a2dd95SBruce Richardson /* search for representor key */
13999a2dd95SBruce Richardson for (pair = 0; pair < kvlist->count; pair++) {
14099a2dd95SBruce Richardson ret = strcmp(kvlist->pairs[pair].key,
14199a2dd95SBruce Richardson eth_params_keys[RTE_ETH_PARAM_REPRESENTOR]);
14299a2dd95SBruce Richardson if (ret == 0)
14399a2dd95SBruce Richardson break; /* there is a representor key */
14499a2dd95SBruce Richardson }
14599a2dd95SBruce Richardson /* if no representor key, default is to not match representor ports */
14699a2dd95SBruce Richardson if (ret != 0)
14799a2dd95SBruce Richardson if ((edev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0)
14899a2dd95SBruce Richardson return -1; /* do not match any representor */
14999a2dd95SBruce Richardson
15099a2dd95SBruce Richardson return 0;
15199a2dd95SBruce Richardson }
15299a2dd95SBruce Richardson
15399a2dd95SBruce Richardson static void *
eth_dev_iterate(const void * start,const char * str,const struct rte_dev_iterator * it)15499a2dd95SBruce Richardson eth_dev_iterate(const void *start,
15599a2dd95SBruce Richardson const char *str,
15699a2dd95SBruce Richardson const struct rte_dev_iterator *it)
15799a2dd95SBruce Richardson {
15899a2dd95SBruce Richardson struct rte_kvargs *kvargs = NULL;
15999a2dd95SBruce Richardson struct rte_eth_dev *edev = NULL;
16099a2dd95SBruce Richardson const char * const *valid_keys = NULL;
16199a2dd95SBruce Richardson
16299a2dd95SBruce Richardson if (str != NULL) {
16399a2dd95SBruce Richardson if (str[0] == '+') /* no validation of keys */
16499a2dd95SBruce Richardson str++;
16599a2dd95SBruce Richardson else
16699a2dd95SBruce Richardson valid_keys = eth_params_keys;
16799a2dd95SBruce Richardson kvargs = rte_kvargs_parse(str, valid_keys);
16899a2dd95SBruce Richardson if (kvargs == NULL) {
16999a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "cannot parse argument list\n");
17099a2dd95SBruce Richardson rte_errno = EINVAL;
17199a2dd95SBruce Richardson return NULL;
17299a2dd95SBruce Richardson }
17399a2dd95SBruce Richardson }
17499a2dd95SBruce Richardson edev = eth_find_device(start, eth_dev_match,
17599a2dd95SBruce Richardson eth_dev_match_arg(it->device, kvargs));
17699a2dd95SBruce Richardson rte_kvargs_free(kvargs);
17799a2dd95SBruce Richardson return edev;
17899a2dd95SBruce Richardson }
17999a2dd95SBruce Richardson
18099a2dd95SBruce Richardson static struct rte_class rte_class_eth = {
18199a2dd95SBruce Richardson .dev_iterate = eth_dev_iterate,
18299a2dd95SBruce Richardson };
18399a2dd95SBruce Richardson
18499a2dd95SBruce Richardson RTE_REGISTER_CLASS(eth, rte_class_eth);
185