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