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