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