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