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