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