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