1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <rte_devargs.h> 35 #include <rte_pci.h> 36 #include <rte_bus_pci.h> 37 #include <rte_kvargs.h> 38 39 #include <cmdline_parse.h> 40 #include <cmdline_parse_etheraddr.h> 41 42 #include "rte_eth_bond.h" 43 #include "rte_eth_bond_private.h" 44 45 const char *pmd_bond_init_valid_arguments[] = { 46 PMD_BOND_SLAVE_PORT_KVARG, 47 PMD_BOND_PRIMARY_SLAVE_KVARG, 48 PMD_BOND_MODE_KVARG, 49 PMD_BOND_XMIT_POLICY_KVARG, 50 PMD_BOND_SOCKET_ID_KVARG, 51 PMD_BOND_MAC_ADDR_KVARG, 52 PMD_BOND_AGG_MODE_KVARG, 53 "driver", 54 NULL 55 }; 56 57 static inline int 58 find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr) 59 { 60 struct rte_pci_device *pci_dev; 61 struct rte_pci_addr *eth_pci_addr; 62 unsigned i; 63 64 for (i = 0; i < rte_eth_dev_count(); i++) { 65 pci_dev = RTE_ETH_DEV_TO_PCI(&rte_eth_devices[i]); 66 eth_pci_addr = &pci_dev->addr; 67 68 if (pci_addr->bus == eth_pci_addr->bus && 69 pci_addr->devid == eth_pci_addr->devid && 70 pci_addr->domain == eth_pci_addr->domain && 71 pci_addr->function == eth_pci_addr->function) 72 return i; 73 } 74 return -1; 75 } 76 77 static inline int 78 find_port_id_by_dev_name(const char *name) 79 { 80 unsigned i; 81 82 for (i = 0; i < rte_eth_dev_count(); i++) { 83 if (rte_eth_devices[i].data == NULL) 84 continue; 85 86 if (strcmp(rte_eth_devices[i].device->name, name) == 0) 87 return i; 88 } 89 return -1; 90 } 91 92 static inline int 93 bond_pci_addr_cmp(const struct rte_device *dev, const void *_pci_addr) 94 { 95 struct rte_pci_device *pdev; 96 const struct rte_pci_addr *paddr = _pci_addr; 97 98 pdev = RTE_DEV_TO_PCI(*(struct rte_device **)(void *)&dev); 99 return rte_eal_compare_pci_addr(&pdev->addr, paddr); 100 } 101 102 /** 103 * Parses a port identifier string to a port id by pci address, then by name, 104 * and finally port id. 105 */ 106 static inline int 107 parse_port_id(const char *port_str) 108 { 109 struct rte_pci_addr dev_addr; 110 struct rte_bus *pci_bus; 111 struct rte_device *dev; 112 int port_id; 113 114 pci_bus = rte_bus_find_by_name("pci"); 115 if (pci_bus == NULL) { 116 RTE_LOG(ERR, PMD, "unable to find PCI bus\n"); 117 return -1; 118 } 119 120 /* try parsing as pci address, physical devices */ 121 if (pci_bus->parse(port_str, &dev_addr) == 0) { 122 dev = pci_bus->find_device(NULL, bond_pci_addr_cmp, &dev_addr); 123 if (dev == NULL) { 124 RTE_LOG(ERR, PMD, "unable to find PCI device\n"); 125 return -1; 126 } 127 port_id = find_port_id_by_pci_addr(&dev_addr); 128 if (port_id < 0) 129 return -1; 130 } else { 131 /* try parsing as device name, virtual devices */ 132 port_id = find_port_id_by_dev_name(port_str); 133 if (port_id < 0) { 134 char *end; 135 errno = 0; 136 137 /* try parsing as port id */ 138 port_id = strtol(port_str, &end, 10); 139 if (*end != 0 || errno != 0) 140 return -1; 141 } 142 } 143 144 if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) { 145 RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range", 146 port_str); 147 return -1; 148 } 149 return port_id; 150 } 151 152 int 153 bond_ethdev_parse_slave_port_kvarg(const char *key, 154 const char *value, void *extra_args) 155 { 156 struct bond_ethdev_slave_ports *slave_ports; 157 158 if (value == NULL || extra_args == NULL) 159 return -1; 160 161 slave_ports = extra_args; 162 163 if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) { 164 int port_id = parse_port_id(value); 165 if (port_id < 0) { 166 RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", value); 167 return -1; 168 } else 169 slave_ports->slaves[slave_ports->slave_count++] = 170 port_id; 171 } 172 return 0; 173 } 174 175 int 176 bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused, 177 const char *value, void *extra_args) 178 { 179 uint8_t *mode; 180 char *endptr; 181 182 if (value == NULL || extra_args == NULL) 183 return -1; 184 185 mode = extra_args; 186 187 errno = 0; 188 *mode = strtol(value, &endptr, 10); 189 if (*endptr != 0 || errno != 0) 190 return -1; 191 192 /* validate mode value */ 193 switch (*mode) { 194 case BONDING_MODE_ROUND_ROBIN: 195 case BONDING_MODE_ACTIVE_BACKUP: 196 case BONDING_MODE_BALANCE: 197 case BONDING_MODE_BROADCAST: 198 case BONDING_MODE_8023AD: 199 case BONDING_MODE_TLB: 200 case BONDING_MODE_ALB: 201 return 0; 202 default: 203 RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value); 204 return -1; 205 } 206 } 207 208 int 209 bond_ethdev_parse_slave_agg_mode_kvarg(const char *key __rte_unused, 210 const char *value, void *extra_args) 211 { 212 uint8_t *agg_mode; 213 214 if (value == NULL || extra_args == NULL) 215 return -1; 216 217 agg_mode = extra_args; 218 219 errno = 0; 220 if (strncmp(value, "stable", 6) == 0) 221 *agg_mode = AGG_STABLE; 222 223 if (strncmp(value, "bandwidth", 9) == 0) 224 *agg_mode = AGG_BANDWIDTH; 225 226 if (strncmp(value, "count", 5) == 0) 227 *agg_mode = AGG_COUNT; 228 229 switch (*agg_mode) { 230 case AGG_STABLE: 231 case AGG_BANDWIDTH: 232 case AGG_COUNT: 233 return 0; 234 default: 235 RTE_BOND_LOG(ERR, "Invalid agg mode value stable/bandwidth/count"); 236 return -1; 237 } 238 } 239 240 int 241 bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused, 242 const char *value, void *extra_args) 243 { 244 int socket_id; 245 char *endptr; 246 247 if (value == NULL || extra_args == NULL) 248 return -1; 249 250 errno = 0; 251 socket_id = (uint8_t)strtol(value, &endptr, 10); 252 if (*endptr != 0 || errno != 0) 253 return -1; 254 255 /* validate socket id value */ 256 if (socket_id >= 0) { 257 *(uint8_t *)extra_args = (uint8_t)socket_id; 258 return 0; 259 } 260 return -1; 261 } 262 263 int 264 bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused, 265 const char *value, void *extra_args) 266 { 267 int primary_slave_port_id; 268 269 if (value == NULL || extra_args == NULL) 270 return -1; 271 272 primary_slave_port_id = parse_port_id(value); 273 if (primary_slave_port_id < 0) 274 return -1; 275 276 *(uint16_t *)extra_args = (uint16_t)primary_slave_port_id; 277 278 return 0; 279 } 280 281 int 282 bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused, 283 const char *value, void *extra_args) 284 { 285 uint8_t *xmit_policy; 286 287 if (value == NULL || extra_args == NULL) 288 return -1; 289 290 xmit_policy = extra_args; 291 292 if (strcmp(PMD_BOND_XMIT_POLICY_LAYER2_KVARG, value) == 0) 293 *xmit_policy = BALANCE_XMIT_POLICY_LAYER2; 294 else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER23_KVARG, value) == 0) 295 *xmit_policy = BALANCE_XMIT_POLICY_LAYER23; 296 else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER34_KVARG, value) == 0) 297 *xmit_policy = BALANCE_XMIT_POLICY_LAYER34; 298 else 299 return -1; 300 301 return 0; 302 } 303 304 int 305 bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused, 306 const char *value, void *extra_args) 307 { 308 if (value == NULL || extra_args == NULL) 309 return -1; 310 311 /* Parse MAC */ 312 return cmdline_parse_etheraddr(NULL, value, extra_args, 313 sizeof(struct ether_addr)); 314 } 315 316 int 317 bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, 318 const char *value, void *extra_args) 319 { 320 uint32_t time_ms; 321 char *endptr; 322 323 if (value == NULL || extra_args == NULL) 324 return -1; 325 326 errno = 0; 327 time_ms = (uint32_t)strtol(value, &endptr, 10); 328 if (*endptr != 0 || errno != 0) 329 return -1; 330 331 *(uint32_t *)extra_args = time_ms; 332 333 return 0; 334 } 335