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