]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation | |
7c673cae FG |
3 | */ |
4 | ||
5 | #include <rte_devargs.h> | |
9f95a23c TL |
6 | #include <rte_pci.h> |
7 | #include <rte_bus_pci.h> | |
7c673cae FG |
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, | |
9f95a23c | 23 | PMD_BOND_AGG_MODE_KVARG, |
11fdf7f2 | 24 | "driver", |
7c673cae FG |
25 | NULL |
26 | }; | |
27 | ||
28 | static inline int | |
29 | find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr) | |
30 | { | |
11fdf7f2 | 31 | struct rte_pci_device *pci_dev; |
7c673cae FG |
32 | struct rte_pci_addr *eth_pci_addr; |
33 | unsigned i; | |
34 | ||
9f95a23c TL |
35 | RTE_ETH_FOREACH_DEV(i) { |
36 | pci_dev = RTE_ETH_DEV_TO_PCI(&rte_eth_devices[i]); | |
11fdf7f2 | 37 | eth_pci_addr = &pci_dev->addr; |
7c673cae FG |
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 | ||
9f95a23c | 53 | RTE_ETH_FOREACH_DEV(i) { |
7c673cae FG |
54 | if (rte_eth_devices[i].data == NULL) |
55 | continue; | |
56 | ||
9f95a23c | 57 | if (strcmp(rte_eth_devices[i].device->name, name) == 0) |
7c673cae FG |
58 | return i; |
59 | } | |
60 | return -1; | |
61 | } | |
62 | ||
9f95a23c TL |
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 | ||
7c673cae FG |
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; | |
9f95a23c TL |
81 | struct rte_bus *pci_bus; |
82 | struct rte_device *dev; | |
7c673cae FG |
83 | int port_id; |
84 | ||
9f95a23c TL |
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 | ||
7c673cae | 91 | /* try parsing as pci address, physical devices */ |
9f95a23c TL |
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 | } | |
7c673cae FG |
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 | |
9f95a23c | 124 | bond_ethdev_parse_slave_port_kvarg(const char *key, |
7c673cae FG |
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) { | |
9f95a23c TL |
137 | RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", |
138 | value); | |
7c673cae FG |
139 | return -1; |
140 | } else | |
141 | slave_ports->slaves[slave_ports->slave_count++] = | |
9f95a23c | 142 | port_id; |
7c673cae FG |
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 | ||
9f95a23c TL |
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 | ||
7c673cae FG |
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 | ||
9f95a23c TL |
227 | /* validate socket id value */ |
228 | if (socket_id >= 0) { | |
7c673cae FG |
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 | ||
9f95a23c | 248 | *(uint16_t *)extra_args = (uint16_t)primary_slave_port_id; |
7c673cae FG |
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 | } |