1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <rte_devargs.h> 6 #include <rte_pci.h> 7 #include <rte_bus_pci.h> 8 #include <rte_kvargs.h> 9 10 #include <cmdline_parse.h> 11 #include <cmdline_parse_etheraddr.h> 12 13 #include "rte_eth_bond.h" 14 #include "rte_eth_bond_private.h" 15 16 const char *pmd_bond_init_valid_arguments[] = { 17 PMD_BOND_SLAVE_PORT_KVARG, 18 PMD_BOND_PRIMARY_SLAVE_KVARG, 19 PMD_BOND_MODE_KVARG, 20 PMD_BOND_XMIT_POLICY_KVARG, 21 PMD_BOND_SOCKET_ID_KVARG, 22 PMD_BOND_MAC_ADDR_KVARG, 23 PMD_BOND_AGG_MODE_KVARG, 24 "driver", 25 NULL 26 }; 27 28 static inline int 29 find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr) 30 { 31 struct rte_pci_device *pci_dev; 32 struct rte_pci_addr *eth_pci_addr; 33 unsigned i; 34 35 RTE_ETH_FOREACH_DEV(i) { 36 pci_dev = RTE_ETH_DEV_TO_PCI(&rte_eth_devices[i]); 37 eth_pci_addr = &pci_dev->addr; 38 39 if (pci_addr->bus == eth_pci_addr->bus && 40 pci_addr->devid == eth_pci_addr->devid && 41 pci_addr->domain == eth_pci_addr->domain && 42 pci_addr->function == eth_pci_addr->function) 43 return i; 44 } 45 return -1; 46 } 47 48 static inline int 49 find_port_id_by_dev_name(const char *name) 50 { 51 unsigned i; 52 53 RTE_ETH_FOREACH_DEV(i) { 54 if (rte_eth_devices[i].data == NULL) 55 continue; 56 57 if (strcmp(rte_eth_devices[i].device->name, name) == 0) 58 return i; 59 } 60 return -1; 61 } 62 63 static inline int 64 bond_pci_addr_cmp(const struct rte_device *dev, const void *_pci_addr) 65 { 66 struct rte_pci_device *pdev; 67 const struct rte_pci_addr *paddr = _pci_addr; 68 69 pdev = RTE_DEV_TO_PCI(*(struct rte_device **)(void *)&dev); 70 return rte_eal_compare_pci_addr(&pdev->addr, paddr); 71 } 72 73 /** 74 * Parses a port identifier string to a port id by pci address, then by name, 75 * and finally port id. 76 */ 77 static inline int 78 parse_port_id(const char *port_str) 79 { 80 struct rte_pci_addr dev_addr; 81 struct rte_bus *pci_bus; 82 struct rte_device *dev; 83 int port_id; 84 85 pci_bus = rte_bus_find_by_name("pci"); 86 if (pci_bus == NULL) { 87 RTE_LOG(ERR, PMD, "unable to find PCI bus\n"); 88 return -1; 89 } 90 91 /* try parsing as pci address, physical devices */ 92 if (pci_bus->parse(port_str, &dev_addr) == 0) { 93 dev = pci_bus->find_device(NULL, bond_pci_addr_cmp, &dev_addr); 94 if (dev == NULL) { 95 RTE_BOND_LOG(ERR, "unable to find PCI device"); 96 return -1; 97 } 98 port_id = find_port_id_by_pci_addr(&dev_addr); 99 if (port_id < 0) 100 return -1; 101 } else { 102 /* try parsing as device name, virtual devices */ 103 port_id = find_port_id_by_dev_name(port_str); 104 if (port_id < 0) { 105 char *end; 106 errno = 0; 107 108 /* try parsing as port id */ 109 port_id = strtol(port_str, &end, 10); 110 if (*end != 0 || errno != 0) 111 return -1; 112 } 113 } 114 115 if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) { 116 RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range", 117 port_str); 118 return -1; 119 } 120 return port_id; 121 } 122 123 int 124 bond_ethdev_parse_slave_port_kvarg(const char *key, 125 const char *value, void *extra_args) 126 { 127 struct bond_ethdev_slave_ports *slave_ports; 128 129 if (value == NULL || extra_args == NULL) 130 return -1; 131 132 slave_ports = extra_args; 133 134 if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) { 135 int port_id = parse_port_id(value); 136 if (port_id < 0) { 137 RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", 138 value); 139 return -1; 140 } else 141 slave_ports->slaves[slave_ports->slave_count++] = 142 port_id; 143 } 144 return 0; 145 } 146 147 int 148 bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused, 149 const char *value, void *extra_args) 150 { 151 uint8_t *mode; 152 char *endptr; 153 154 if (value == NULL || extra_args == NULL) 155 return -1; 156 157 mode = extra_args; 158 159 errno = 0; 160 *mode = strtol(value, &endptr, 10); 161 if (*endptr != 0 || errno != 0) 162 return -1; 163 164 /* validate mode value */ 165 switch (*mode) { 166 case BONDING_MODE_ROUND_ROBIN: 167 case BONDING_MODE_ACTIVE_BACKUP: 168 case BONDING_MODE_BALANCE: 169 case BONDING_MODE_BROADCAST: 170 case BONDING_MODE_8023AD: 171 case BONDING_MODE_TLB: 172 case BONDING_MODE_ALB: 173 return 0; 174 default: 175 RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value); 176 return -1; 177 } 178 } 179 180 int 181 bond_ethdev_parse_slave_agg_mode_kvarg(const char *key __rte_unused, 182 const char *value, void *extra_args) 183 { 184 uint8_t *agg_mode; 185 186 if (value == NULL || extra_args == NULL) 187 return -1; 188 189 agg_mode = extra_args; 190 191 errno = 0; 192 if (strncmp(value, "stable", 6) == 0) 193 *agg_mode = AGG_STABLE; 194 195 if (strncmp(value, "bandwidth", 9) == 0) 196 *agg_mode = AGG_BANDWIDTH; 197 198 if (strncmp(value, "count", 5) == 0) 199 *agg_mode = AGG_COUNT; 200 201 switch (*agg_mode) { 202 case AGG_STABLE: 203 case AGG_BANDWIDTH: 204 case AGG_COUNT: 205 return 0; 206 default: 207 RTE_BOND_LOG(ERR, "Invalid agg mode value stable/bandwidth/count"); 208 return -1; 209 } 210 } 211 212 int 213 bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused, 214 const char *value, void *extra_args) 215 { 216 int socket_id; 217 char *endptr; 218 219 if (value == NULL || extra_args == NULL) 220 return -1; 221 222 errno = 0; 223 socket_id = (uint8_t)strtol(value, &endptr, 10); 224 if (*endptr != 0 || errno != 0) 225 return -1; 226 227 /* validate socket id value */ 228 if (socket_id >= 0) { 229 *(uint8_t *)extra_args = (uint8_t)socket_id; 230 return 0; 231 } 232 return -1; 233 } 234 235 int 236 bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused, 237 const char *value, void *extra_args) 238 { 239 int primary_slave_port_id; 240 241 if (value == NULL || extra_args == NULL) 242 return -1; 243 244 primary_slave_port_id = parse_port_id(value); 245 if (primary_slave_port_id < 0) 246 return -1; 247 248 *(uint16_t *)extra_args = (uint16_t)primary_slave_port_id; 249 250 return 0; 251 } 252 253 int 254 bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused, 255 const char *value, void *extra_args) 256 { 257 uint8_t *xmit_policy; 258 259 if (value == NULL || extra_args == NULL) 260 return -1; 261 262 xmit_policy = extra_args; 263 264 if (strcmp(PMD_BOND_XMIT_POLICY_LAYER2_KVARG, value) == 0) 265 *xmit_policy = BALANCE_XMIT_POLICY_LAYER2; 266 else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER23_KVARG, value) == 0) 267 *xmit_policy = BALANCE_XMIT_POLICY_LAYER23; 268 else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER34_KVARG, value) == 0) 269 *xmit_policy = BALANCE_XMIT_POLICY_LAYER34; 270 else 271 return -1; 272 273 return 0; 274 } 275 276 int 277 bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused, 278 const char *value, void *extra_args) 279 { 280 if (value == NULL || extra_args == NULL) 281 return -1; 282 283 /* Parse MAC */ 284 return cmdline_parse_etheraddr(NULL, value, extra_args, 285 sizeof(struct ether_addr)); 286 } 287 288 int 289 bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, 290 const char *value, void *extra_args) 291 { 292 uint32_t time_ms; 293 char *endptr; 294 295 if (value == NULL || extra_args == NULL) 296 return -1; 297 298 errno = 0; 299 time_ms = (uint32_t)strtol(value, &endptr, 10); 300 if (*endptr != 0 || errno != 0) 301 return -1; 302 303 *(uint32_t *)extra_args = time_ms; 304 305 return 0; 306 } 307