1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2018 Gaëtan Rivet
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 
5d30ea906Sjfb8856606 #include <string.h>
6d30ea906Sjfb8856606 
7d30ea906Sjfb8856606 #include <rte_class.h>
8d30ea906Sjfb8856606 #include <rte_compat.h>
9d30ea906Sjfb8856606 #include <rte_errno.h>
10d30ea906Sjfb8856606 #include <rte_kvargs.h>
11d30ea906Sjfb8856606 #include <rte_log.h>
12d30ea906Sjfb8856606 
13d30ea906Sjfb8856606 #include "rte_ethdev.h"
14d30ea906Sjfb8856606 #include "rte_ethdev_core.h"
15d30ea906Sjfb8856606 #include "rte_ethdev_driver.h"
16d30ea906Sjfb8856606 #include "ethdev_private.h"
17d30ea906Sjfb8856606 
18d30ea906Sjfb8856606 enum eth_params {
19d30ea906Sjfb8856606 	RTE_ETH_PARAM_MAC,
20d30ea906Sjfb8856606 	RTE_ETH_PARAM_REPRESENTOR,
21d30ea906Sjfb8856606 	RTE_ETH_PARAM_MAX,
22d30ea906Sjfb8856606 };
23d30ea906Sjfb8856606 
24d30ea906Sjfb8856606 static const char * const eth_params_keys[] = {
25d30ea906Sjfb8856606 	[RTE_ETH_PARAM_MAC] = "mac",
26d30ea906Sjfb8856606 	[RTE_ETH_PARAM_REPRESENTOR] = "representor",
27d30ea906Sjfb8856606 	[RTE_ETH_PARAM_MAX] = NULL,
28d30ea906Sjfb8856606 };
29d30ea906Sjfb8856606 
30d30ea906Sjfb8856606 struct eth_dev_match_arg {
31d30ea906Sjfb8856606 	struct rte_device *device;
32d30ea906Sjfb8856606 	struct rte_kvargs *kvlist;
33d30ea906Sjfb8856606 };
34d30ea906Sjfb8856606 
35d30ea906Sjfb8856606 #define eth_dev_match_arg(d, k) \
36d30ea906Sjfb8856606 	(&(const struct eth_dev_match_arg) { \
37d30ea906Sjfb8856606 		.device = (d), \
38d30ea906Sjfb8856606 		.kvlist = (k), \
39d30ea906Sjfb8856606 	})
40d30ea906Sjfb8856606 
41d30ea906Sjfb8856606 static int
eth_mac_cmp(const char * key __rte_unused,const char * value,void * opaque)42d30ea906Sjfb8856606 eth_mac_cmp(const char *key __rte_unused,
43d30ea906Sjfb8856606 		const char *value, void *opaque)
44d30ea906Sjfb8856606 {
45*4418919fSjohnjiang 	struct rte_ether_addr mac;
46d30ea906Sjfb8856606 	const struct rte_eth_dev_data *data = opaque;
47d30ea906Sjfb8856606 	struct rte_eth_dev_info dev_info;
48d30ea906Sjfb8856606 	uint32_t index;
49d30ea906Sjfb8856606 
50d30ea906Sjfb8856606 	/* Parse devargs MAC address. */
51*4418919fSjohnjiang 	if (rte_ether_unformat_addr(value, &mac) < 0)
52d30ea906Sjfb8856606 		return -1; /* invalid devargs value */
53d30ea906Sjfb8856606 
54d30ea906Sjfb8856606 	/* Return 0 if devargs MAC is matching one of the device MACs. */
55d30ea906Sjfb8856606 	rte_eth_dev_info_get(data->port_id, &dev_info);
56d30ea906Sjfb8856606 	for (index = 0; index < dev_info.max_mac_addrs; index++)
57*4418919fSjohnjiang 		if (rte_is_same_ether_addr(&mac, &data->mac_addrs[index]))
58d30ea906Sjfb8856606 			return 0;
59d30ea906Sjfb8856606 	return -1; /* no match */
60d30ea906Sjfb8856606 }
61d30ea906Sjfb8856606 
62d30ea906Sjfb8856606 static int
eth_representor_cmp(const char * key __rte_unused,const char * value,void * opaque)63d30ea906Sjfb8856606 eth_representor_cmp(const char *key __rte_unused,
64d30ea906Sjfb8856606 		const char *value, void *opaque)
65d30ea906Sjfb8856606 {
66d30ea906Sjfb8856606 	int ret;
67d30ea906Sjfb8856606 	char *values;
68d30ea906Sjfb8856606 	const struct rte_eth_dev_data *data = opaque;
69d30ea906Sjfb8856606 	struct rte_eth_devargs representors;
70d30ea906Sjfb8856606 	uint16_t index;
71d30ea906Sjfb8856606 
72d30ea906Sjfb8856606 	if ((data->dev_flags & RTE_ETH_DEV_REPRESENTOR) == 0)
73d30ea906Sjfb8856606 		return -1; /* not a representor port */
74d30ea906Sjfb8856606 
75d30ea906Sjfb8856606 	/* Parse devargs representor values. */
76d30ea906Sjfb8856606 	values = strdup(value);
77d30ea906Sjfb8856606 	if (values == NULL)
78d30ea906Sjfb8856606 		return -1;
79d30ea906Sjfb8856606 	memset(&representors, 0, sizeof(representors));
80d30ea906Sjfb8856606 	ret = rte_eth_devargs_parse_list(values,
81d30ea906Sjfb8856606 			rte_eth_devargs_parse_representor_ports,
82d30ea906Sjfb8856606 			&representors);
83d30ea906Sjfb8856606 	free(values);
84d30ea906Sjfb8856606 	if (ret != 0)
85d30ea906Sjfb8856606 		return -1; /* invalid devargs value */
86d30ea906Sjfb8856606 
87d30ea906Sjfb8856606 	/* Return 0 if representor id is matching one of the values. */
88d30ea906Sjfb8856606 	for (index = 0; index < representors.nb_representor_ports; index++)
89d30ea906Sjfb8856606 		if (data->representor_id ==
90d30ea906Sjfb8856606 				representors.representor_ports[index])
91d30ea906Sjfb8856606 			return 0;
92d30ea906Sjfb8856606 	return -1; /* no match */
93d30ea906Sjfb8856606 }
94d30ea906Sjfb8856606 
95d30ea906Sjfb8856606 static int
eth_dev_match(const struct rte_eth_dev * edev,const void * _arg)96d30ea906Sjfb8856606 eth_dev_match(const struct rte_eth_dev *edev,
97d30ea906Sjfb8856606 	      const void *_arg)
98d30ea906Sjfb8856606 {
99d30ea906Sjfb8856606 	int ret;
100d30ea906Sjfb8856606 	const struct eth_dev_match_arg *arg = _arg;
101d30ea906Sjfb8856606 	const struct rte_kvargs *kvlist = arg->kvlist;
102d30ea906Sjfb8856606 	unsigned int pair;
103d30ea906Sjfb8856606 
104d30ea906Sjfb8856606 	if (edev->state == RTE_ETH_DEV_UNUSED)
105d30ea906Sjfb8856606 		return -1;
106d30ea906Sjfb8856606 	if (arg->device != NULL && arg->device != edev->device)
107d30ea906Sjfb8856606 		return -1;
108d30ea906Sjfb8856606 
109d30ea906Sjfb8856606 	ret = rte_kvargs_process(kvlist,
110d30ea906Sjfb8856606 			eth_params_keys[RTE_ETH_PARAM_MAC],
111d30ea906Sjfb8856606 			eth_mac_cmp, edev->data);
112d30ea906Sjfb8856606 	if (ret != 0)
113d30ea906Sjfb8856606 		return -1;
114d30ea906Sjfb8856606 
115d30ea906Sjfb8856606 	ret = rte_kvargs_process(kvlist,
116d30ea906Sjfb8856606 			eth_params_keys[RTE_ETH_PARAM_REPRESENTOR],
117d30ea906Sjfb8856606 			eth_representor_cmp, edev->data);
118d30ea906Sjfb8856606 	if (ret != 0)
119d30ea906Sjfb8856606 		return -1;
120d30ea906Sjfb8856606 	/* search for representor key */
121d30ea906Sjfb8856606 	for (pair = 0; pair < kvlist->count; pair++) {
122d30ea906Sjfb8856606 		ret = strcmp(kvlist->pairs[pair].key,
123d30ea906Sjfb8856606 				eth_params_keys[RTE_ETH_PARAM_REPRESENTOR]);
124d30ea906Sjfb8856606 		if (ret == 0)
125d30ea906Sjfb8856606 			break; /* there is a representor key */
126d30ea906Sjfb8856606 	}
127d30ea906Sjfb8856606 	/* if no representor key, default is to not match representor ports */
128d30ea906Sjfb8856606 	if (ret != 0)
129d30ea906Sjfb8856606 		if ((edev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0)
130d30ea906Sjfb8856606 			return -1; /* do not match any representor */
131d30ea906Sjfb8856606 
132d30ea906Sjfb8856606 	return 0;
133d30ea906Sjfb8856606 }
134d30ea906Sjfb8856606 
135d30ea906Sjfb8856606 static void *
eth_dev_iterate(const void * start,const char * str,const struct rte_dev_iterator * it)136d30ea906Sjfb8856606 eth_dev_iterate(const void *start,
137d30ea906Sjfb8856606 		const char *str,
138d30ea906Sjfb8856606 		const struct rte_dev_iterator *it)
139d30ea906Sjfb8856606 {
140d30ea906Sjfb8856606 	struct rte_kvargs *kvargs = NULL;
141d30ea906Sjfb8856606 	struct rte_eth_dev *edev = NULL;
142d30ea906Sjfb8856606 	const char * const *valid_keys = NULL;
143d30ea906Sjfb8856606 
144d30ea906Sjfb8856606 	if (str != NULL) {
145d30ea906Sjfb8856606 		if (str[0] == '+') /* no validation of keys */
146d30ea906Sjfb8856606 			str++;
147d30ea906Sjfb8856606 		else
148d30ea906Sjfb8856606 			valid_keys = eth_params_keys;
149d30ea906Sjfb8856606 		kvargs = rte_kvargs_parse(str, valid_keys);
150d30ea906Sjfb8856606 		if (kvargs == NULL) {
151d30ea906Sjfb8856606 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
152d30ea906Sjfb8856606 			rte_errno = EINVAL;
153d30ea906Sjfb8856606 			return NULL;
154d30ea906Sjfb8856606 		}
155d30ea906Sjfb8856606 	}
156d30ea906Sjfb8856606 	edev = eth_find_device(start, eth_dev_match,
157d30ea906Sjfb8856606 			       eth_dev_match_arg(it->device, kvargs));
158d30ea906Sjfb8856606 	rte_kvargs_free(kvargs);
159d30ea906Sjfb8856606 	return edev;
160d30ea906Sjfb8856606 }
161d30ea906Sjfb8856606 
162d30ea906Sjfb8856606 static struct rte_class rte_class_eth = {
163d30ea906Sjfb8856606 	.dev_iterate = eth_dev_iterate,
164d30ea906Sjfb8856606 };
165d30ea906Sjfb8856606 
166d30ea906Sjfb8856606 RTE_REGISTER_CLASS(eth, rte_class_eth);
167