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 "rte_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_data *data = opaque; 69 struct rte_eth_devargs representors; 70 uint16_t index; 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(&representors, 0, sizeof(representors)); 80 ret = rte_eth_devargs_parse_list(values, 81 rte_eth_devargs_parse_representor_ports, 82 &representors); 83 free(values); 84 if (ret != 0) 85 return -1; /* invalid devargs value */ 86 87 /* Return 0 if representor id is matching one of the values. */ 88 for (index = 0; index < representors.nb_representor_ports; index++) 89 if (data->representor_id == 90 representors.representor_ports[index]) 91 return 0; 92 return -1; /* no match */ 93 } 94 95 static int 96 eth_dev_match(const struct rte_eth_dev *edev, 97 const void *_arg) 98 { 99 int ret; 100 const struct eth_dev_match_arg *arg = _arg; 101 const struct rte_kvargs *kvlist = arg->kvlist; 102 unsigned int pair; 103 104 if (edev->state == RTE_ETH_DEV_UNUSED) 105 return -1; 106 if (arg->device != NULL && arg->device != edev->device) 107 return -1; 108 109 ret = rte_kvargs_process(kvlist, 110 eth_params_keys[RTE_ETH_PARAM_MAC], 111 eth_mac_cmp, edev->data); 112 if (ret != 0) 113 return -1; 114 115 ret = rte_kvargs_process(kvlist, 116 eth_params_keys[RTE_ETH_PARAM_REPRESENTOR], 117 eth_representor_cmp, edev->data); 118 if (ret != 0) 119 return -1; 120 /* search for representor key */ 121 for (pair = 0; pair < kvlist->count; pair++) { 122 ret = strcmp(kvlist->pairs[pair].key, 123 eth_params_keys[RTE_ETH_PARAM_REPRESENTOR]); 124 if (ret == 0) 125 break; /* there is a representor key */ 126 } 127 /* if no representor key, default is to not match representor ports */ 128 if (ret != 0) 129 if ((edev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0) 130 return -1; /* do not match any representor */ 131 132 return 0; 133 } 134 135 static void * 136 eth_dev_iterate(const void *start, 137 const char *str, 138 const struct rte_dev_iterator *it) 139 { 140 struct rte_kvargs *kvargs = NULL; 141 struct rte_eth_dev *edev = NULL; 142 const char * const *valid_keys = NULL; 143 144 if (str != NULL) { 145 if (str[0] == '+') /* no validation of keys */ 146 str++; 147 else 148 valid_keys = eth_params_keys; 149 kvargs = rte_kvargs_parse(str, valid_keys); 150 if (kvargs == NULL) { 151 RTE_LOG(ERR, EAL, "cannot parse argument list\n"); 152 rte_errno = EINVAL; 153 return NULL; 154 } 155 } 156 edev = eth_find_device(start, eth_dev_match, 157 eth_dev_match_arg(it->device, kvargs)); 158 rte_kvargs_free(kvargs); 159 return edev; 160 } 161 162 static struct rte_class rte_class_eth = { 163 .dev_iterate = eth_dev_iterate, 164 }; 165 166 RTE_REGISTER_CLASS(eth, rte_class_eth); 167