Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2017 Intel Corporation
3 : : */
4 : : #include <stdlib.h>
5 : : #include <stdbool.h>
6 : : #include <netinet/in.h>
7 : :
8 : : #include <rte_mbuf.h>
9 : : #include <rte_malloc.h>
10 : : #include <ethdev_driver.h>
11 : : #include <ethdev_vdev.h>
12 : : #include <rte_tcp.h>
13 : : #include <rte_udp.h>
14 : : #include <rte_ip.h>
15 : : #include <rte_ip_frag.h>
16 : : #include <rte_devargs.h>
17 : : #include <rte_kvargs.h>
18 : : #include <bus_vdev_driver.h>
19 : : #include <rte_alarm.h>
20 : : #include <rte_cycles.h>
21 : : #include <rte_string_fns.h>
22 : :
23 : : #include "rte_eth_bond.h"
24 : : #include "eth_bond_private.h"
25 : : #include "eth_bond_8023ad_private.h"
26 : :
27 : : #define REORDER_PERIOD_MS 10
28 : : #define DEFAULT_POLLING_INTERVAL_10_MS (10)
29 : : #define BOND_MAX_MAC_ADDRS 16
30 : :
31 : : #define HASH_L4_PORTS(h) ((h)->src_port ^ (h)->dst_port)
32 : :
33 : : /* Table for statistics in mode 5 TLB */
34 : : static uint64_t tlb_last_obytets[RTE_MAX_ETHPORTS];
35 : :
36 : : static inline size_t
37 : : get_vlan_offset(struct rte_ether_hdr *eth_hdr, uint16_t *proto)
38 : : {
39 : : size_t vlan_offset = 0;
40 : :
41 [ # # # # : 0 : if (rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) == *proto ||
# # # # ]
42 : : rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ) == *proto) {
43 : : struct rte_vlan_hdr *vlan_hdr =
44 : : (struct rte_vlan_hdr *)(eth_hdr + 1);
45 : :
46 : : vlan_offset = sizeof(struct rte_vlan_hdr);
47 : 0 : *proto = vlan_hdr->eth_proto;
48 : :
49 [ # # # # : 0 : if (rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) == *proto) {
# # # # ]
50 : : vlan_hdr = vlan_hdr + 1;
51 : 0 : *proto = vlan_hdr->eth_proto;
52 : : vlan_offset += sizeof(struct rte_vlan_hdr);
53 : : }
54 : : }
55 : : return vlan_offset;
56 : : }
57 : :
58 : : static uint16_t
59 : 0 : bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
60 : : {
61 : : struct bond_dev_private *internals;
62 : :
63 : : uint16_t num_rx_total = 0;
64 : : uint16_t member_count;
65 : : uint16_t active_member;
66 : : int i;
67 : :
68 : : /* Cast to structure, containing bonding device's port id and queue id */
69 : : struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
70 : 0 : internals = bd_rx_q->dev_private;
71 : 0 : member_count = internals->active_member_count;
72 : 0 : active_member = bd_rx_q->active_member;
73 : :
74 [ # # # # ]: 0 : for (i = 0; i < member_count && nb_pkts; i++) {
75 : : uint16_t num_rx_member;
76 : :
77 : : /*
78 : : * Offset of pointer to *bufs increases as packets are received
79 : : * from other members.
80 : : */
81 : : num_rx_member =
82 : 0 : rte_eth_rx_burst(internals->active_members[active_member],
83 : 0 : bd_rx_q->queue_id,
84 : 0 : bufs + num_rx_total, nb_pkts);
85 : 0 : num_rx_total += num_rx_member;
86 : 0 : nb_pkts -= num_rx_member;
87 [ # # ]: 0 : if (++active_member >= member_count)
88 : : active_member = 0;
89 : : }
90 : :
91 [ # # ]: 0 : if (++bd_rx_q->active_member >= member_count)
92 : 0 : bd_rx_q->active_member = 0;
93 : 0 : return num_rx_total;
94 : : }
95 : :
96 : : static uint16_t
97 : 0 : bond_ethdev_rx_burst_active_backup(void *queue, struct rte_mbuf **bufs,
98 : : uint16_t nb_pkts)
99 : : {
100 : : struct bond_dev_private *internals;
101 : :
102 : : /* Cast to structure, containing bonding device's port id and queue id */
103 : : struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
104 : :
105 : 0 : internals = bd_rx_q->dev_private;
106 : :
107 : 0 : return rte_eth_rx_burst(internals->current_primary_port,
108 : 0 : bd_rx_q->queue_id, bufs, nb_pkts);
109 : : }
110 : :
111 : : static inline uint8_t
112 : : is_lacp_packets(uint16_t ethertype, uint8_t subtype, struct rte_mbuf *mbuf)
113 : : {
114 : : const uint16_t ether_type_slow_be =
115 : : rte_be_to_cpu_16(RTE_ETHER_TYPE_SLOW);
116 : :
117 [ # # # # ]: 0 : return !((mbuf->ol_flags & RTE_MBUF_F_RX_VLAN) ? mbuf->vlan_tci : 0) &&
118 : 0 : (ethertype == ether_type_slow_be &&
119 [ # # ]: 0 : (subtype == SLOW_SUBTYPE_MARKER || subtype == SLOW_SUBTYPE_LACP));
120 : : }
121 : :
122 : : /*****************************************************************************
123 : : * Flow director's setup for mode 4 optimization
124 : : */
125 : :
126 : : static struct rte_flow_item_eth flow_item_eth_type_8023ad = {
127 : : .hdr.dst_addr.addr_bytes = { 0 },
128 : : .hdr.src_addr.addr_bytes = { 0 },
129 : : .hdr.ether_type = RTE_BE16(RTE_ETHER_TYPE_SLOW),
130 : : };
131 : :
132 : : static struct rte_flow_item_eth flow_item_eth_mask_type_8023ad = {
133 : : .hdr.dst_addr.addr_bytes = { 0 },
134 : : .hdr.src_addr.addr_bytes = { 0 },
135 : : .hdr.ether_type = 0xFFFF,
136 : : };
137 : :
138 : : static struct rte_flow_item flow_item_8023ad[] = {
139 : : {
140 : : .type = RTE_FLOW_ITEM_TYPE_ETH,
141 : : .spec = &flow_item_eth_type_8023ad,
142 : : .last = NULL,
143 : : .mask = &flow_item_eth_mask_type_8023ad,
144 : : },
145 : : {
146 : : .type = RTE_FLOW_ITEM_TYPE_END,
147 : : .spec = NULL,
148 : : .last = NULL,
149 : : .mask = NULL,
150 : : }
151 : : };
152 : :
153 : : const struct rte_flow_attr flow_attr_8023ad = {
154 : : .group = 0,
155 : : .priority = 0,
156 : : .ingress = 1,
157 : : .egress = 0,
158 : : .reserved = 0,
159 : : };
160 : :
161 : : int
162 : 0 : bond_ethdev_8023ad_flow_verify(struct rte_eth_dev *bond_dev,
163 : : uint16_t member_port) {
164 : : struct rte_eth_dev_info member_info;
165 : : struct rte_flow_error error;
166 : 0 : struct bond_dev_private *internals = bond_dev->data->dev_private;
167 : :
168 : 0 : const struct rte_flow_action_queue lacp_queue_conf = {
169 : : .index = 0,
170 : : };
171 : :
172 : 0 : const struct rte_flow_action actions[] = {
173 : : {
174 : : .type = RTE_FLOW_ACTION_TYPE_QUEUE,
175 : : .conf = &lacp_queue_conf
176 : : },
177 : : {
178 : : .type = RTE_FLOW_ACTION_TYPE_END,
179 : : }
180 : : };
181 : :
182 : 0 : int ret = rte_flow_validate(member_port, &flow_attr_8023ad,
183 : : flow_item_8023ad, actions, &error);
184 [ # # ]: 0 : if (ret < 0) {
185 : 0 : RTE_BOND_LOG(ERR, "%s: %s (member_port=%d queue_id=%d)",
186 : : __func__, error.message, member_port,
187 : : internals->mode4.dedicated_queues.rx_qid);
188 : 0 : return -1;
189 : : }
190 : :
191 : 0 : ret = rte_eth_dev_info_get(member_port, &member_info);
192 [ # # ]: 0 : if (ret != 0) {
193 : 0 : RTE_BOND_LOG(ERR,
194 : : "%s: Error during getting device (port %u) info: %s\n",
195 : : __func__, member_port, strerror(-ret));
196 : :
197 : 0 : return ret;
198 : : }
199 : :
200 [ # # ]: 0 : if (member_info.max_rx_queues < bond_dev->data->nb_rx_queues ||
201 [ # # ]: 0 : member_info.max_tx_queues < bond_dev->data->nb_tx_queues) {
202 : 0 : RTE_BOND_LOG(ERR,
203 : : "%s: Member %d capabilities doesn't allow allocating additional queues",
204 : : __func__, member_port);
205 : 0 : return -1;
206 : : }
207 : :
208 : : return 0;
209 : : }
210 : :
211 : : int
212 : 0 : bond_8023ad_slow_pkt_hw_filter_supported(uint16_t port_id) {
213 : 0 : struct rte_eth_dev *bond_dev = &rte_eth_devices[port_id];
214 : 0 : struct bond_dev_private *internals = bond_dev->data->dev_private;
215 : : struct rte_eth_dev_info bond_info;
216 : : uint16_t idx;
217 : : int ret;
218 : :
219 : : /* Verify if all members in bonding supports flow director and */
220 [ # # ]: 0 : if (internals->member_count > 0) {
221 : 0 : ret = rte_eth_dev_info_get(bond_dev->data->port_id, &bond_info);
222 [ # # ]: 0 : if (ret != 0) {
223 : 0 : RTE_BOND_LOG(ERR,
224 : : "%s: Error during getting device (port %u) info: %s\n",
225 : : __func__, bond_dev->data->port_id,
226 : : strerror(-ret));
227 : :
228 : 0 : return ret;
229 : : }
230 : :
231 : 0 : internals->mode4.dedicated_queues.rx_qid = bond_info.nb_rx_queues;
232 : 0 : internals->mode4.dedicated_queues.tx_qid = bond_info.nb_tx_queues;
233 : :
234 [ # # ]: 0 : for (idx = 0; idx < internals->member_count; idx++) {
235 [ # # ]: 0 : if (bond_ethdev_8023ad_flow_verify(bond_dev,
236 : 0 : internals->members[idx].port_id) != 0)
237 : : return -1;
238 : : }
239 : : }
240 : :
241 : : return 0;
242 : : }
243 : :
244 : : int
245 : 0 : bond_ethdev_8023ad_flow_set(struct rte_eth_dev *bond_dev, uint16_t member_port) {
246 : :
247 : : struct rte_flow_error error;
248 : 0 : struct bond_dev_private *internals = bond_dev->data->dev_private;
249 : 0 : struct rte_flow_action_queue lacp_queue_conf = {
250 : 0 : .index = internals->mode4.dedicated_queues.rx_qid,
251 : : };
252 : :
253 : 0 : const struct rte_flow_action actions[] = {
254 : : {
255 : : .type = RTE_FLOW_ACTION_TYPE_QUEUE,
256 : : .conf = &lacp_queue_conf
257 : : },
258 : : {
259 : : .type = RTE_FLOW_ACTION_TYPE_END,
260 : : }
261 : : };
262 : :
263 : 0 : internals->mode4.dedicated_queues.flow[member_port] = rte_flow_create(member_port,
264 : : &flow_attr_8023ad, flow_item_8023ad, actions, &error);
265 [ # # ]: 0 : if (internals->mode4.dedicated_queues.flow[member_port] == NULL) {
266 : 0 : RTE_BOND_LOG(ERR, "bond_ethdev_8023ad_flow_set: %s "
267 : : "(member_port=%d queue_id=%d)",
268 : : error.message, member_port,
269 : : internals->mode4.dedicated_queues.rx_qid);
270 : 0 : return -1;
271 : : }
272 : :
273 : : return 0;
274 : : }
275 : :
276 : : static bool
277 : 0 : is_bond_mac_addr(const struct rte_ether_addr *ea,
278 : : const struct rte_ether_addr *mac_addrs, uint32_t max_mac_addrs)
279 : : {
280 : : uint32_t i;
281 : :
282 [ # # ]: 0 : for (i = 0; i < max_mac_addrs; i++) {
283 : : /* skip zero address */
284 [ # # ]: 0 : if (rte_is_zero_ether_addr(&mac_addrs[i]))
285 : 0 : continue;
286 : :
287 [ # # ]: 0 : if (rte_is_same_ether_addr(ea, &mac_addrs[i]))
288 : : return true;
289 : : }
290 : :
291 : : return false;
292 : : }
293 : :
294 : : static inline uint16_t
295 : 0 : rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
296 : : bool dedicated_rxq)
297 : : {
298 : : /* Cast to structure, containing bonding device's port id and queue id */
299 : : struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
300 : 0 : struct bond_dev_private *internals = bd_rx_q->dev_private;
301 : : struct rte_eth_dev *bonding_eth_dev =
302 : 0 : &rte_eth_devices[internals->port_id];
303 : 0 : struct rte_ether_addr *bond_mac = bonding_eth_dev->data->mac_addrs;
304 : : struct rte_ether_hdr *hdr;
305 : :
306 : : const uint16_t ether_type_slow_be =
307 : : rte_be_to_cpu_16(RTE_ETHER_TYPE_SLOW);
308 : : uint16_t num_rx_total = 0; /* Total number of received packets */
309 : : uint16_t members[RTE_MAX_ETHPORTS];
310 : : uint16_t member_count, idx;
311 : :
312 : : uint8_t collecting; /* current member collecting status */
313 : 0 : const uint8_t promisc = rte_eth_promiscuous_get(internals->port_id);
314 : 0 : const uint8_t allmulti = rte_eth_allmulticast_get(internals->port_id);
315 : : uint8_t subtype;
316 : : uint16_t i;
317 : : uint16_t j;
318 : : uint16_t k;
319 : :
320 : : /* Copy member list to protect against member up/down changes during tx
321 : : * bursting */
322 : 0 : member_count = internals->active_member_count;
323 [ # # ]: 0 : memcpy(members, internals->active_members,
324 : : sizeof(internals->active_members[0]) * member_count);
325 : :
326 : 0 : idx = bd_rx_q->active_member;
327 [ # # ]: 0 : if (idx >= member_count) {
328 : 0 : bd_rx_q->active_member = 0;
329 : : idx = 0;
330 : : }
331 [ # # ]: 0 : for (i = 0; i < member_count && num_rx_total < nb_pkts; i++) {
332 : : j = num_rx_total;
333 : 0 : collecting = ACTOR_STATE(&bond_mode_8023ad_ports[members[idx]],
334 : : COLLECTING);
335 : :
336 : : /* Read packets from this member */
337 : 0 : num_rx_total += rte_eth_rx_burst(members[idx], bd_rx_q->queue_id,
338 : 0 : &bufs[num_rx_total], nb_pkts - num_rx_total);
339 : :
340 [ # # ]: 0 : for (k = j; k < 2 && k < num_rx_total; k++)
341 : 0 : rte_prefetch0(rte_pktmbuf_mtod(bufs[k], void *));
342 : :
343 : : /* Handle slow protocol packets. */
344 [ # # ]: 0 : while (j < num_rx_total) {
345 [ # # ]: 0 : if (j + 3 < num_rx_total)
346 : 0 : rte_prefetch0(rte_pktmbuf_mtod(bufs[j + 3], void *));
347 : :
348 : 0 : hdr = rte_pktmbuf_mtod(bufs[j], struct rte_ether_hdr *);
349 : 0 : subtype = ((struct slow_protocol_frame *)hdr)->slow_protocol.subtype;
350 : :
351 : : /* Remove packet from array if:
352 : : * - it is slow packet but no dedicated rxq is present,
353 : : * - member is not in collecting state,
354 : : * - bonding interface is not in promiscuous mode and
355 : : * packet address isn't in mac_addrs array:
356 : : * - packet is unicast,
357 : : * - packet is multicast and bonding interface
358 : : * is not in allmulti,
359 : : */
360 [ # # # # : 0 : if (unlikely(
# # # # #
# # # # #
# # ]
361 : : (!dedicated_rxq &&
362 : : is_lacp_packets(hdr->ether_type, subtype,
363 : : bufs[j])) ||
364 : : !collecting ||
365 : : (!promisc &&
366 : : !is_bond_mac_addr(&hdr->dst_addr, bond_mac,
367 : : BOND_MAX_MAC_ADDRS) &&
368 : : (rte_is_unicast_ether_addr(&hdr->dst_addr) ||
369 : : !allmulti)))) {
370 [ # # ]: 0 : if (hdr->ether_type == ether_type_slow_be) {
371 : 0 : bond_mode_8023ad_handle_slow_pkt(
372 : 0 : internals, members[idx], bufs[j]);
373 : : } else
374 : 0 : rte_pktmbuf_free(bufs[j]);
375 : :
376 : : /* Packet is managed by mode 4 or dropped, shift the array */
377 : 0 : num_rx_total--;
378 [ # # ]: 0 : if (j < num_rx_total) {
379 : 0 : memmove(&bufs[j], &bufs[j + 1], sizeof(bufs[0]) *
380 : 0 : (num_rx_total - j));
381 : : }
382 : : } else
383 : 0 : j++;
384 : : }
385 [ # # ]: 0 : if (unlikely(++idx == member_count))
386 : : idx = 0;
387 : : }
388 : :
389 [ # # ]: 0 : if (++bd_rx_q->active_member >= member_count)
390 : 0 : bd_rx_q->active_member = 0;
391 : :
392 : 0 : return num_rx_total;
393 : : }
394 : :
395 : : static uint16_t
396 : 0 : bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
397 : : uint16_t nb_pkts)
398 : : {
399 : 0 : return rx_burst_8023ad(queue, bufs, nb_pkts, false);
400 : : }
401 : :
402 : : static uint16_t
403 : 0 : bond_ethdev_rx_burst_8023ad_fast_queue(void *queue, struct rte_mbuf **bufs,
404 : : uint16_t nb_pkts)
405 : : {
406 : 0 : return rx_burst_8023ad(queue, bufs, nb_pkts, true);
407 : : }
408 : :
409 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
410 : : uint32_t burstnumberRX;
411 : : uint32_t burst_number_TX;
412 : :
413 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
414 : :
415 : : static void
416 : : arp_op_name(uint16_t arp_op, char *buf, size_t buf_len)
417 : : {
418 : : switch (arp_op) {
419 : : case RTE_ARP_OP_REQUEST:
420 : : strlcpy(buf, "ARP Request", buf_len);
421 : : return;
422 : : case RTE_ARP_OP_REPLY:
423 : : strlcpy(buf, "ARP Reply", buf_len);
424 : : return;
425 : : case RTE_ARP_OP_REVREQUEST:
426 : : strlcpy(buf, "Reverse ARP Request", buf_len);
427 : : return;
428 : : case RTE_ARP_OP_REVREPLY:
429 : : strlcpy(buf, "Reverse ARP Reply", buf_len);
430 : : return;
431 : : case RTE_ARP_OP_INVREQUEST:
432 : : strlcpy(buf, "Peer Identify Request", buf_len);
433 : : return;
434 : : case RTE_ARP_OP_INVREPLY:
435 : : strlcpy(buf, "Peer Identify Reply", buf_len);
436 : : return;
437 : : default:
438 : : break;
439 : : }
440 : : strlcpy(buf, "Unknown", buf_len);
441 : : return;
442 : : }
443 : : #endif
444 : : #define MaxIPv4String 16
445 : : static void
446 : : ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf, uint8_t buf_size)
447 : : {
448 : : uint32_t ipv4_addr;
449 : :
450 : : ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr);
451 : : snprintf(buf, buf_size, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF,
452 : : (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF,
453 : : ipv4_addr & 0xFF);
454 : : }
455 : :
456 : : #define MAX_CLIENTS_NUMBER 128
457 : : uint8_t active_clients;
458 : : struct client_stats_t {
459 : : uint16_t port;
460 : : uint32_t ipv4_addr;
461 : : uint32_t ipv4_rx_packets;
462 : : uint32_t ipv4_tx_packets;
463 : : };
464 : : struct client_stats_t client_stats[MAX_CLIENTS_NUMBER];
465 : :
466 : : static void
467 : : update_client_stats(uint32_t addr, uint16_t port, uint32_t *TXorRXindicator)
468 : : {
469 : : int i = 0;
470 : :
471 : : for (; i < MAX_CLIENTS_NUMBER; i++) {
472 : : if ((client_stats[i].ipv4_addr == addr) && (client_stats[i].port == port)) {
473 : : /* Just update RX packets number for this client */
474 : : if (TXorRXindicator == &burstnumberRX)
475 : : client_stats[i].ipv4_rx_packets++;
476 : : else
477 : : client_stats[i].ipv4_tx_packets++;
478 : : return;
479 : : }
480 : : }
481 : : /* We have a new client. Insert him to the table, and increment stats */
482 : : if (TXorRXindicator == &burstnumberRX)
483 : : client_stats[active_clients].ipv4_rx_packets++;
484 : : else
485 : : client_stats[active_clients].ipv4_tx_packets++;
486 : : client_stats[active_clients].ipv4_addr = addr;
487 : : client_stats[active_clients].port = port;
488 : : active_clients++;
489 : :
490 : : }
491 : :
492 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
493 : : #define MODE6_DEBUG(info, src_ip, dst_ip, eth_h, arp_op, port, burstnumber) \
494 : : rte_log(RTE_LOG_DEBUG, bond_logtype, \
495 : : "%s port:%d SrcMAC:" RTE_ETHER_ADDR_PRT_FMT " SrcIP:%s " \
496 : : "DstMAC:" RTE_ETHER_ADDR_PRT_FMT " DstIP:%s %s %d\n", \
497 : : info, \
498 : : port, \
499 : : RTE_ETHER_ADDR_BYTES(ð_h->src_addr), \
500 : : src_ip, \
501 : : RTE_ETHER_ADDR_BYTES(ð_h->dst_addr), \
502 : : dst_ip, \
503 : : arp_op, ++burstnumber)
504 : : #endif
505 : :
506 : : static void
507 : : mode6_debug(const char __rte_unused *info,
508 : : struct rte_ether_hdr *eth_h, uint16_t port,
509 : : uint32_t __rte_unused *burstnumber)
510 : : {
511 : : struct rte_ipv4_hdr *ipv4_h;
512 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
513 : : struct rte_arp_hdr *arp_h;
514 : : char dst_ip[16];
515 : : char ArpOp[24];
516 : : char buf[16];
517 : : #endif
518 : : char src_ip[16];
519 : :
520 : : uint16_t ether_type = eth_h->ether_type;
521 : : uint16_t offset = get_vlan_offset(eth_h, ðer_type);
522 : :
523 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
524 : : strlcpy(buf, info, 16);
525 : : #endif
526 : :
527 : : if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
528 : : ipv4_h = (struct rte_ipv4_hdr *)((char *)(eth_h + 1) + offset);
529 : : ipv4_addr_to_dot(ipv4_h->src_addr, src_ip, MaxIPv4String);
530 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
531 : : ipv4_addr_to_dot(ipv4_h->dst_addr, dst_ip, MaxIPv4String);
532 : : MODE6_DEBUG(buf, src_ip, dst_ip, eth_h, "", port, *burstnumber);
533 : : #endif
534 : : update_client_stats(ipv4_h->src_addr, port, burstnumber);
535 : : }
536 : : #ifdef RTE_LIBRTE_BOND_DEBUG_ALB
537 : : else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
538 : : arp_h = (struct rte_arp_hdr *)((char *)(eth_h + 1) + offset);
539 : : ipv4_addr_to_dot(arp_h->arp_data.arp_sip, src_ip, MaxIPv4String);
540 : : ipv4_addr_to_dot(arp_h->arp_data.arp_tip, dst_ip, MaxIPv4String);
541 : : arp_op_name(rte_be_to_cpu_16(arp_h->arp_opcode),
542 : : ArpOp, sizeof(ArpOp));
543 : : MODE6_DEBUG(buf, src_ip, dst_ip, eth_h, ArpOp, port, *burstnumber);
544 : : }
545 : : #endif
546 : : }
547 : : #endif
548 : :
549 : : static uint16_t
550 : 0 : bond_ethdev_rx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
551 : : {
552 : : struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
553 : 0 : struct bond_dev_private *internals = bd_rx_q->dev_private;
554 : : struct rte_ether_hdr *eth_h;
555 : : uint16_t ether_type, offset;
556 : : uint16_t nb_recv_pkts;
557 : : int i;
558 : :
559 : 0 : nb_recv_pkts = bond_ethdev_rx_burst(queue, bufs, nb_pkts);
560 : :
561 [ # # ]: 0 : for (i = 0; i < nb_recv_pkts; i++) {
562 : 0 : eth_h = rte_pktmbuf_mtod(bufs[i], struct rte_ether_hdr *);
563 [ # # ]: 0 : ether_type = eth_h->ether_type;
564 : : offset = get_vlan_offset(eth_h, ðer_type);
565 : :
566 [ # # ]: 0 : if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
567 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
568 : : mode6_debug("RX ARP:", eth_h, bufs[i]->port, &burstnumberRX);
569 : : #endif
570 : 0 : bond_mode_alb_arp_recv(eth_h, offset, internals);
571 : : }
572 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
573 : : else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
574 : : mode6_debug("RX IPv4:", eth_h, bufs[i]->port, &burstnumberRX);
575 : : #endif
576 : : }
577 : :
578 : 0 : return nb_recv_pkts;
579 : : }
580 : :
581 : : static uint16_t
582 : 0 : bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
583 : : uint16_t nb_pkts)
584 : 0 : {
585 : : struct bond_dev_private *internals;
586 : : struct bond_tx_queue *bd_tx_q;
587 : :
588 : 0 : struct rte_mbuf *member_bufs[RTE_MAX_ETHPORTS][nb_pkts];
589 : 0 : uint16_t member_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };
590 : :
591 : : uint16_t num_of_members;
592 : : uint16_t members[RTE_MAX_ETHPORTS];
593 : :
594 : : uint16_t num_tx_total = 0, num_tx_member;
595 : :
596 : : static int member_idx;
597 : : int i, cmember_idx = 0, tx_fail_total = 0;
598 : :
599 : : bd_tx_q = (struct bond_tx_queue *)queue;
600 : 0 : internals = bd_tx_q->dev_private;
601 : :
602 : : /* Copy member list to protect against member up/down changes during tx
603 : : * bursting */
604 : 0 : num_of_members = internals->active_member_count;
605 [ # # ]: 0 : memcpy(members, internals->active_members,
606 : : sizeof(internals->active_members[0]) * num_of_members);
607 : :
608 [ # # ]: 0 : if (num_of_members < 1)
609 : : return num_tx_total;
610 : :
611 : : /* Populate members mbuf with which packets are to be sent on it */
612 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
613 : 0 : cmember_idx = (member_idx + i) % num_of_members;
614 : 0 : member_bufs[cmember_idx][(member_nb_pkts[cmember_idx])++] = bufs[i];
615 : : }
616 : :
617 : : /*
618 : : * increment current member index so the next call to tx burst starts on the
619 : : * next member.
620 : : */
621 : 0 : member_idx = ++cmember_idx;
622 : :
623 : : /* Send packet burst on each member device */
624 [ # # ]: 0 : for (i = 0; i < num_of_members; i++) {
625 [ # # ]: 0 : if (member_nb_pkts[i] > 0) {
626 : 0 : num_tx_member = rte_eth_tx_prepare(members[i],
627 [ # # ]: 0 : bd_tx_q->queue_id, member_bufs[i],
628 : : member_nb_pkts[i]);
629 : 0 : num_tx_member = rte_eth_tx_burst(members[i], bd_tx_q->queue_id,
630 : : member_bufs[i], num_tx_member);
631 : :
632 : : /* if tx burst fails move packets to end of bufs */
633 [ # # ]: 0 : if (unlikely(num_tx_member < member_nb_pkts[i])) {
634 : 0 : int tx_fail_member = member_nb_pkts[i] - num_tx_member;
635 : :
636 : 0 : tx_fail_total += tx_fail_member;
637 : :
638 : 0 : memcpy(&bufs[nb_pkts - tx_fail_total],
639 : 0 : &member_bufs[i][num_tx_member],
640 : : tx_fail_member * sizeof(bufs[0]));
641 : : }
642 : 0 : num_tx_total += num_tx_member;
643 : : }
644 : : }
645 : :
646 : : return num_tx_total;
647 : : }
648 : :
649 : : static uint16_t
650 : 0 : bond_ethdev_tx_burst_active_backup(void *queue,
651 : : struct rte_mbuf **bufs, uint16_t nb_pkts)
652 : : {
653 : : struct bond_dev_private *internals;
654 : : struct bond_tx_queue *bd_tx_q;
655 : : uint16_t nb_prep_pkts;
656 : :
657 : : bd_tx_q = (struct bond_tx_queue *)queue;
658 : 0 : internals = bd_tx_q->dev_private;
659 : :
660 [ # # ]: 0 : if (internals->active_member_count < 1)
661 : : return 0;
662 : :
663 : 0 : nb_prep_pkts = rte_eth_tx_prepare(internals->current_primary_port,
664 [ # # ]: 0 : bd_tx_q->queue_id, bufs, nb_pkts);
665 : :
666 : 0 : return rte_eth_tx_burst(internals->current_primary_port, bd_tx_q->queue_id,
667 : : bufs, nb_prep_pkts);
668 : : }
669 : :
670 : : static inline uint16_t
671 : : ether_hash(struct rte_ether_hdr *eth_hdr)
672 : : {
673 : : unaligned_uint16_t *word_src_addr =
674 : : (unaligned_uint16_t *)eth_hdr->src_addr.addr_bytes;
675 : : unaligned_uint16_t *word_dst_addr =
676 : : (unaligned_uint16_t *)eth_hdr->dst_addr.addr_bytes;
677 : :
678 : 0 : return (word_src_addr[0] ^ word_dst_addr[0]) ^
679 : 0 : (word_src_addr[1] ^ word_dst_addr[1]) ^
680 : 0 : (word_src_addr[2] ^ word_dst_addr[2]);
681 : : }
682 : :
683 : : static inline uint32_t
684 : : ipv4_hash(struct rte_ipv4_hdr *ipv4_hdr)
685 : : {
686 : 0 : return ipv4_hdr->src_addr ^ ipv4_hdr->dst_addr;
687 : : }
688 : :
689 : : static inline uint32_t
690 : : ipv6_hash(struct rte_ipv6_hdr *ipv6_hdr)
691 : : {
692 : : unaligned_uint32_t *word_src_addr =
693 : : (unaligned_uint32_t *)&(ipv6_hdr->src_addr[0]);
694 : : unaligned_uint32_t *word_dst_addr =
695 : : (unaligned_uint32_t *)&(ipv6_hdr->dst_addr[0]);
696 : :
697 : 0 : return (word_src_addr[0] ^ word_dst_addr[0]) ^
698 : 0 : (word_src_addr[1] ^ word_dst_addr[1]) ^
699 : 0 : (word_src_addr[2] ^ word_dst_addr[2]) ^
700 : 0 : (word_src_addr[3] ^ word_dst_addr[3]);
701 : : }
702 : :
703 : :
704 : : void
705 : 0 : burst_xmit_l2_hash(struct rte_mbuf **buf, uint16_t nb_pkts,
706 : : uint16_t member_count, uint16_t *members)
707 : : {
708 : : struct rte_ether_hdr *eth_hdr;
709 : : uint32_t hash;
710 : : int i;
711 : :
712 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
713 : 0 : eth_hdr = rte_pktmbuf_mtod(buf[i], struct rte_ether_hdr *);
714 : :
715 : 0 : hash = ether_hash(eth_hdr);
716 : :
717 : 0 : members[i] = (hash ^= hash >> 8) % member_count;
718 : : }
719 : 0 : }
720 : :
721 : : void
722 : 0 : burst_xmit_l23_hash(struct rte_mbuf **buf, uint16_t nb_pkts,
723 : : uint16_t member_count, uint16_t *members)
724 : : {
725 : : uint16_t i;
726 : : struct rte_ether_hdr *eth_hdr;
727 : : uint16_t proto;
728 : : size_t vlan_offset;
729 : : uint32_t hash, l3hash;
730 : :
731 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
732 : 0 : eth_hdr = rte_pktmbuf_mtod(buf[i], struct rte_ether_hdr *);
733 : : l3hash = 0;
734 : :
735 : 0 : proto = eth_hdr->ether_type;
736 [ # # ]: 0 : hash = ether_hash(eth_hdr);
737 : :
738 : : vlan_offset = get_vlan_offset(eth_hdr, &proto);
739 : :
740 [ # # ]: 0 : if (rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) == proto) {
741 : 0 : struct rte_ipv4_hdr *ipv4_hdr = (struct rte_ipv4_hdr *)
742 : 0 : ((char *)(eth_hdr + 1) + vlan_offset);
743 : : l3hash = ipv4_hash(ipv4_hdr);
744 : :
745 [ # # ]: 0 : } else if (rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) == proto) {
746 : 0 : struct rte_ipv6_hdr *ipv6_hdr = (struct rte_ipv6_hdr *)
747 : 0 : ((char *)(eth_hdr + 1) + vlan_offset);
748 : : l3hash = ipv6_hash(ipv6_hdr);
749 : : }
750 : :
751 : 0 : hash = hash ^ l3hash;
752 : 0 : hash ^= hash >> 16;
753 : 0 : hash ^= hash >> 8;
754 : :
755 : 0 : members[i] = hash % member_count;
756 : : }
757 : 0 : }
758 : :
759 : : void
760 : 0 : burst_xmit_l34_hash(struct rte_mbuf **buf, uint16_t nb_pkts,
761 : : uint16_t member_count, uint16_t *members)
762 : : {
763 : : struct rte_ether_hdr *eth_hdr;
764 : : uint16_t proto;
765 : : size_t vlan_offset;
766 : : int i;
767 : :
768 : : struct rte_udp_hdr *udp_hdr;
769 : : struct rte_tcp_hdr *tcp_hdr;
770 : : uint32_t hash, l3hash, l4hash;
771 : :
772 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
773 : 0 : eth_hdr = rte_pktmbuf_mtod(buf[i], struct rte_ether_hdr *);
774 : 0 : size_t pkt_end = (size_t)eth_hdr + rte_pktmbuf_data_len(buf[i]);
775 [ # # ]: 0 : proto = eth_hdr->ether_type;
776 : : vlan_offset = get_vlan_offset(eth_hdr, &proto);
777 : : l3hash = 0;
778 : : l4hash = 0;
779 : :
780 [ # # ]: 0 : if (rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) == proto) {
781 : 0 : struct rte_ipv4_hdr *ipv4_hdr = (struct rte_ipv4_hdr *)
782 [ # # ]: 0 : ((char *)(eth_hdr + 1) + vlan_offset);
783 : : size_t ip_hdr_offset;
784 : :
785 : : l3hash = ipv4_hash(ipv4_hdr);
786 : :
787 : : /* there is no L4 header in fragmented packet */
788 [ # # ]: 0 : if (likely(rte_ipv4_frag_pkt_is_fragmented(ipv4_hdr)
789 : : == 0)) {
790 : 0 : ip_hdr_offset = (ipv4_hdr->version_ihl
791 : 0 : & RTE_IPV4_HDR_IHL_MASK) *
792 : : RTE_IPV4_IHL_MULTIPLIER;
793 : :
794 [ # # ]: 0 : if (ipv4_hdr->next_proto_id == IPPROTO_TCP) {
795 : 0 : tcp_hdr = (struct rte_tcp_hdr *)
796 : : ((char *)ipv4_hdr +
797 : : ip_hdr_offset);
798 [ # # ]: 0 : if ((size_t)tcp_hdr + sizeof(*tcp_hdr)
799 : : <= pkt_end)
800 : 0 : l4hash = HASH_L4_PORTS(tcp_hdr);
801 [ # # ]: 0 : } else if (ipv4_hdr->next_proto_id ==
802 : : IPPROTO_UDP) {
803 : 0 : udp_hdr = (struct rte_udp_hdr *)
804 : : ((char *)ipv4_hdr +
805 : : ip_hdr_offset);
806 [ # # ]: 0 : if ((size_t)udp_hdr + sizeof(*udp_hdr)
807 : : < pkt_end)
808 : 0 : l4hash = HASH_L4_PORTS(udp_hdr);
809 : : }
810 : : }
811 [ # # ]: 0 : } else if (rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) == proto) {
812 : 0 : struct rte_ipv6_hdr *ipv6_hdr = (struct rte_ipv6_hdr *)
813 : 0 : ((char *)(eth_hdr + 1) + vlan_offset);
814 : : l3hash = ipv6_hash(ipv6_hdr);
815 : :
816 [ # # ]: 0 : if (ipv6_hdr->proto == IPPROTO_TCP) {
817 : : tcp_hdr = (struct rte_tcp_hdr *)(ipv6_hdr + 1);
818 : 0 : l4hash = HASH_L4_PORTS(tcp_hdr);
819 [ # # ]: 0 : } else if (ipv6_hdr->proto == IPPROTO_UDP) {
820 : : udp_hdr = (struct rte_udp_hdr *)(ipv6_hdr + 1);
821 : 0 : l4hash = HASH_L4_PORTS(udp_hdr);
822 : : }
823 : : }
824 : :
825 : 0 : hash = l3hash ^ l4hash;
826 : 0 : hash ^= hash >> 16;
827 : 0 : hash ^= hash >> 8;
828 : :
829 : 0 : members[i] = hash % member_count;
830 : : }
831 : 0 : }
832 : :
833 : : struct bwg_member {
834 : : uint64_t bwg_left_int;
835 : : uint64_t bwg_left_remainder;
836 : : uint16_t member;
837 : : };
838 : :
839 : : void
840 : 0 : bond_tlb_activate_member(struct bond_dev_private *internals) {
841 : : int i;
842 : :
843 [ # # ]: 0 : for (i = 0; i < internals->active_member_count; i++)
844 : 0 : tlb_last_obytets[internals->active_members[i]] = 0;
845 : 0 : }
846 : :
847 : : static int
848 : 0 : bandwidth_cmp(const void *a, const void *b)
849 : : {
850 : : const struct bwg_member *bwg_a = a;
851 : : const struct bwg_member *bwg_b = b;
852 : 0 : int64_t diff = (int64_t)bwg_b->bwg_left_int - (int64_t)bwg_a->bwg_left_int;
853 : 0 : int64_t diff2 = (int64_t)bwg_b->bwg_left_remainder -
854 : 0 : (int64_t)bwg_a->bwg_left_remainder;
855 [ # # ]: 0 : if (diff > 0)
856 : : return 1;
857 [ # # ]: 0 : else if (diff < 0)
858 : : return -1;
859 [ # # ]: 0 : else if (diff2 > 0)
860 : : return 1;
861 [ # # ]: 0 : else if (diff2 < 0)
862 : : return -1;
863 : : else
864 : 0 : return 0;
865 : : }
866 : :
867 : : static void
868 : 0 : bandwidth_left(uint16_t port_id, uint64_t load, uint8_t update_idx,
869 : : struct bwg_member *bwg_member)
870 : : {
871 : : struct rte_eth_link link_status;
872 : : int ret;
873 : :
874 : 0 : ret = rte_eth_link_get_nowait(port_id, &link_status);
875 [ # # ]: 0 : if (ret < 0) {
876 : 0 : RTE_BOND_LOG(ERR, "Member (port %u) link get failed: %s",
877 : : port_id, rte_strerror(-ret));
878 : 0 : return;
879 : : }
880 : 0 : uint64_t link_bwg = link_status.link_speed * 1000000ULL / 8;
881 [ # # ]: 0 : if (link_bwg == 0)
882 : : return;
883 : 0 : link_bwg = link_bwg * (update_idx+1) * REORDER_PERIOD_MS;
884 : 0 : bwg_member->bwg_left_int = (link_bwg - 1000 * load) / link_bwg;
885 : 0 : bwg_member->bwg_left_remainder = (link_bwg - 1000 * load) % link_bwg;
886 : : }
887 : :
888 : : static void
889 : 0 : bond_ethdev_update_tlb_member_cb(void *arg)
890 : : {
891 : : struct bond_dev_private *internals = arg;
892 : : struct rte_eth_stats member_stats;
893 : : struct bwg_member bwg_array[RTE_MAX_ETHPORTS];
894 : : uint16_t member_count;
895 : : uint64_t tx_bytes;
896 : :
897 : : uint8_t update_stats = 0;
898 : : uint16_t member_id;
899 : : uint16_t i;
900 : :
901 : 0 : internals->member_update_idx++;
902 : :
903 : :
904 [ # # ]: 0 : if (internals->member_update_idx >= REORDER_PERIOD_MS)
905 : : update_stats = 1;
906 : :
907 [ # # ]: 0 : for (i = 0; i < internals->active_member_count; i++) {
908 : 0 : member_id = internals->active_members[i];
909 : 0 : rte_eth_stats_get(member_id, &member_stats);
910 : 0 : tx_bytes = member_stats.obytes - tlb_last_obytets[member_id];
911 : 0 : bandwidth_left(member_id, tx_bytes,
912 : 0 : internals->member_update_idx, &bwg_array[i]);
913 : 0 : bwg_array[i].member = member_id;
914 : :
915 [ # # ]: 0 : if (update_stats) {
916 : 0 : tlb_last_obytets[member_id] = member_stats.obytes;
917 : : }
918 : : }
919 : :
920 [ # # ]: 0 : if (update_stats == 1)
921 : 0 : internals->member_update_idx = 0;
922 : :
923 : : member_count = i;
924 : 0 : qsort(bwg_array, member_count, sizeof(bwg_array[0]), bandwidth_cmp);
925 [ # # ]: 0 : for (i = 0; i < member_count; i++)
926 : 0 : internals->tlb_members_order[i] = bwg_array[i].member;
927 : :
928 : 0 : rte_eal_alarm_set(REORDER_PERIOD_MS * 1000, bond_ethdev_update_tlb_member_cb,
929 : : (struct bond_dev_private *)internals);
930 : 0 : }
931 : :
932 : : static uint16_t
933 : 0 : bond_ethdev_tx_burst_tlb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
934 : : {
935 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
936 : 0 : struct bond_dev_private *internals = bd_tx_q->dev_private;
937 : :
938 : : struct rte_eth_dev *primary_port =
939 : 0 : &rte_eth_devices[internals->primary_port];
940 : : uint16_t num_tx_total = 0, num_tx_prep;
941 : : uint16_t i, j;
942 : :
943 : 0 : uint16_t num_of_members = internals->active_member_count;
944 : : uint16_t members[RTE_MAX_ETHPORTS];
945 : :
946 : : struct rte_ether_hdr *ether_hdr;
947 : : struct rte_ether_addr primary_member_addr;
948 : : struct rte_ether_addr active_member_addr;
949 : :
950 [ # # ]: 0 : if (num_of_members < 1)
951 : : return num_tx_total;
952 : :
953 [ # # ]: 0 : memcpy(members, internals->tlb_members_order,
954 : : sizeof(internals->tlb_members_order[0]) * num_of_members);
955 : :
956 : :
957 [ # # ]: 0 : rte_ether_addr_copy(primary_port->data->mac_addrs, &primary_member_addr);
958 : :
959 [ # # ]: 0 : if (nb_pkts > 3) {
960 [ # # ]: 0 : for (i = 0; i < 3; i++)
961 : 0 : rte_prefetch0(rte_pktmbuf_mtod(bufs[i], void*));
962 : : }
963 : :
964 [ # # ]: 0 : for (i = 0; i < num_of_members; i++) {
965 : 0 : rte_eth_macaddr_get(members[i], &active_member_addr);
966 [ # # ]: 0 : for (j = num_tx_total; j < nb_pkts; j++) {
967 [ # # ]: 0 : if (j + 3 < nb_pkts)
968 : 0 : rte_prefetch0(rte_pktmbuf_mtod(bufs[j+3], void*));
969 : :
970 [ # # ]: 0 : ether_hdr = rte_pktmbuf_mtod(bufs[j],
971 : : struct rte_ether_hdr *);
972 [ # # ]: 0 : if (rte_is_same_ether_addr(ðer_hdr->src_addr,
973 : : &primary_member_addr))
974 : : rte_ether_addr_copy(&active_member_addr,
975 : : ðer_hdr->src_addr);
976 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
977 : : mode6_debug("TX IPv4:", ether_hdr, members[i],
978 : : &burst_number_TX);
979 : : #endif
980 : : }
981 : :
982 : 0 : num_tx_prep = rte_eth_tx_prepare(members[i], bd_tx_q->queue_id,
983 [ # # ]: 0 : bufs + num_tx_total, nb_pkts - num_tx_total);
984 : 0 : num_tx_total += rte_eth_tx_burst(members[i], bd_tx_q->queue_id,
985 : : bufs + num_tx_total, num_tx_prep);
986 : :
987 [ # # ]: 0 : if (num_tx_total == nb_pkts)
988 : : break;
989 : : }
990 : :
991 : : return num_tx_total;
992 : : }
993 : :
994 : : void
995 : 0 : bond_tlb_disable(struct bond_dev_private *internals)
996 : : {
997 : 0 : rte_eal_alarm_cancel(bond_ethdev_update_tlb_member_cb, internals);
998 : 0 : }
999 : :
1000 : : void
1001 : 0 : bond_tlb_enable(struct bond_dev_private *internals)
1002 : : {
1003 : 0 : bond_ethdev_update_tlb_member_cb(internals);
1004 : 0 : }
1005 : :
1006 : : static uint16_t
1007 : 0 : bond_ethdev_tx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
1008 : 0 : {
1009 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
1010 : 0 : struct bond_dev_private *internals = bd_tx_q->dev_private;
1011 : :
1012 : : struct rte_ether_hdr *eth_h;
1013 : : uint16_t ether_type, offset;
1014 : :
1015 : : struct client_data *client_info;
1016 : :
1017 : : /*
1018 : : * We create transmit buffers for every member and one additional to send
1019 : : * through tlb. In worst case every packet will be send on one port.
1020 : : */
1021 : 0 : struct rte_mbuf *member_bufs[RTE_MAX_ETHPORTS + 1][nb_pkts];
1022 : 0 : uint16_t member_bufs_pkts[RTE_MAX_ETHPORTS + 1] = { 0 };
1023 : :
1024 : : /*
1025 : : * We create separate transmit buffers for update packets as they won't
1026 : : * be counted in num_tx_total.
1027 : : */
1028 : : struct rte_mbuf *update_bufs[RTE_MAX_ETHPORTS][ALB_HASH_TABLE_SIZE];
1029 : 0 : uint16_t update_bufs_pkts[RTE_MAX_ETHPORTS] = { 0 };
1030 : :
1031 : : struct rte_mbuf *upd_pkt;
1032 : : size_t pkt_size;
1033 : :
1034 : : uint16_t num_send, num_not_send = 0;
1035 : : uint16_t num_tx_total = 0;
1036 : : uint16_t member_idx;
1037 : :
1038 : : int i, j;
1039 : :
1040 : : /* Search tx buffer for ARP packets and forward them to alb */
1041 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
1042 : 0 : eth_h = rte_pktmbuf_mtod(bufs[i], struct rte_ether_hdr *);
1043 [ # # ]: 0 : ether_type = eth_h->ether_type;
1044 : : offset = get_vlan_offset(eth_h, ðer_type);
1045 : :
1046 [ # # ]: 0 : if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
1047 : 0 : member_idx = bond_mode_alb_arp_xmit(eth_h, offset, internals);
1048 : :
1049 : : /* Change src mac in eth header */
1050 : 0 : rte_eth_macaddr_get(member_idx, ð_h->src_addr);
1051 : :
1052 : : /* Add packet to member tx buffer */
1053 : 0 : member_bufs[member_idx][member_bufs_pkts[member_idx]] = bufs[i];
1054 : 0 : member_bufs_pkts[member_idx]++;
1055 : : } else {
1056 : : /* If packet is not ARP, send it with TLB policy */
1057 : 0 : member_bufs[RTE_MAX_ETHPORTS][member_bufs_pkts[RTE_MAX_ETHPORTS]] =
1058 : : bufs[i];
1059 : 0 : member_bufs_pkts[RTE_MAX_ETHPORTS]++;
1060 : : }
1061 : : }
1062 : :
1063 : : /* Update connected client ARP tables */
1064 [ # # ]: 0 : if (internals->mode6.ntt) {
1065 [ # # ]: 0 : for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) {
1066 : 0 : client_info = &internals->mode6.client_table[i];
1067 : :
1068 [ # # ]: 0 : if (client_info->in_use) {
1069 : : /* Allocate new packet to send ARP update on current member */
1070 : 0 : upd_pkt = rte_pktmbuf_alloc(internals->mode6.mempool);
1071 [ # # ]: 0 : if (upd_pkt == NULL) {
1072 : 0 : RTE_BOND_LOG(ERR,
1073 : : "Failed to allocate ARP packet from pool");
1074 : 0 : continue;
1075 : : }
1076 : 0 : pkt_size = sizeof(struct rte_ether_hdr) +
1077 : : sizeof(struct rte_arp_hdr) +
1078 : 0 : client_info->vlan_count *
1079 : : sizeof(struct rte_vlan_hdr);
1080 : 0 : upd_pkt->data_len = pkt_size;
1081 : 0 : upd_pkt->pkt_len = pkt_size;
1082 : :
1083 : 0 : member_idx = bond_mode_alb_arp_upd(client_info, upd_pkt,
1084 : : internals);
1085 : :
1086 : : /* Add packet to update tx buffer */
1087 : 0 : update_bufs[member_idx][update_bufs_pkts[member_idx]] = upd_pkt;
1088 : 0 : update_bufs_pkts[member_idx]++;
1089 : : }
1090 : : }
1091 : 0 : internals->mode6.ntt = 0;
1092 : : }
1093 : :
1094 : : /* Send ARP packets on proper members */
1095 [ # # ]: 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
1096 [ # # ]: 0 : if (member_bufs_pkts[i] > 0) {
1097 : 0 : num_send = rte_eth_tx_prepare(i, bd_tx_q->queue_id,
1098 [ # # ]: 0 : member_bufs[i], member_bufs_pkts[i]);
1099 : 0 : num_send = rte_eth_tx_burst(i, bd_tx_q->queue_id,
1100 : : member_bufs[i], num_send);
1101 [ # # ]: 0 : for (j = 0; j < member_bufs_pkts[i] - num_send; j++) {
1102 : 0 : bufs[nb_pkts - 1 - num_not_send - j] =
1103 : 0 : member_bufs[i][nb_pkts - 1 - j];
1104 : : }
1105 : :
1106 : 0 : num_tx_total += num_send;
1107 : 0 : num_not_send += member_bufs_pkts[i] - num_send;
1108 : :
1109 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
1110 : : /* Print TX stats including update packets */
1111 : : for (j = 0; j < member_bufs_pkts[i]; j++) {
1112 : : eth_h = rte_pktmbuf_mtod(member_bufs[i][j],
1113 : : struct rte_ether_hdr *);
1114 : : mode6_debug("TX ARP:", eth_h, i, &burst_number_TX);
1115 : : }
1116 : : #endif
1117 : : }
1118 : : }
1119 : :
1120 : : /* Send update packets on proper members */
1121 [ # # ]: 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
1122 [ # # ]: 0 : if (update_bufs_pkts[i] > 0) {
1123 : 0 : num_send = rte_eth_tx_prepare(i, bd_tx_q->queue_id,
1124 [ # # ]: 0 : update_bufs[i], update_bufs_pkts[i]);
1125 : 0 : num_send = rte_eth_tx_burst(i, bd_tx_q->queue_id, update_bufs[i],
1126 : : num_send);
1127 [ # # ]: 0 : for (j = num_send; j < update_bufs_pkts[i]; j++) {
1128 : 0 : rte_pktmbuf_free(update_bufs[i][j]);
1129 : : }
1130 : : #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1)
1131 : : for (j = 0; j < update_bufs_pkts[i]; j++) {
1132 : : eth_h = rte_pktmbuf_mtod(update_bufs[i][j],
1133 : : struct rte_ether_hdr *);
1134 : : mode6_debug("TX ARPupd:", eth_h, i, &burst_number_TX);
1135 : : }
1136 : : #endif
1137 : : }
1138 : : }
1139 : :
1140 : : /* Send non-ARP packets using tlb policy */
1141 [ # # ]: 0 : if (member_bufs_pkts[RTE_MAX_ETHPORTS] > 0) {
1142 : 0 : num_send = bond_ethdev_tx_burst_tlb(queue,
1143 : 0 : member_bufs[RTE_MAX_ETHPORTS],
1144 : : member_bufs_pkts[RTE_MAX_ETHPORTS]);
1145 : :
1146 [ # # ]: 0 : for (j = 0; j < member_bufs_pkts[RTE_MAX_ETHPORTS]; j++) {
1147 : 0 : bufs[nb_pkts - 1 - num_not_send - j] =
1148 : 0 : member_bufs[RTE_MAX_ETHPORTS][nb_pkts - 1 - j];
1149 : : }
1150 : :
1151 : 0 : num_tx_total += num_send;
1152 : : }
1153 : :
1154 : 0 : return num_tx_total;
1155 : : }
1156 : :
1157 : : static inline uint16_t
1158 : 0 : tx_burst_balance(void *queue, struct rte_mbuf **bufs, uint16_t nb_bufs,
1159 : : uint16_t *member_port_ids, uint16_t member_count)
1160 : 0 : {
1161 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
1162 : 0 : struct bond_dev_private *internals = bd_tx_q->dev_private;
1163 : :
1164 : : /* Array to sort mbufs for transmission on each member into */
1165 : 0 : struct rte_mbuf *member_bufs[RTE_MAX_ETHPORTS][nb_bufs];
1166 : : /* Number of mbufs for transmission on each member */
1167 : 0 : uint16_t member_nb_bufs[RTE_MAX_ETHPORTS] = { 0 };
1168 : : /* Mapping array generated by hash function to map mbufs to members */
1169 : 0 : uint16_t bufs_member_port_idxs[nb_bufs];
1170 : :
1171 : : uint16_t member_tx_count;
1172 : : uint16_t total_tx_count = 0, total_tx_fail_count = 0;
1173 : :
1174 : : uint16_t i;
1175 : :
1176 : : /*
1177 : : * Populate members mbuf with the packets which are to be sent on it
1178 : : * selecting output member using hash based on xmit policy
1179 : : */
1180 : 0 : internals->burst_xmit_hash(bufs, nb_bufs, member_count,
1181 : : bufs_member_port_idxs);
1182 : :
1183 [ # # ]: 0 : for (i = 0; i < nb_bufs; i++) {
1184 : : /* Populate member mbuf arrays with mbufs for that member. */
1185 : 0 : uint16_t member_idx = bufs_member_port_idxs[i];
1186 : :
1187 : 0 : member_bufs[member_idx][member_nb_bufs[member_idx]++] = bufs[i];
1188 : : }
1189 : :
1190 : : /* Send packet burst on each member device */
1191 [ # # ]: 0 : for (i = 0; i < member_count; i++) {
1192 [ # # ]: 0 : if (member_nb_bufs[i] == 0)
1193 : 0 : continue;
1194 : :
1195 : 0 : member_tx_count = rte_eth_tx_prepare(member_port_ids[i],
1196 [ # # ]: 0 : bd_tx_q->queue_id, member_bufs[i],
1197 : : member_nb_bufs[i]);
1198 : 0 : member_tx_count = rte_eth_tx_burst(member_port_ids[i],
1199 : 0 : bd_tx_q->queue_id, member_bufs[i],
1200 : : member_tx_count);
1201 : :
1202 : 0 : total_tx_count += member_tx_count;
1203 : :
1204 : : /* If tx burst fails move packets to end of bufs */
1205 [ # # ]: 0 : if (unlikely(member_tx_count < member_nb_bufs[i])) {
1206 : 0 : int member_tx_fail_count = member_nb_bufs[i] -
1207 : : member_tx_count;
1208 : 0 : total_tx_fail_count += member_tx_fail_count;
1209 : 0 : memcpy(&bufs[nb_bufs - total_tx_fail_count],
1210 : 0 : &member_bufs[i][member_tx_count],
1211 : : member_tx_fail_count * sizeof(bufs[0]));
1212 : : }
1213 : : }
1214 : :
1215 : 0 : return total_tx_count;
1216 : : }
1217 : :
1218 : : static uint16_t
1219 : 0 : bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,
1220 : : uint16_t nb_bufs)
1221 : : {
1222 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
1223 : 0 : struct bond_dev_private *internals = bd_tx_q->dev_private;
1224 : :
1225 : : uint16_t member_port_ids[RTE_MAX_ETHPORTS];
1226 : : uint16_t member_count;
1227 : :
1228 [ # # ]: 0 : if (unlikely(nb_bufs == 0))
1229 : : return 0;
1230 : :
1231 : : /* Copy member list to protect against member up/down changes during tx
1232 : : * bursting
1233 : : */
1234 : 0 : member_count = internals->active_member_count;
1235 [ # # ]: 0 : if (unlikely(member_count < 1))
1236 : : return 0;
1237 : :
1238 : 0 : memcpy(member_port_ids, internals->active_members,
1239 : : sizeof(member_port_ids[0]) * member_count);
1240 : 0 : return tx_burst_balance(queue, bufs, nb_bufs, member_port_ids,
1241 : : member_count);
1242 : : }
1243 : :
1244 : : static inline uint16_t
1245 : 0 : tx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_bufs,
1246 : : bool dedicated_txq)
1247 : : {
1248 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
1249 : 0 : struct bond_dev_private *internals = bd_tx_q->dev_private;
1250 : :
1251 : : uint16_t member_port_ids[RTE_MAX_ETHPORTS];
1252 : : uint16_t member_count;
1253 : :
1254 : : uint16_t dist_member_port_ids[RTE_MAX_ETHPORTS];
1255 : : uint16_t dist_member_count;
1256 : :
1257 : : uint16_t member_tx_count;
1258 : :
1259 : : uint16_t i;
1260 : :
1261 : : /* Copy member list to protect against member up/down changes during tx
1262 : : * bursting */
1263 : 0 : member_count = internals->active_member_count;
1264 [ # # ]: 0 : if (unlikely(member_count < 1))
1265 : : return 0;
1266 : :
1267 [ # # ]: 0 : memcpy(member_port_ids, internals->active_members,
1268 : : sizeof(member_port_ids[0]) * member_count);
1269 : :
1270 [ # # ]: 0 : if (dedicated_txq)
1271 : 0 : goto skip_tx_ring;
1272 : :
1273 : : /* Check for LACP control packets and send if available */
1274 [ # # ]: 0 : for (i = 0; i < member_count; i++) {
1275 : 0 : struct port *port = &bond_mode_8023ad_ports[member_port_ids[i]];
1276 : 0 : struct rte_mbuf *ctrl_pkt = NULL;
1277 : :
1278 [ # # ]: 0 : if (likely(rte_ring_empty(port->tx_ring)))
1279 : 0 : continue;
1280 : :
1281 : : if (rte_ring_dequeue(port->tx_ring,
1282 : : (void **)&ctrl_pkt) != -ENOENT) {
1283 : 0 : member_tx_count = rte_eth_tx_prepare(member_port_ids[i],
1284 [ # # ]: 0 : bd_tx_q->queue_id, &ctrl_pkt, 1);
1285 : 0 : member_tx_count = rte_eth_tx_burst(member_port_ids[i],
1286 : 0 : bd_tx_q->queue_id, &ctrl_pkt, member_tx_count);
1287 : : /*
1288 : : * re-enqueue LAG control plane packets to buffering
1289 : : * ring if transmission fails so the packet isn't lost.
1290 : : */
1291 [ # # ]: 0 : if (member_tx_count != 1)
1292 [ # # # # : 0 : rte_ring_enqueue(port->tx_ring, ctrl_pkt);
# ]
1293 : : }
1294 : : }
1295 : :
1296 : 0 : skip_tx_ring:
1297 [ # # ]: 0 : if (unlikely(nb_bufs == 0))
1298 : : return 0;
1299 : :
1300 : : dist_member_count = 0;
1301 [ # # ]: 0 : for (i = 0; i < member_count; i++) {
1302 : 0 : struct port *port = &bond_mode_8023ad_ports[member_port_ids[i]];
1303 : :
1304 [ # # ]: 0 : if (ACTOR_STATE(port, DISTRIBUTING))
1305 : 0 : dist_member_port_ids[dist_member_count++] =
1306 : : member_port_ids[i];
1307 : : }
1308 : :
1309 [ # # ]: 0 : if (unlikely(dist_member_count < 1))
1310 : : return 0;
1311 : :
1312 : 0 : return tx_burst_balance(queue, bufs, nb_bufs, dist_member_port_ids,
1313 : : dist_member_count);
1314 : : }
1315 : :
1316 : : static uint16_t
1317 : 0 : bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
1318 : : uint16_t nb_bufs)
1319 : : {
1320 : 0 : return tx_burst_8023ad(queue, bufs, nb_bufs, false);
1321 : : }
1322 : :
1323 : : static uint16_t
1324 : 0 : bond_ethdev_tx_burst_8023ad_fast_queue(void *queue, struct rte_mbuf **bufs,
1325 : : uint16_t nb_bufs)
1326 : : {
1327 : 0 : return tx_burst_8023ad(queue, bufs, nb_bufs, true);
1328 : : }
1329 : :
1330 : : static uint16_t
1331 : 0 : bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,
1332 : : uint16_t nb_pkts)
1333 : : {
1334 : : struct bond_dev_private *internals;
1335 : : struct bond_tx_queue *bd_tx_q;
1336 : :
1337 : : uint16_t members[RTE_MAX_ETHPORTS];
1338 : : uint8_t tx_failed_flag = 0;
1339 : : uint16_t num_of_members;
1340 : :
1341 : : uint16_t max_nb_of_tx_pkts = 0;
1342 : :
1343 : : int member_tx_total[RTE_MAX_ETHPORTS];
1344 : : int i, most_successful_tx_member = -1;
1345 : :
1346 : : bd_tx_q = (struct bond_tx_queue *)queue;
1347 : 0 : internals = bd_tx_q->dev_private;
1348 : :
1349 : : /* Copy member list to protect against member up/down changes during tx
1350 : : * bursting */
1351 : 0 : num_of_members = internals->active_member_count;
1352 [ # # ]: 0 : memcpy(members, internals->active_members,
1353 : : sizeof(internals->active_members[0]) * num_of_members);
1354 : :
1355 [ # # ]: 0 : if (num_of_members < 1)
1356 : : return 0;
1357 : :
1358 : : /* It is rare that bond different PMDs together, so just call tx-prepare once */
1359 [ # # ]: 0 : nb_pkts = rte_eth_tx_prepare(members[0], bd_tx_q->queue_id, bufs, nb_pkts);
1360 : :
1361 : : /* Increment reference count on mbufs */
1362 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++)
1363 : 0 : rte_pktmbuf_refcnt_update(bufs[i], num_of_members - 1);
1364 : :
1365 : : /* Transmit burst on each active member */
1366 [ # # ]: 0 : for (i = 0; i < num_of_members; i++) {
1367 : 0 : member_tx_total[i] = rte_eth_tx_burst(members[i], bd_tx_q->queue_id,
1368 : : bufs, nb_pkts);
1369 : :
1370 [ # # ]: 0 : if (unlikely(member_tx_total[i] < nb_pkts))
1371 : : tx_failed_flag = 1;
1372 : :
1373 : : /* record the value and member index for the member which transmits the
1374 : : * maximum number of packets */
1375 [ # # ]: 0 : if (member_tx_total[i] > max_nb_of_tx_pkts) {
1376 : : max_nb_of_tx_pkts = member_tx_total[i];
1377 : : most_successful_tx_member = i;
1378 : : }
1379 : : }
1380 : :
1381 : : /* if members fail to transmit packets from burst, the calling application
1382 : : * is not expected to know about multiple references to packets so we must
1383 : : * handle failures of all packets except those of the most successful member
1384 : : */
1385 [ # # ]: 0 : if (unlikely(tx_failed_flag))
1386 [ # # ]: 0 : for (i = 0; i < num_of_members; i++)
1387 [ # # ]: 0 : if (i != most_successful_tx_member)
1388 [ # # ]: 0 : while (member_tx_total[i] < nb_pkts)
1389 : 0 : rte_pktmbuf_free(bufs[member_tx_total[i]++]);
1390 : :
1391 : : return max_nb_of_tx_pkts;
1392 : : }
1393 : :
1394 : : static void
1395 : : link_properties_set(struct rte_eth_dev *ethdev, struct rte_eth_link *member_link)
1396 : : {
1397 : 0 : struct bond_dev_private *bond_ctx = ethdev->data->dev_private;
1398 : :
1399 [ # # ]: 0 : if (bond_ctx->mode == BONDING_MODE_8023AD) {
1400 : : /**
1401 : : * If in mode 4 then save the link properties of the first
1402 : : * member, all subsequent members must match these properties
1403 : : */
1404 : : struct rte_eth_link *bond_link = &bond_ctx->mode4.member_link;
1405 : :
1406 : 0 : bond_link->link_autoneg = member_link->link_autoneg;
1407 : 0 : bond_link->link_duplex = member_link->link_duplex;
1408 : 0 : bond_link->link_speed = member_link->link_speed;
1409 : : } else {
1410 : : /**
1411 : : * In any other mode the link properties are set to default
1412 : : * values of AUTONEG/DUPLEX
1413 : : */
1414 : 0 : ethdev->data->dev_link.link_autoneg = RTE_ETH_LINK_AUTONEG;
1415 : 0 : ethdev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
1416 : : }
1417 : : }
1418 : :
1419 : : static int
1420 : : link_properties_valid(struct rte_eth_dev *ethdev,
1421 : : struct rte_eth_link *member_link)
1422 : : {
1423 : 0 : struct bond_dev_private *bond_ctx = ethdev->data->dev_private;
1424 : :
1425 [ # # ]: 0 : if (bond_ctx->mode == BONDING_MODE_8023AD) {
1426 : : struct rte_eth_link *bond_link = &bond_ctx->mode4.member_link;
1427 : :
1428 [ # # ]: 0 : if (bond_link->link_duplex != member_link->link_duplex ||
1429 : 0 : bond_link->link_autoneg != member_link->link_autoneg ||
1430 [ # # ]: 0 : bond_link->link_speed != member_link->link_speed)
1431 : : return -1;
1432 : : }
1433 : :
1434 : : return 0;
1435 : : }
1436 : :
1437 : : int
1438 : 0 : mac_address_get(struct rte_eth_dev *eth_dev,
1439 : : struct rte_ether_addr *dst_mac_addr)
1440 : : {
1441 : : struct rte_ether_addr *mac_addr;
1442 : :
1443 [ # # ]: 0 : if (eth_dev == NULL) {
1444 : 0 : RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified");
1445 : 0 : return -1;
1446 : : }
1447 : :
1448 [ # # ]: 0 : if (dst_mac_addr == NULL) {
1449 : 0 : RTE_BOND_LOG(ERR, "NULL pointer MAC specified");
1450 : 0 : return -1;
1451 : : }
1452 : :
1453 : 0 : mac_addr = eth_dev->data->mac_addrs;
1454 : :
1455 : : rte_ether_addr_copy(mac_addr, dst_mac_addr);
1456 : 0 : return 0;
1457 : : }
1458 : :
1459 : : int
1460 : 0 : mac_address_set(struct rte_eth_dev *eth_dev,
1461 : : struct rte_ether_addr *new_mac_addr)
1462 : : {
1463 : : struct rte_ether_addr *mac_addr;
1464 : :
1465 [ # # ]: 0 : if (eth_dev == NULL) {
1466 : 0 : RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified");
1467 : 0 : return -1;
1468 : : }
1469 : :
1470 [ # # ]: 0 : if (new_mac_addr == NULL) {
1471 : 0 : RTE_BOND_LOG(ERR, "NULL pointer MAC specified");
1472 : 0 : return -1;
1473 : : }
1474 : :
1475 : 0 : mac_addr = eth_dev->data->mac_addrs;
1476 : :
1477 : : /* If new MAC is different to current MAC then update */
1478 [ # # ]: 0 : if (memcmp(mac_addr, new_mac_addr, sizeof(*mac_addr)) != 0)
1479 : : memcpy(mac_addr, new_mac_addr, sizeof(*mac_addr));
1480 : :
1481 : : return 0;
1482 : : }
1483 : :
1484 : : static const struct rte_ether_addr null_mac_addr;
1485 : :
1486 : : /*
1487 : : * Add additional MAC addresses to the member
1488 : : */
1489 : : int
1490 : 0 : member_add_mac_addresses(struct rte_eth_dev *bonding_eth_dev,
1491 : : uint16_t member_port_id)
1492 : : {
1493 : : int i, ret;
1494 : : struct rte_ether_addr *mac_addr;
1495 : :
1496 [ # # ]: 0 : for (i = 1; i < BOND_MAX_MAC_ADDRS; i++) {
1497 [ # # ]: 0 : mac_addr = &bonding_eth_dev->data->mac_addrs[i];
1498 [ # # ]: 0 : if (rte_is_same_ether_addr(mac_addr, &null_mac_addr))
1499 : : break;
1500 : :
1501 : 0 : ret = rte_eth_dev_mac_addr_add(member_port_id, mac_addr, 0);
1502 [ # # ]: 0 : if (ret < 0) {
1503 : : /* rollback */
1504 [ # # ]: 0 : for (i--; i > 0; i--)
1505 : 0 : rte_eth_dev_mac_addr_remove(member_port_id,
1506 : 0 : &bonding_eth_dev->data->mac_addrs[i]);
1507 : : return ret;
1508 : : }
1509 : : }
1510 : :
1511 : : return 0;
1512 : : }
1513 : :
1514 : : /*
1515 : : * Remove additional MAC addresses from the member
1516 : : */
1517 : : int
1518 : 0 : member_remove_mac_addresses(struct rte_eth_dev *bonding_eth_dev,
1519 : : uint16_t member_port_id)
1520 : : {
1521 : : int i, rc, ret;
1522 : : struct rte_ether_addr *mac_addr;
1523 : :
1524 : : rc = 0;
1525 [ # # ]: 0 : for (i = 1; i < BOND_MAX_MAC_ADDRS; i++) {
1526 [ # # ]: 0 : mac_addr = &bonding_eth_dev->data->mac_addrs[i];
1527 [ # # ]: 0 : if (rte_is_same_ether_addr(mac_addr, &null_mac_addr))
1528 : : break;
1529 : :
1530 : 0 : ret = rte_eth_dev_mac_addr_remove(member_port_id, mac_addr);
1531 : : /* save only the first error */
1532 [ # # ]: 0 : if (ret < 0 && rc == 0)
1533 : : rc = ret;
1534 : : }
1535 : :
1536 : 0 : return rc;
1537 : : }
1538 : :
1539 : : int
1540 : 0 : mac_address_members_update(struct rte_eth_dev *bonding_eth_dev)
1541 : : {
1542 : 0 : struct bond_dev_private *internals = bonding_eth_dev->data->dev_private;
1543 : : bool set;
1544 : : int i;
1545 : :
1546 : : /* Update member devices MAC addresses */
1547 [ # # ]: 0 : if (internals->member_count < 1)
1548 : : return -1;
1549 : :
1550 [ # # # ]: 0 : switch (internals->mode) {
1551 : : case BONDING_MODE_ROUND_ROBIN:
1552 : : case BONDING_MODE_BALANCE:
1553 : : case BONDING_MODE_BROADCAST:
1554 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
1555 [ # # ]: 0 : if (rte_eth_dev_default_mac_addr_set(
1556 : 0 : internals->members[i].port_id,
1557 : 0 : bonding_eth_dev->data->mac_addrs)) {
1558 : 0 : RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
1559 : : internals->members[i].port_id);
1560 : 0 : return -1;
1561 : : }
1562 : : }
1563 : : break;
1564 : 0 : case BONDING_MODE_8023AD:
1565 : 0 : bond_mode_8023ad_mac_address_update(bonding_eth_dev);
1566 : 0 : break;
1567 : : case BONDING_MODE_ACTIVE_BACKUP:
1568 : : case BONDING_MODE_TLB:
1569 : : case BONDING_MODE_ALB:
1570 : : default:
1571 : : set = true;
1572 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
1573 : 0 : if (internals->members[i].port_id ==
1574 [ # # ]: 0 : internals->current_primary_port) {
1575 [ # # ]: 0 : if (rte_eth_dev_default_mac_addr_set(
1576 : : internals->current_primary_port,
1577 : 0 : bonding_eth_dev->data->mac_addrs)) {
1578 : 0 : RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
1579 : : internals->current_primary_port);
1580 : : set = false;
1581 : : }
1582 : : } else {
1583 [ # # ]: 0 : if (rte_eth_dev_default_mac_addr_set(
1584 : : internals->members[i].port_id,
1585 : : &internals->members[i].persisted_mac_addr)) {
1586 : 0 : RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
1587 : : internals->members[i].port_id);
1588 : : }
1589 : : }
1590 : : }
1591 [ # # ]: 0 : if (!set)
1592 : 0 : return -1;
1593 : : }
1594 : :
1595 : : return 0;
1596 : : }
1597 : :
1598 : : int
1599 : 0 : bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, uint8_t mode)
1600 : : {
1601 : : struct bond_dev_private *internals;
1602 : :
1603 : 0 : internals = eth_dev->data->dev_private;
1604 : :
1605 [ # # # # : 0 : switch (mode) {
# # # # ]
1606 : 0 : case BONDING_MODE_ROUND_ROBIN:
1607 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_round_robin;
1608 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
1609 : 0 : break;
1610 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
1611 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_active_backup;
1612 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
1613 : 0 : break;
1614 : 0 : case BONDING_MODE_BALANCE:
1615 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_balance;
1616 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
1617 : 0 : break;
1618 : 0 : case BONDING_MODE_BROADCAST:
1619 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast;
1620 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
1621 : 0 : break;
1622 : 0 : case BONDING_MODE_8023AD:
1623 [ # # ]: 0 : if (bond_mode_8023ad_enable(eth_dev) != 0)
1624 : : return -1;
1625 : :
1626 [ # # ]: 0 : if (internals->mode4.dedicated_queues.enabled == 0) {
1627 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_8023ad;
1628 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_8023ad;
1629 : 0 : RTE_BOND_LOG(WARNING,
1630 : : "Using mode 4, it is necessary to do TX burst "
1631 : : "and RX burst at least every 100ms.");
1632 : : } else {
1633 : : /* Use flow director's optimization */
1634 : 0 : eth_dev->rx_pkt_burst =
1635 : : bond_ethdev_rx_burst_8023ad_fast_queue;
1636 : 0 : eth_dev->tx_pkt_burst =
1637 : : bond_ethdev_tx_burst_8023ad_fast_queue;
1638 : : }
1639 : : break;
1640 : 0 : case BONDING_MODE_TLB:
1641 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_tlb;
1642 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
1643 : 0 : break;
1644 : 0 : case BONDING_MODE_ALB:
1645 [ # # ]: 0 : if (bond_mode_alb_enable(eth_dev) != 0)
1646 : : return -1;
1647 : :
1648 : 0 : eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb;
1649 : 0 : eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb;
1650 : 0 : break;
1651 : : default:
1652 : : return -1;
1653 : : }
1654 : :
1655 : 0 : internals->mode = mode;
1656 : :
1657 : 0 : return 0;
1658 : : }
1659 : :
1660 : :
1661 : : static int
1662 : 0 : member_configure_slow_queue(struct rte_eth_dev *bonding_eth_dev,
1663 : : struct rte_eth_dev *member_eth_dev)
1664 : : {
1665 : : int errval = 0;
1666 : 0 : struct bond_dev_private *internals = bonding_eth_dev->data->dev_private;
1667 : 0 : struct port *port = &bond_mode_8023ad_ports[member_eth_dev->data->port_id];
1668 : :
1669 [ # # ]: 0 : if (port->slow_pool == NULL) {
1670 : : char mem_name[256];
1671 : : int member_id = member_eth_dev->data->port_id;
1672 : :
1673 : : snprintf(mem_name, RTE_DIM(mem_name), "member_port%u_slow_pool",
1674 : : member_id);
1675 : 0 : port->slow_pool = rte_pktmbuf_pool_create(mem_name, 8191,
1676 : : 250, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
1677 : 0 : member_eth_dev->data->numa_node);
1678 : :
1679 : : /* Any memory allocation failure in initialization is critical because
1680 : : * resources can't be free, so reinitialization is impossible. */
1681 [ # # ]: 0 : if (port->slow_pool == NULL) {
1682 : 0 : rte_panic("Member %u: Failed to create memory pool '%s': %s\n",
1683 : : member_id, mem_name, rte_strerror(rte_errno));
1684 : : }
1685 : : }
1686 : :
1687 [ # # ]: 0 : if (internals->mode4.dedicated_queues.enabled == 1) {
1688 : : /* Configure slow Rx queue */
1689 : :
1690 : 0 : errval = rte_eth_rx_queue_setup(member_eth_dev->data->port_id,
1691 : 0 : internals->mode4.dedicated_queues.rx_qid, 128,
1692 : 0 : rte_eth_dev_socket_id(member_eth_dev->data->port_id),
1693 : : NULL, port->slow_pool);
1694 [ # # ]: 0 : if (errval != 0) {
1695 : 0 : RTE_BOND_LOG(ERR,
1696 : : "rte_eth_rx_queue_setup: port=%d queue_id %d, err (%d)",
1697 : : member_eth_dev->data->port_id,
1698 : : internals->mode4.dedicated_queues.rx_qid,
1699 : : errval);
1700 : 0 : return errval;
1701 : : }
1702 : :
1703 : 0 : errval = rte_eth_tx_queue_setup(member_eth_dev->data->port_id,
1704 : 0 : internals->mode4.dedicated_queues.tx_qid, 512,
1705 : 0 : rte_eth_dev_socket_id(member_eth_dev->data->port_id),
1706 : : NULL);
1707 [ # # ]: 0 : if (errval != 0) {
1708 : 0 : RTE_BOND_LOG(ERR,
1709 : : "rte_eth_tx_queue_setup: port=%d queue_id %d, err (%d)",
1710 : : member_eth_dev->data->port_id,
1711 : : internals->mode4.dedicated_queues.tx_qid,
1712 : : errval);
1713 : 0 : return errval;
1714 : : }
1715 : : }
1716 : : return 0;
1717 : : }
1718 : :
1719 : : int
1720 : 0 : member_configure(struct rte_eth_dev *bonding_eth_dev,
1721 : : struct rte_eth_dev *member_eth_dev)
1722 : : {
1723 : : uint16_t nb_rx_queues;
1724 : : uint16_t nb_tx_queues;
1725 : :
1726 : : int errval;
1727 : :
1728 : 0 : struct bond_dev_private *internals = bonding_eth_dev->data->dev_private;
1729 : :
1730 : : /* Stop member */
1731 : 0 : errval = rte_eth_dev_stop(member_eth_dev->data->port_id);
1732 [ # # ]: 0 : if (errval != 0)
1733 : 0 : RTE_BOND_LOG(ERR, "rte_eth_dev_stop: port %u, err (%d)",
1734 : : member_eth_dev->data->port_id, errval);
1735 : :
1736 : : /* Enable interrupts on member device if supported */
1737 [ # # ]: 0 : if (member_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
1738 : 0 : member_eth_dev->data->dev_conf.intr_conf.lsc = 1;
1739 : :
1740 : : /* If RSS is enabled for bonding, try to enable it for members */
1741 [ # # ]: 0 : if (bonding_eth_dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
1742 : : /* rss_key won't be empty if RSS is configured in bonding dev */
1743 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len =
1744 : 0 : internals->rss_key_len;
1745 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key =
1746 : 0 : internals->rss_key;
1747 : :
1748 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
1749 : 0 : bonding_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
1750 : 0 : member_eth_dev->data->dev_conf.rxmode.mq_mode =
1751 : : bonding_eth_dev->data->dev_conf.rxmode.mq_mode;
1752 : : } else {
1753 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key_len = 0;
1754 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
1755 : 0 : member_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
1756 : 0 : member_eth_dev->data->dev_conf.rxmode.mq_mode =
1757 : : bonding_eth_dev->data->dev_conf.rxmode.mq_mode;
1758 : : }
1759 : :
1760 : 0 : member_eth_dev->data->dev_conf.rxmode.mtu =
1761 : 0 : bonding_eth_dev->data->dev_conf.rxmode.mtu;
1762 : 0 : member_eth_dev->data->dev_conf.link_speeds =
1763 : 0 : bonding_eth_dev->data->dev_conf.link_speeds;
1764 : :
1765 : 0 : member_eth_dev->data->dev_conf.txmode.offloads =
1766 : 0 : bonding_eth_dev->data->dev_conf.txmode.offloads;
1767 : :
1768 : 0 : member_eth_dev->data->dev_conf.rxmode.offloads =
1769 : 0 : bonding_eth_dev->data->dev_conf.rxmode.offloads;
1770 : :
1771 : 0 : nb_rx_queues = bonding_eth_dev->data->nb_rx_queues;
1772 : 0 : nb_tx_queues = bonding_eth_dev->data->nb_tx_queues;
1773 : :
1774 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD) {
1775 [ # # ]: 0 : if (internals->mode4.dedicated_queues.enabled == 1) {
1776 : 0 : nb_rx_queues++;
1777 : 0 : nb_tx_queues++;
1778 : : }
1779 : : }
1780 : :
1781 : : /* Configure device */
1782 : 0 : errval = rte_eth_dev_configure(member_eth_dev->data->port_id,
1783 : : nb_rx_queues, nb_tx_queues,
1784 : 0 : &member_eth_dev->data->dev_conf);
1785 [ # # ]: 0 : if (errval != 0) {
1786 : 0 : RTE_BOND_LOG(ERR, "Cannot configure member device: port %u, err (%d)",
1787 : : member_eth_dev->data->port_id, errval);
1788 : 0 : return errval;
1789 : : }
1790 : :
1791 : 0 : errval = rte_eth_dev_set_mtu(member_eth_dev->data->port_id,
1792 : 0 : bonding_eth_dev->data->mtu);
1793 [ # # ]: 0 : if (errval != 0 && errval != -ENOTSUP) {
1794 : 0 : RTE_BOND_LOG(ERR, "rte_eth_dev_set_mtu: port %u, err (%d)",
1795 : : member_eth_dev->data->port_id, errval);
1796 : 0 : return errval;
1797 : : }
1798 : : return 0;
1799 : : }
1800 : :
1801 : : int
1802 : 0 : member_start(struct rte_eth_dev *bonding_eth_dev,
1803 : : struct rte_eth_dev *member_eth_dev)
1804 : : {
1805 : : int errval = 0;
1806 : : struct bond_rx_queue *bd_rx_q;
1807 : : struct bond_tx_queue *bd_tx_q;
1808 : : uint16_t q_id;
1809 : : struct rte_flow_error flow_error;
1810 : 0 : struct bond_dev_private *internals = bonding_eth_dev->data->dev_private;
1811 : 0 : uint16_t member_port_id = member_eth_dev->data->port_id;
1812 : :
1813 : : /* Setup Rx Queues */
1814 [ # # ]: 0 : for (q_id = 0; q_id < bonding_eth_dev->data->nb_rx_queues; q_id++) {
1815 : 0 : bd_rx_q = (struct bond_rx_queue *)bonding_eth_dev->data->rx_queues[q_id];
1816 : :
1817 : 0 : errval = rte_eth_rx_queue_setup(member_port_id, q_id,
1818 : 0 : bd_rx_q->nb_rx_desc,
1819 : 0 : rte_eth_dev_socket_id(member_port_id),
1820 : 0 : &(bd_rx_q->rx_conf), bd_rx_q->mb_pool);
1821 [ # # ]: 0 : if (errval != 0) {
1822 : 0 : RTE_BOND_LOG(ERR,
1823 : : "rte_eth_rx_queue_setup: port=%d queue_id %d, err (%d)",
1824 : : member_port_id, q_id, errval);
1825 : 0 : return errval;
1826 : : }
1827 : : }
1828 : :
1829 : : /* Setup Tx Queues */
1830 [ # # ]: 0 : for (q_id = 0; q_id < bonding_eth_dev->data->nb_tx_queues; q_id++) {
1831 : 0 : bd_tx_q = (struct bond_tx_queue *)bonding_eth_dev->data->tx_queues[q_id];
1832 : :
1833 : 0 : errval = rte_eth_tx_queue_setup(member_port_id, q_id,
1834 : 0 : bd_tx_q->nb_tx_desc,
1835 : 0 : rte_eth_dev_socket_id(member_port_id),
1836 : 0 : &bd_tx_q->tx_conf);
1837 [ # # ]: 0 : if (errval != 0) {
1838 : 0 : RTE_BOND_LOG(ERR,
1839 : : "rte_eth_tx_queue_setup: port=%d queue_id %d, err (%d)",
1840 : : member_port_id, q_id, errval);
1841 : 0 : return errval;
1842 : : }
1843 : : }
1844 : :
1845 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD &&
1846 [ # # ]: 0 : internals->mode4.dedicated_queues.enabled == 1) {
1847 [ # # ]: 0 : if (member_configure_slow_queue(bonding_eth_dev, member_eth_dev)
1848 : : != 0)
1849 : : return errval;
1850 : :
1851 : 0 : errval = bond_ethdev_8023ad_flow_verify(bonding_eth_dev,
1852 : : member_port_id);
1853 [ # # ]: 0 : if (errval != 0) {
1854 : 0 : RTE_BOND_LOG(ERR,
1855 : : "bond_ethdev_8023ad_flow_verify: port=%d, err (%d)",
1856 : : member_port_id, errval);
1857 : 0 : return errval;
1858 : : }
1859 : :
1860 [ # # ]: 0 : if (internals->mode4.dedicated_queues.flow[member_port_id] != NULL) {
1861 : 0 : errval = rte_flow_destroy(member_port_id,
1862 : : internals->mode4.dedicated_queues.flow[member_port_id],
1863 : : &flow_error);
1864 : 0 : RTE_BOND_LOG(ERR, "bond_ethdev_8023ad_flow_destroy: port=%d, err (%d)",
1865 : : member_port_id, errval);
1866 : : }
1867 : : }
1868 : :
1869 : : /* Start device */
1870 : 0 : errval = rte_eth_dev_start(member_port_id);
1871 [ # # ]: 0 : if (errval != 0) {
1872 : 0 : RTE_BOND_LOG(ERR, "rte_eth_dev_start: port=%u, err (%d)",
1873 : : member_port_id, errval);
1874 : 0 : return -1;
1875 : : }
1876 : :
1877 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD &&
1878 [ # # ]: 0 : internals->mode4.dedicated_queues.enabled == 1) {
1879 : 0 : errval = bond_ethdev_8023ad_flow_set(bonding_eth_dev,
1880 : : member_port_id);
1881 [ # # ]: 0 : if (errval != 0) {
1882 : 0 : RTE_BOND_LOG(ERR,
1883 : : "bond_ethdev_8023ad_flow_set: port=%d, err (%d)",
1884 : : member_port_id, errval);
1885 : 0 : return errval;
1886 : : }
1887 : : }
1888 : :
1889 : : /* If RSS is enabled for bonding, synchronize RETA */
1890 [ # # ]: 0 : if (bonding_eth_dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) {
1891 : : int i;
1892 : : struct bond_dev_private *internals;
1893 : :
1894 : 0 : internals = bonding_eth_dev->data->dev_private;
1895 : :
1896 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
1897 [ # # ]: 0 : if (internals->members[i].port_id == member_port_id) {
1898 : 0 : errval = rte_eth_dev_rss_reta_update(
1899 : : member_port_id,
1900 : : &internals->reta_conf[0],
1901 : 0 : internals->members[i].reta_size);
1902 [ # # ]: 0 : if (errval != 0) {
1903 : 0 : RTE_BOND_LOG(WARNING,
1904 : : "rte_eth_dev_rss_reta_update on member port %d fails (err %d)."
1905 : : " RSS Configuration for bonding may be inconsistent.",
1906 : : member_port_id, errval);
1907 : : }
1908 : : break;
1909 : : }
1910 : : }
1911 : : }
1912 : :
1913 : : /* If lsc interrupt is set, check initial member's link status */
1914 [ # # ]: 0 : if (member_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
1915 : 0 : member_eth_dev->dev_ops->link_update(member_eth_dev, 0);
1916 : 0 : bond_ethdev_lsc_event_callback(member_port_id,
1917 : 0 : RTE_ETH_EVENT_INTR_LSC, &bonding_eth_dev->data->port_id,
1918 : : NULL);
1919 : : }
1920 : :
1921 : : return 0;
1922 : : }
1923 : :
1924 : : void
1925 : 0 : member_remove(struct bond_dev_private *internals,
1926 : : struct rte_eth_dev *member_eth_dev)
1927 : : {
1928 : : uint16_t i;
1929 : :
1930 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++)
1931 : 0 : if (internals->members[i].port_id ==
1932 [ # # ]: 0 : member_eth_dev->data->port_id)
1933 : : break;
1934 : :
1935 [ # # ]: 0 : if (i < (internals->member_count - 1)) {
1936 : : struct rte_flow *flow;
1937 : :
1938 : 0 : memmove(&internals->members[i], &internals->members[i + 1],
1939 : : sizeof(internals->members[0]) *
1940 : 0 : (internals->member_count - i - 1));
1941 [ # # ]: 0 : TAILQ_FOREACH(flow, &internals->flow_list, next) {
1942 : 0 : memmove(&flow->flows[i], &flow->flows[i + 1],
1943 : : sizeof(flow->flows[0]) *
1944 : 0 : (internals->member_count - i - 1));
1945 : 0 : flow->flows[internals->member_count - 1] = NULL;
1946 : : }
1947 : : }
1948 : :
1949 : 0 : internals->member_count--;
1950 : :
1951 : : /* force reconfiguration of member interfaces */
1952 : 0 : rte_eth_dev_internal_reset(member_eth_dev);
1953 : 0 : }
1954 : :
1955 : : static void
1956 : : bond_ethdev_member_link_status_change_monitor(void *cb_arg);
1957 : :
1958 : : void
1959 : 0 : member_add(struct bond_dev_private *internals,
1960 : : struct rte_eth_dev *member_eth_dev)
1961 : : {
1962 : : struct bond_member_details *member_details =
1963 : 0 : &internals->members[internals->member_count];
1964 : :
1965 : 0 : member_details->port_id = member_eth_dev->data->port_id;
1966 : 0 : member_details->last_link_status = 0;
1967 : :
1968 : : /* Mark member devices that don't support interrupts so we can
1969 : : * compensate when we start the bond
1970 : : */
1971 [ # # ]: 0 : if (!(member_eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC))
1972 : 0 : member_details->link_status_poll_enabled = 1;
1973 : :
1974 : 0 : member_details->link_status_wait_to_complete = 0;
1975 : : /* clean tlb_last_obytes when adding port for bonding device */
1976 : 0 : memcpy(&member_details->persisted_mac_addr, member_eth_dev->data->mac_addrs,
1977 : : sizeof(struct rte_ether_addr));
1978 : 0 : }
1979 : :
1980 : : void
1981 : 0 : bond_ethdev_primary_set(struct bond_dev_private *internals,
1982 : : uint16_t member_port_id)
1983 : : {
1984 : : int i;
1985 : :
1986 [ # # ]: 0 : if (internals->active_member_count < 1)
1987 : 0 : internals->current_primary_port = member_port_id;
1988 : : else
1989 : : /* Search bonding device member ports for new proposed primary port */
1990 [ # # ]: 0 : for (i = 0; i < internals->active_member_count; i++) {
1991 [ # # ]: 0 : if (internals->active_members[i] == member_port_id)
1992 : 0 : internals->current_primary_port = member_port_id;
1993 : : }
1994 : 0 : }
1995 : :
1996 : : static int
1997 : : bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev);
1998 : :
1999 : : static int
2000 : 0 : bond_ethdev_start(struct rte_eth_dev *eth_dev)
2001 : : {
2002 : : struct bond_dev_private *internals;
2003 : : int i;
2004 : :
2005 : : /* member eth dev will be started by bonding device */
2006 [ # # ]: 0 : if (check_for_bonding_ethdev(eth_dev)) {
2007 : 0 : RTE_BOND_LOG(ERR, "User tried to explicitly start a member eth_dev (%d)",
2008 : : eth_dev->data->port_id);
2009 : 0 : return -1;
2010 : : }
2011 : :
2012 : 0 : eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
2013 : 0 : eth_dev->data->dev_started = 1;
2014 : :
2015 : 0 : internals = eth_dev->data->dev_private;
2016 : :
2017 [ # # ]: 0 : if (internals->member_count == 0) {
2018 : 0 : RTE_BOND_LOG(ERR, "Cannot start port since there are no member devices");
2019 : 0 : goto out_err;
2020 : : }
2021 : :
2022 [ # # ]: 0 : if (internals->user_defined_mac == 0) {
2023 : : struct rte_ether_addr *new_mac_addr = NULL;
2024 : :
2025 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++)
2026 [ # # ]: 0 : if (internals->members[i].port_id == internals->primary_port)
2027 : 0 : new_mac_addr = &internals->members[i].persisted_mac_addr;
2028 : :
2029 [ # # ]: 0 : if (new_mac_addr == NULL)
2030 : 0 : goto out_err;
2031 : :
2032 [ # # ]: 0 : if (mac_address_set(eth_dev, new_mac_addr) != 0) {
2033 : 0 : RTE_BOND_LOG(ERR, "bonding port (%d) failed to update MAC address",
2034 : : eth_dev->data->port_id);
2035 : 0 : goto out_err;
2036 : : }
2037 : : }
2038 : :
2039 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD) {
2040 [ # # ]: 0 : if (internals->mode4.dedicated_queues.enabled == 1) {
2041 : 0 : internals->mode4.dedicated_queues.rx_qid =
2042 : 0 : eth_dev->data->nb_rx_queues;
2043 : 0 : internals->mode4.dedicated_queues.tx_qid =
2044 : 0 : eth_dev->data->nb_tx_queues;
2045 : : }
2046 : : }
2047 : :
2048 : :
2049 : : /* Reconfigure each member device if starting bonding device */
2050 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2051 : 0 : struct rte_eth_dev *member_ethdev =
2052 : 0 : &(rte_eth_devices[internals->members[i].port_id]);
2053 [ # # ]: 0 : if (member_configure(eth_dev, member_ethdev) != 0) {
2054 : 0 : RTE_BOND_LOG(ERR,
2055 : : "bonding port (%d) failed to reconfigure member device (%d)",
2056 : : eth_dev->data->port_id,
2057 : : internals->members[i].port_id);
2058 : 0 : goto out_err;
2059 : : }
2060 [ # # ]: 0 : if (member_start(eth_dev, member_ethdev) != 0) {
2061 : 0 : RTE_BOND_LOG(ERR,
2062 : : "bonding port (%d) failed to start member device (%d)",
2063 : : eth_dev->data->port_id,
2064 : : internals->members[i].port_id);
2065 : 0 : goto out_err;
2066 : : }
2067 : : /* We will need to poll for link status if any member doesn't
2068 : : * support interrupts
2069 : : */
2070 [ # # ]: 0 : if (internals->members[i].link_status_poll_enabled)
2071 : 0 : internals->link_status_polling_enabled = 1;
2072 : : }
2073 : :
2074 : : /* start polling if needed */
2075 [ # # ]: 0 : if (internals->link_status_polling_enabled) {
2076 : 0 : rte_eal_alarm_set(
2077 : 0 : internals->link_status_polling_interval_ms * 1000,
2078 : : bond_ethdev_member_link_status_change_monitor,
2079 : 0 : (void *)&rte_eth_devices[internals->port_id]);
2080 : : }
2081 : :
2082 : : /* Update all member devices MACs*/
2083 [ # # ]: 0 : if (mac_address_members_update(eth_dev) != 0)
2084 : 0 : goto out_err;
2085 : :
2086 [ # # ]: 0 : if (internals->user_defined_primary_port)
2087 : 0 : bond_ethdev_primary_set(internals, internals->primary_port);
2088 : :
2089 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD)
2090 : 0 : bond_mode_8023ad_start(eth_dev);
2091 : :
2092 [ # # ]: 0 : if (internals->mode == BONDING_MODE_TLB ||
2093 : : internals->mode == BONDING_MODE_ALB)
2094 : 0 : bond_tlb_enable(internals);
2095 : :
2096 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
2097 : 0 : eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
2098 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
2099 : 0 : eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
2100 : :
2101 : : return 0;
2102 : :
2103 : 0 : out_err:
2104 : 0 : eth_dev->data->dev_started = 0;
2105 : 0 : return -1;
2106 : : }
2107 : :
2108 : : static void
2109 : 0 : bond_ethdev_free_queues(struct rte_eth_dev *dev)
2110 : : {
2111 : : uint16_t i;
2112 : :
2113 [ # # ]: 0 : if (dev->data->rx_queues != NULL) {
2114 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
2115 : 0 : rte_free(dev->data->rx_queues[i]);
2116 : 0 : dev->data->rx_queues[i] = NULL;
2117 : : }
2118 : 0 : dev->data->nb_rx_queues = 0;
2119 : : }
2120 : :
2121 [ # # ]: 0 : if (dev->data->tx_queues != NULL) {
2122 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
2123 : 0 : rte_free(dev->data->tx_queues[i]);
2124 : 0 : dev->data->tx_queues[i] = NULL;
2125 : : }
2126 : 0 : dev->data->nb_tx_queues = 0;
2127 : : }
2128 : 0 : }
2129 : :
2130 : : int
2131 : 0 : bond_ethdev_stop(struct rte_eth_dev *eth_dev)
2132 : : {
2133 : 0 : struct bond_dev_private *internals = eth_dev->data->dev_private;
2134 : : uint16_t i;
2135 : : int ret;
2136 : :
2137 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD) {
2138 : : struct port *port;
2139 : 0 : void *pkt = NULL;
2140 : :
2141 : 0 : bond_mode_8023ad_stop(eth_dev);
2142 : :
2143 : : /* Discard all messages to/from mode 4 state machines */
2144 [ # # ]: 0 : for (i = 0; i < internals->active_member_count; i++) {
2145 : 0 : port = &bond_mode_8023ad_ports[internals->active_members[i]];
2146 : :
2147 : : RTE_ASSERT(port->rx_ring != NULL);
2148 [ # # # # : 0 : while (rte_ring_dequeue(port->rx_ring, &pkt) != -ENOENT)
# ]
2149 : 0 : rte_pktmbuf_free(pkt);
2150 : :
2151 : : RTE_ASSERT(port->tx_ring != NULL);
2152 [ # # # # : 0 : while (rte_ring_dequeue(port->tx_ring, &pkt) != -ENOENT)
# ]
2153 : 0 : rte_pktmbuf_free(pkt);
2154 : : }
2155 : : }
2156 : :
2157 [ # # ]: 0 : if (internals->mode == BONDING_MODE_TLB ||
2158 : : internals->mode == BONDING_MODE_ALB) {
2159 : 0 : bond_tlb_disable(internals);
2160 [ # # ]: 0 : for (i = 0; i < internals->active_member_count; i++)
2161 : 0 : tlb_last_obytets[internals->active_members[i]] = 0;
2162 : : }
2163 : :
2164 : 0 : eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
2165 : 0 : eth_dev->data->dev_started = 0;
2166 : :
2167 [ # # ]: 0 : if (internals->link_status_polling_enabled) {
2168 : 0 : rte_eal_alarm_cancel(bond_ethdev_member_link_status_change_monitor,
2169 : 0 : (void *)&rte_eth_devices[internals->port_id]);
2170 : : }
2171 : 0 : internals->link_status_polling_enabled = 0;
2172 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2173 : 0 : uint16_t member_id = internals->members[i].port_id;
2174 : :
2175 : 0 : internals->members[i].last_link_status = 0;
2176 : 0 : ret = rte_eth_dev_stop(member_id);
2177 [ # # ]: 0 : if (ret != 0) {
2178 : 0 : RTE_BOND_LOG(ERR, "Failed to stop device on port %u",
2179 : : member_id);
2180 : 0 : return ret;
2181 : : }
2182 : :
2183 : : /* active members need to be deactivated. */
2184 [ # # ]: 0 : if (find_member_by_id(internals->active_members,
2185 : 0 : internals->active_member_count, member_id) !=
2186 : : internals->active_member_count)
2187 : 0 : deactivate_member(eth_dev, member_id);
2188 : : }
2189 : :
2190 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
2191 : 0 : eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2192 [ # # ]: 0 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
2193 : 0 : eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
2194 : :
2195 : : return 0;
2196 : : }
2197 : :
2198 : : static void
2199 : 0 : bond_ethdev_cfg_cleanup(struct rte_eth_dev *dev, bool remove)
2200 : : {
2201 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2202 : 0 : uint16_t bond_port_id = internals->port_id;
2203 : : int skipped = 0;
2204 : : struct rte_flow_error ferror;
2205 : :
2206 : : /* Flush flows in all back-end devices before removing them */
2207 : 0 : bond_flow_ops.flush(dev, &ferror);
2208 : :
2209 [ # # ]: 0 : while (internals->member_count != skipped) {
2210 : 0 : uint16_t port_id = internals->members[skipped].port_id;
2211 : : int ret;
2212 : :
2213 : 0 : ret = rte_eth_dev_stop(port_id);
2214 [ # # ]: 0 : if (ret != 0) {
2215 : 0 : RTE_BOND_LOG(ERR, "Failed to stop device on port %u",
2216 : : port_id);
2217 : : }
2218 : :
2219 [ # # ]: 0 : if (ret != 0 || !remove) {
2220 : 0 : skipped++;
2221 : 0 : continue;
2222 : : }
2223 : :
2224 [ # # ]: 0 : if (rte_eth_bond_member_remove(bond_port_id, port_id) != 0) {
2225 : 0 : RTE_BOND_LOG(ERR,
2226 : : "Failed to remove port %d from bonding device %s",
2227 : : port_id, dev->device->name);
2228 : 0 : skipped++;
2229 : : }
2230 : : }
2231 : 0 : }
2232 : :
2233 : : int
2234 : 0 : bond_ethdev_close(struct rte_eth_dev *dev)
2235 : : {
2236 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2237 : :
2238 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
2239 : : return 0;
2240 : :
2241 : 0 : RTE_BOND_LOG(INFO, "Closing bonding device %s", dev->device->name);
2242 : :
2243 : 0 : bond_ethdev_cfg_cleanup(dev, true);
2244 : :
2245 : 0 : bond_ethdev_free_queues(dev);
2246 : 0 : rte_bitmap_reset(internals->vlan_filter_bmp);
2247 : : rte_bitmap_free(internals->vlan_filter_bmp);
2248 : 0 : rte_free(internals->vlan_filter_bmpmem);
2249 : :
2250 : : /* Try to release mempool used in mode6. If the bond
2251 : : * device is not mode6, free the NULL is not problem.
2252 : : */
2253 : 0 : rte_mempool_free(internals->mode6.mempool);
2254 : :
2255 : 0 : rte_kvargs_free(internals->kvlist);
2256 : :
2257 : 0 : return 0;
2258 : : }
2259 : :
2260 : : /* forward declaration */
2261 : : static int bond_ethdev_configure(struct rte_eth_dev *dev);
2262 : :
2263 : : static int
2264 : 0 : bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
2265 : : {
2266 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2267 : : struct bond_member_details member;
2268 : : int ret;
2269 : :
2270 : : uint16_t max_nb_rx_queues = UINT16_MAX;
2271 : : uint16_t max_nb_tx_queues = UINT16_MAX;
2272 : :
2273 : 0 : dev_info->max_mac_addrs = BOND_MAX_MAC_ADDRS;
2274 : :
2275 : 0 : dev_info->max_rx_pktlen = internals->candidate_max_rx_pktlen ?
2276 [ # # ]: 0 : internals->candidate_max_rx_pktlen :
2277 : : RTE_ETHER_MAX_JUMBO_FRAME_LEN;
2278 : :
2279 : : /* Max number of tx/rx queues that the bonding device can support is the
2280 : : * minimum values of the bonding members, as all members must be capable
2281 : : * of supporting the same number of tx/rx queues.
2282 : : */
2283 [ # # ]: 0 : if (internals->member_count > 0) {
2284 : : struct rte_eth_dev_info member_info;
2285 : : uint16_t idx;
2286 : :
2287 [ # # ]: 0 : for (idx = 0; idx < internals->member_count; idx++) {
2288 : 0 : member = internals->members[idx];
2289 : 0 : ret = rte_eth_dev_info_get(member.port_id, &member_info);
2290 [ # # ]: 0 : if (ret != 0) {
2291 : 0 : RTE_BOND_LOG(ERR,
2292 : : "%s: Error during getting device (port %u) info: %s\n",
2293 : : __func__,
2294 : : member.port_id,
2295 : : strerror(-ret));
2296 : :
2297 : 0 : return ret;
2298 : : }
2299 : :
2300 : 0 : if (member_info.max_rx_queues < max_nb_rx_queues)
2301 : : max_nb_rx_queues = member_info.max_rx_queues;
2302 : :
2303 : 0 : if (member_info.max_tx_queues < max_nb_tx_queues)
2304 : : max_nb_tx_queues = member_info.max_tx_queues;
2305 : : }
2306 : : }
2307 : :
2308 : 0 : dev_info->max_rx_queues = max_nb_rx_queues;
2309 : 0 : dev_info->max_tx_queues = max_nb_tx_queues;
2310 : :
2311 [ # # ]: 0 : memcpy(&dev_info->default_rxconf, &internals->default_rxconf,
2312 : : sizeof(dev_info->default_rxconf));
2313 : 0 : memcpy(&dev_info->default_txconf, &internals->default_txconf,
2314 : : sizeof(dev_info->default_txconf));
2315 : :
2316 : 0 : memcpy(&dev_info->rx_desc_lim, &internals->rx_desc_lim,
2317 : : sizeof(dev_info->rx_desc_lim));
2318 : 0 : memcpy(&dev_info->tx_desc_lim, &internals->tx_desc_lim,
2319 : : sizeof(dev_info->tx_desc_lim));
2320 : :
2321 : : /**
2322 : : * If dedicated hw queues enabled for link bonding device in LACP mode
2323 : : * then we need to reduce the maximum number of data path queues by 1.
2324 : : */
2325 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD &&
2326 [ # # ]: 0 : internals->mode4.dedicated_queues.enabled == 1) {
2327 : 0 : dev_info->max_rx_queues--;
2328 : 0 : dev_info->max_tx_queues--;
2329 : : }
2330 : :
2331 : 0 : dev_info->min_rx_bufsize = 0;
2332 : :
2333 : 0 : dev_info->rx_offload_capa = internals->rx_offload_capa;
2334 : 0 : dev_info->tx_offload_capa = internals->tx_offload_capa;
2335 : 0 : dev_info->rx_queue_offload_capa = internals->rx_queue_offload_capa;
2336 : 0 : dev_info->tx_queue_offload_capa = internals->tx_queue_offload_capa;
2337 : 0 : dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
2338 : :
2339 : 0 : dev_info->reta_size = internals->reta_size;
2340 : 0 : dev_info->hash_key_size = internals->rss_key_len;
2341 : 0 : dev_info->speed_capa = internals->speed_capa;
2342 : :
2343 : 0 : return 0;
2344 : : }
2345 : :
2346 : : static int
2347 : 0 : bond_ethdev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
2348 : : {
2349 : : int res;
2350 : : uint16_t i;
2351 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2352 : :
2353 : : /* don't do this while a member is being added */
2354 : 0 : rte_spinlock_lock(&internals->lock);
2355 : :
2356 [ # # ]: 0 : if (on)
2357 : 0 : rte_bitmap_set(internals->vlan_filter_bmp, vlan_id);
2358 : : else
2359 : 0 : rte_bitmap_clear(internals->vlan_filter_bmp, vlan_id);
2360 : :
2361 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2362 : 0 : uint16_t port_id = internals->members[i].port_id;
2363 : :
2364 : 0 : res = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
2365 [ # # ]: 0 : if (res == ENOTSUP)
2366 : 0 : RTE_BOND_LOG(WARNING,
2367 : : "Setting VLAN filter on member port %u not supported.",
2368 : : port_id);
2369 : : }
2370 : :
2371 : : rte_spinlock_unlock(&internals->lock);
2372 : 0 : return 0;
2373 : : }
2374 : :
2375 : : static int
2376 : 0 : bond_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
2377 : : uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
2378 : : const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool)
2379 : : {
2380 : : struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)
2381 : 0 : rte_zmalloc_socket(NULL, sizeof(struct bond_rx_queue),
2382 : 0 : 0, dev->data->numa_node);
2383 [ # # ]: 0 : if (bd_rx_q == NULL)
2384 : : return -1;
2385 : :
2386 : 0 : bd_rx_q->queue_id = rx_queue_id;
2387 : 0 : bd_rx_q->dev_private = dev->data->dev_private;
2388 : :
2389 : 0 : bd_rx_q->nb_rx_desc = nb_rx_desc;
2390 : :
2391 : 0 : memcpy(&(bd_rx_q->rx_conf), rx_conf, sizeof(struct rte_eth_rxconf));
2392 : 0 : bd_rx_q->mb_pool = mb_pool;
2393 : :
2394 : 0 : dev->data->rx_queues[rx_queue_id] = bd_rx_q;
2395 : :
2396 : 0 : return 0;
2397 : : }
2398 : :
2399 : : static int
2400 : 0 : bond_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
2401 : : uint16_t nb_tx_desc, unsigned int socket_id __rte_unused,
2402 : : const struct rte_eth_txconf *tx_conf)
2403 : : {
2404 : : struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)
2405 : 0 : rte_zmalloc_socket(NULL, sizeof(struct bond_tx_queue),
2406 : 0 : 0, dev->data->numa_node);
2407 : :
2408 [ # # ]: 0 : if (bd_tx_q == NULL)
2409 : : return -1;
2410 : :
2411 : 0 : bd_tx_q->queue_id = tx_queue_id;
2412 : 0 : bd_tx_q->dev_private = dev->data->dev_private;
2413 : :
2414 : 0 : bd_tx_q->nb_tx_desc = nb_tx_desc;
2415 : 0 : memcpy(&(bd_tx_q->tx_conf), tx_conf, sizeof(bd_tx_q->tx_conf));
2416 : :
2417 : 0 : dev->data->tx_queues[tx_queue_id] = bd_tx_q;
2418 : :
2419 : 0 : return 0;
2420 : : }
2421 : :
2422 : : static void
2423 : 0 : bond_ethdev_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id)
2424 : : {
2425 : 0 : void *queue = dev->data->rx_queues[queue_id];
2426 : :
2427 [ # # ]: 0 : if (queue == NULL)
2428 : : return;
2429 : :
2430 : 0 : rte_free(queue);
2431 : : }
2432 : :
2433 : : static void
2434 : 0 : bond_ethdev_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id)
2435 : : {
2436 : 0 : void *queue = dev->data->tx_queues[queue_id];
2437 : :
2438 [ # # ]: 0 : if (queue == NULL)
2439 : : return;
2440 : :
2441 : 0 : rte_free(queue);
2442 : : }
2443 : :
2444 : : static void
2445 : 0 : bond_ethdev_member_link_status_change_monitor(void *cb_arg)
2446 : : {
2447 : : struct rte_eth_dev *bonding_ethdev, *member_ethdev;
2448 : : struct bond_dev_private *internals;
2449 : :
2450 : : /* Default value for polling member found is true as we don't want to
2451 : : * disable the polling thread if we cannot get the lock */
2452 : : int i, polling_member_found = 1;
2453 : :
2454 [ # # ]: 0 : if (cb_arg == NULL)
2455 : : return;
2456 : :
2457 : : bonding_ethdev = cb_arg;
2458 : 0 : internals = bonding_ethdev->data->dev_private;
2459 : :
2460 [ # # ]: 0 : if (!bonding_ethdev->data->dev_started ||
2461 [ # # ]: 0 : !internals->link_status_polling_enabled)
2462 : : return;
2463 : :
2464 : : /* If device is currently being configured then don't check members link
2465 : : * status, wait until next period */
2466 [ # # ]: 0 : if (rte_spinlock_trylock(&internals->lock)) {
2467 [ # # ]: 0 : if (internals->member_count > 0)
2468 : : polling_member_found = 0;
2469 : :
2470 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2471 [ # # ]: 0 : if (!internals->members[i].link_status_poll_enabled)
2472 : 0 : continue;
2473 : :
2474 : 0 : member_ethdev = &rte_eth_devices[internals->members[i].port_id];
2475 : : polling_member_found = 1;
2476 : :
2477 : : /* Update member link status */
2478 : 0 : (*member_ethdev->dev_ops->link_update)(member_ethdev,
2479 : 0 : internals->members[i].link_status_wait_to_complete);
2480 : :
2481 : : /* if link status has changed since last checked then call lsc
2482 : : * event callback */
2483 : 0 : if (member_ethdev->data->dev_link.link_status !=
2484 [ # # ]: 0 : internals->members[i].last_link_status) {
2485 : 0 : bond_ethdev_lsc_event_callback(internals->members[i].port_id,
2486 : : RTE_ETH_EVENT_INTR_LSC,
2487 : 0 : &bonding_ethdev->data->port_id,
2488 : : NULL);
2489 : : }
2490 : : }
2491 : : rte_spinlock_unlock(&internals->lock);
2492 : : }
2493 : :
2494 [ # # ]: 0 : if (polling_member_found)
2495 : : /* Set alarm to continue monitoring link status of member ethdev's */
2496 : 0 : rte_eal_alarm_set(internals->link_status_polling_interval_ms * 1000,
2497 : : bond_ethdev_member_link_status_change_monitor, cb_arg);
2498 : : }
2499 : :
2500 : : static int
2501 : 0 : bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
2502 : : {
2503 : : int (*link_update)(uint16_t port_id, struct rte_eth_link *eth_link);
2504 : :
2505 : : struct bond_dev_private *bond_ctx;
2506 : : struct rte_eth_link member_link;
2507 : :
2508 : : bool one_link_update_succeeded;
2509 : : uint32_t idx;
2510 : : int ret;
2511 : :
2512 : 0 : bond_ctx = ethdev->data->dev_private;
2513 : :
2514 : 0 : ethdev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
2515 : :
2516 [ # # ]: 0 : if (ethdev->data->dev_started == 0 ||
2517 [ # # ]: 0 : bond_ctx->active_member_count == 0) {
2518 : 0 : ethdev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
2519 : 0 : return 0;
2520 : : }
2521 : :
2522 : 0 : ethdev->data->dev_link.link_status = RTE_ETH_LINK_UP;
2523 : :
2524 [ # # ]: 0 : if (wait_to_complete)
2525 : : link_update = rte_eth_link_get;
2526 : : else
2527 : : link_update = rte_eth_link_get_nowait;
2528 : :
2529 [ # # # # ]: 0 : switch (bond_ctx->mode) {
2530 : 0 : case BONDING_MODE_BROADCAST:
2531 : : /**
2532 : : * Setting link speed to UINT32_MAX to ensure we pick up the
2533 : : * value of the first active member
2534 : : */
2535 : 0 : ethdev->data->dev_link.link_speed = UINT32_MAX;
2536 : :
2537 : : /**
2538 : : * link speed is minimum value of all the members link speed as
2539 : : * packet loss will occur on this member if transmission at rates
2540 : : * greater than this are attempted
2541 : : */
2542 [ # # ]: 0 : for (idx = 0; idx < bond_ctx->active_member_count; idx++) {
2543 : 0 : ret = link_update(bond_ctx->active_members[idx],
2544 : : &member_link);
2545 [ # # ]: 0 : if (ret < 0) {
2546 : 0 : ethdev->data->dev_link.link_speed =
2547 : : RTE_ETH_SPEED_NUM_NONE;
2548 : 0 : RTE_BOND_LOG(ERR,
2549 : : "Member (port %u) link get failed: %s",
2550 : : bond_ctx->active_members[idx],
2551 : : rte_strerror(-ret));
2552 : 0 : return 0;
2553 : : }
2554 : :
2555 : 0 : if (member_link.link_speed <
2556 [ # # ]: 0 : ethdev->data->dev_link.link_speed)
2557 : 0 : ethdev->data->dev_link.link_speed =
2558 : : member_link.link_speed;
2559 : : }
2560 : : break;
2561 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2562 : : /* Current primary member */
2563 : 0 : ret = link_update(bond_ctx->current_primary_port, &member_link);
2564 [ # # ]: 0 : if (ret < 0) {
2565 : 0 : RTE_BOND_LOG(ERR, "Member (port %u) link get failed: %s",
2566 : : bond_ctx->current_primary_port,
2567 : : rte_strerror(-ret));
2568 : 0 : return 0;
2569 : : }
2570 : :
2571 : 0 : ethdev->data->dev_link.link_speed = member_link.link_speed;
2572 : 0 : break;
2573 : 0 : case BONDING_MODE_8023AD:
2574 : 0 : ethdev->data->dev_link.link_autoneg =
2575 : 0 : bond_ctx->mode4.member_link.link_autoneg;
2576 : 0 : ethdev->data->dev_link.link_duplex =
2577 : 0 : bond_ctx->mode4.member_link.link_duplex;
2578 : : /* fall through */
2579 : : /* to update link speed */
2580 : : case BONDING_MODE_ROUND_ROBIN:
2581 : : case BONDING_MODE_BALANCE:
2582 : : case BONDING_MODE_TLB:
2583 : : case BONDING_MODE_ALB:
2584 : : default:
2585 : : /**
2586 : : * In theses mode the maximum theoretical link speed is the sum
2587 : : * of all the members
2588 : : */
2589 : : ethdev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
2590 : : one_link_update_succeeded = false;
2591 : :
2592 [ # # ]: 0 : for (idx = 0; idx < bond_ctx->active_member_count; idx++) {
2593 : 0 : ret = link_update(bond_ctx->active_members[idx],
2594 : : &member_link);
2595 [ # # ]: 0 : if (ret < 0) {
2596 : 0 : RTE_BOND_LOG(ERR,
2597 : : "Member (port %u) link get failed: %s",
2598 : : bond_ctx->active_members[idx],
2599 : : rte_strerror(-ret));
2600 : 0 : continue;
2601 : : }
2602 : :
2603 : : one_link_update_succeeded = true;
2604 : 0 : ethdev->data->dev_link.link_speed +=
2605 : 0 : member_link.link_speed;
2606 : : }
2607 : :
2608 [ # # ]: 0 : if (!one_link_update_succeeded) {
2609 : 0 : RTE_BOND_LOG(ERR, "All members link get failed");
2610 : 0 : return 0;
2611 : : }
2612 : : }
2613 : :
2614 : :
2615 : : return 0;
2616 : : }
2617 : :
2618 : :
2619 : : static int
2620 : 0 : bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
2621 : : {
2622 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2623 : : struct rte_eth_stats member_stats;
2624 : : int i, j;
2625 : :
2626 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2627 : 0 : rte_eth_stats_get(internals->members[i].port_id, &member_stats);
2628 : :
2629 : 0 : stats->ipackets += member_stats.ipackets;
2630 : 0 : stats->opackets += member_stats.opackets;
2631 : 0 : stats->ibytes += member_stats.ibytes;
2632 : 0 : stats->obytes += member_stats.obytes;
2633 : 0 : stats->imissed += member_stats.imissed;
2634 : 0 : stats->ierrors += member_stats.ierrors;
2635 : 0 : stats->oerrors += member_stats.oerrors;
2636 : 0 : stats->rx_nombuf += member_stats.rx_nombuf;
2637 : :
2638 [ # # ]: 0 : for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS; j++) {
2639 : 0 : stats->q_ipackets[j] += member_stats.q_ipackets[j];
2640 : 0 : stats->q_opackets[j] += member_stats.q_opackets[j];
2641 : 0 : stats->q_ibytes[j] += member_stats.q_ibytes[j];
2642 : 0 : stats->q_obytes[j] += member_stats.q_obytes[j];
2643 : 0 : stats->q_errors[j] += member_stats.q_errors[j];
2644 : : }
2645 : :
2646 : : }
2647 : :
2648 : 0 : return 0;
2649 : : }
2650 : :
2651 : : static int
2652 : 0 : bond_ethdev_stats_reset(struct rte_eth_dev *dev)
2653 : : {
2654 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2655 : : int i;
2656 : : int err;
2657 : : int ret;
2658 : :
2659 [ # # ]: 0 : for (i = 0, err = 0; i < internals->member_count; i++) {
2660 : 0 : ret = rte_eth_stats_reset(internals->members[i].port_id);
2661 [ # # ]: 0 : if (ret != 0)
2662 : : err = ret;
2663 : : }
2664 : :
2665 : 0 : return err;
2666 : : }
2667 : :
2668 : : static int
2669 : 0 : bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
2670 : : {
2671 : 0 : struct bond_dev_private *internals = eth_dev->data->dev_private;
2672 : : int i;
2673 : : int ret = 0;
2674 : : uint16_t port_id;
2675 : :
2676 [ # # ]: 0 : switch (internals->mode) {
2677 : : /* Promiscuous mode is propagated to all members */
2678 : : case BONDING_MODE_ROUND_ROBIN:
2679 : : case BONDING_MODE_BALANCE:
2680 : : case BONDING_MODE_BROADCAST:
2681 : : case BONDING_MODE_8023AD: {
2682 : : unsigned int member_ok = 0;
2683 : :
2684 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2685 : 0 : port_id = internals->members[i].port_id;
2686 : :
2687 : 0 : ret = rte_eth_promiscuous_enable(port_id);
2688 [ # # ]: 0 : if (ret != 0)
2689 : 0 : RTE_BOND_LOG(ERR,
2690 : : "Failed to enable promiscuous mode for port %u: %s",
2691 : : port_id, rte_strerror(-ret));
2692 : : else
2693 : 0 : member_ok++;
2694 : : }
2695 : : /*
2696 : : * Report success if operation is successful on at least
2697 : : * on one member. Otherwise return last error code.
2698 : : */
2699 [ # # ]: 0 : if (member_ok > 0)
2700 : : ret = 0;
2701 : : break;
2702 : : }
2703 : : /* Promiscuous mode is propagated only to primary member */
2704 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2705 : : case BONDING_MODE_TLB:
2706 : : case BONDING_MODE_ALB:
2707 : : default:
2708 : : /* Do not touch promisc when there cannot be primary ports */
2709 [ # # ]: 0 : if (internals->member_count == 0)
2710 : : break;
2711 : 0 : port_id = internals->current_primary_port;
2712 : 0 : ret = rte_eth_promiscuous_enable(port_id);
2713 [ # # ]: 0 : if (ret != 0)
2714 : 0 : RTE_BOND_LOG(ERR,
2715 : : "Failed to enable promiscuous mode for port %u: %s",
2716 : : port_id, rte_strerror(-ret));
2717 : : }
2718 : :
2719 : 0 : return ret;
2720 : : }
2721 : :
2722 : : static int
2723 : 0 : bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
2724 : : {
2725 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2726 : : int i;
2727 : : int ret = 0;
2728 : : uint16_t port_id;
2729 : :
2730 [ # # ]: 0 : switch (internals->mode) {
2731 : : /* Promiscuous mode is propagated to all members */
2732 : : case BONDING_MODE_ROUND_ROBIN:
2733 : : case BONDING_MODE_BALANCE:
2734 : : case BONDING_MODE_BROADCAST:
2735 : : case BONDING_MODE_8023AD: {
2736 : : unsigned int member_ok = 0;
2737 : :
2738 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2739 : 0 : port_id = internals->members[i].port_id;
2740 : :
2741 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD &&
2742 [ # # ]: 0 : bond_mode_8023ad_ports[port_id].forced_rx_flags ==
2743 : : BOND_8023AD_FORCED_PROMISC) {
2744 : 0 : member_ok++;
2745 : 0 : continue;
2746 : : }
2747 : 0 : ret = rte_eth_promiscuous_disable(port_id);
2748 [ # # ]: 0 : if (ret != 0)
2749 : 0 : RTE_BOND_LOG(ERR,
2750 : : "Failed to disable promiscuous mode for port %u: %s",
2751 : : port_id, rte_strerror(-ret));
2752 : : else
2753 : 0 : member_ok++;
2754 : : }
2755 : : /*
2756 : : * Report success if operation is successful on at least
2757 : : * on one member. Otherwise return last error code.
2758 : : */
2759 [ # # ]: 0 : if (member_ok > 0)
2760 : : ret = 0;
2761 : : break;
2762 : : }
2763 : : /* Promiscuous mode is propagated only to primary member */
2764 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2765 : : case BONDING_MODE_TLB:
2766 : : case BONDING_MODE_ALB:
2767 : : default:
2768 : : /* Do not touch promisc when there cannot be primary ports */
2769 [ # # ]: 0 : if (internals->member_count == 0)
2770 : : break;
2771 : 0 : port_id = internals->current_primary_port;
2772 : 0 : ret = rte_eth_promiscuous_disable(port_id);
2773 [ # # ]: 0 : if (ret != 0)
2774 : 0 : RTE_BOND_LOG(ERR,
2775 : : "Failed to disable promiscuous mode for port %u: %s",
2776 : : port_id, rte_strerror(-ret));
2777 : : }
2778 : :
2779 : 0 : return ret;
2780 : : }
2781 : :
2782 : : static int
2783 : 0 : bond_ethdev_promiscuous_update(struct rte_eth_dev *dev)
2784 : : {
2785 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2786 : 0 : uint16_t port_id = internals->current_primary_port;
2787 : :
2788 [ # # ]: 0 : switch (internals->mode) {
2789 : : case BONDING_MODE_ROUND_ROBIN:
2790 : : case BONDING_MODE_BALANCE:
2791 : : case BONDING_MODE_BROADCAST:
2792 : : case BONDING_MODE_8023AD:
2793 : : /* As promiscuous mode is propagated to all members for these
2794 : : * mode, no need to update for bonding device.
2795 : : */
2796 : : break;
2797 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2798 : : case BONDING_MODE_TLB:
2799 : : case BONDING_MODE_ALB:
2800 : : default:
2801 : : /* As promiscuous mode is propagated only to primary member
2802 : : * for these mode. When active/standby switchover, promiscuous
2803 : : * mode should be set to new primary member according to bonding
2804 : : * device.
2805 : : */
2806 [ # # ]: 0 : if (rte_eth_promiscuous_get(internals->port_id) == 1)
2807 : 0 : rte_eth_promiscuous_enable(port_id);
2808 : : else
2809 : 0 : rte_eth_promiscuous_disable(port_id);
2810 : : }
2811 : :
2812 : 0 : return 0;
2813 : : }
2814 : :
2815 : : static int
2816 : 0 : bond_ethdev_allmulticast_enable(struct rte_eth_dev *eth_dev)
2817 : : {
2818 : 0 : struct bond_dev_private *internals = eth_dev->data->dev_private;
2819 : : int i;
2820 : : int ret = 0;
2821 : : uint16_t port_id;
2822 : :
2823 [ # # ]: 0 : switch (internals->mode) {
2824 : : /* allmulti mode is propagated to all members */
2825 : : case BONDING_MODE_ROUND_ROBIN:
2826 : : case BONDING_MODE_BALANCE:
2827 : : case BONDING_MODE_BROADCAST:
2828 : : case BONDING_MODE_8023AD: {
2829 : : unsigned int member_ok = 0;
2830 : :
2831 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2832 : 0 : port_id = internals->members[i].port_id;
2833 : :
2834 : 0 : ret = rte_eth_allmulticast_enable(port_id);
2835 [ # # ]: 0 : if (ret != 0)
2836 : 0 : RTE_BOND_LOG(ERR,
2837 : : "Failed to enable allmulti mode for port %u: %s",
2838 : : port_id, rte_strerror(-ret));
2839 : : else
2840 : 0 : member_ok++;
2841 : : }
2842 : : /*
2843 : : * Report success if operation is successful on at least
2844 : : * on one member. Otherwise return last error code.
2845 : : */
2846 [ # # ]: 0 : if (member_ok > 0)
2847 : : ret = 0;
2848 : : break;
2849 : : }
2850 : : /* allmulti mode is propagated only to primary member */
2851 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2852 : : case BONDING_MODE_TLB:
2853 : : case BONDING_MODE_ALB:
2854 : : default:
2855 : : /* Do not touch allmulti when there cannot be primary ports */
2856 [ # # ]: 0 : if (internals->member_count == 0)
2857 : : break;
2858 : 0 : port_id = internals->current_primary_port;
2859 : 0 : ret = rte_eth_allmulticast_enable(port_id);
2860 [ # # ]: 0 : if (ret != 0)
2861 : 0 : RTE_BOND_LOG(ERR,
2862 : : "Failed to enable allmulti mode for port %u: %s",
2863 : : port_id, rte_strerror(-ret));
2864 : : }
2865 : :
2866 : 0 : return ret;
2867 : : }
2868 : :
2869 : : static int
2870 : 0 : bond_ethdev_allmulticast_disable(struct rte_eth_dev *eth_dev)
2871 : : {
2872 : 0 : struct bond_dev_private *internals = eth_dev->data->dev_private;
2873 : : int i;
2874 : : int ret = 0;
2875 : : uint16_t port_id;
2876 : :
2877 [ # # ]: 0 : switch (internals->mode) {
2878 : : /* allmulti mode is propagated to all members */
2879 : : case BONDING_MODE_ROUND_ROBIN:
2880 : : case BONDING_MODE_BALANCE:
2881 : : case BONDING_MODE_BROADCAST:
2882 : : case BONDING_MODE_8023AD: {
2883 : : unsigned int member_ok = 0;
2884 : :
2885 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
2886 : 0 : uint16_t port_id = internals->members[i].port_id;
2887 : :
2888 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD &&
2889 [ # # ]: 0 : bond_mode_8023ad_ports[port_id].forced_rx_flags ==
2890 : : BOND_8023AD_FORCED_ALLMULTI)
2891 : 0 : continue;
2892 : :
2893 : 0 : ret = rte_eth_allmulticast_disable(port_id);
2894 [ # # ]: 0 : if (ret != 0)
2895 : 0 : RTE_BOND_LOG(ERR,
2896 : : "Failed to disable allmulti mode for port %u: %s",
2897 : : port_id, rte_strerror(-ret));
2898 : : else
2899 : 0 : member_ok++;
2900 : : }
2901 : : /*
2902 : : * Report success if operation is successful on at least
2903 : : * on one member. Otherwise return last error code.
2904 : : */
2905 [ # # ]: 0 : if (member_ok > 0)
2906 : : ret = 0;
2907 : : break;
2908 : : }
2909 : : /* allmulti mode is propagated only to primary member */
2910 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2911 : : case BONDING_MODE_TLB:
2912 : : case BONDING_MODE_ALB:
2913 : : default:
2914 : : /* Do not touch allmulti when there cannot be primary ports */
2915 [ # # ]: 0 : if (internals->member_count == 0)
2916 : : break;
2917 : 0 : port_id = internals->current_primary_port;
2918 : 0 : ret = rte_eth_allmulticast_disable(port_id);
2919 [ # # ]: 0 : if (ret != 0)
2920 : 0 : RTE_BOND_LOG(ERR,
2921 : : "Failed to disable allmulti mode for port %u: %s",
2922 : : port_id, rte_strerror(-ret));
2923 : : }
2924 : :
2925 : 0 : return ret;
2926 : : }
2927 : :
2928 : : static int
2929 : 0 : bond_ethdev_allmulticast_update(struct rte_eth_dev *dev)
2930 : : {
2931 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
2932 : 0 : uint16_t port_id = internals->current_primary_port;
2933 : :
2934 [ # # ]: 0 : switch (internals->mode) {
2935 : : case BONDING_MODE_ROUND_ROBIN:
2936 : : case BONDING_MODE_BALANCE:
2937 : : case BONDING_MODE_BROADCAST:
2938 : : case BONDING_MODE_8023AD:
2939 : : /* As allmulticast mode is propagated to all members for these
2940 : : * mode, no need to update for bonding device.
2941 : : */
2942 : : break;
2943 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
2944 : : case BONDING_MODE_TLB:
2945 : : case BONDING_MODE_ALB:
2946 : : default:
2947 : : /* As allmulticast mode is propagated only to primary member
2948 : : * for these mode. When active/standby switchover, allmulticast
2949 : : * mode should be set to new primary member according to bonding
2950 : : * device.
2951 : : */
2952 [ # # ]: 0 : if (rte_eth_allmulticast_get(internals->port_id) == 1)
2953 : 0 : rte_eth_allmulticast_enable(port_id);
2954 : : else
2955 : 0 : rte_eth_allmulticast_disable(port_id);
2956 : : }
2957 : :
2958 : 0 : return 0;
2959 : : }
2960 : :
2961 : : static void
2962 : 0 : bond_ethdev_delayed_lsc_propagation(void *arg)
2963 : : {
2964 [ # # ]: 0 : if (arg == NULL)
2965 : : return;
2966 : :
2967 : 0 : rte_eth_dev_callback_process((struct rte_eth_dev *)arg,
2968 : : RTE_ETH_EVENT_INTR_LSC, NULL);
2969 : : }
2970 : :
2971 : : int
2972 : 0 : bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
2973 : : void *param, void *ret_param __rte_unused)
2974 : : {
2975 : : struct rte_eth_dev *bonding_eth_dev;
2976 : : struct bond_dev_private *internals;
2977 : : struct rte_eth_link link;
2978 : : int rc = -1;
2979 : : int ret;
2980 : :
2981 : : uint8_t lsc_flag = 0;
2982 : : int valid_member = 0;
2983 : : uint16_t active_pos, member_idx;
2984 : : uint16_t i;
2985 : :
2986 [ # # ]: 0 : if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)
2987 : : return rc;
2988 : :
2989 : 0 : bonding_eth_dev = &rte_eth_devices[*(uint16_t *)param];
2990 : :
2991 [ # # ]: 0 : if (check_for_bonding_ethdev(bonding_eth_dev))
2992 : : return rc;
2993 : :
2994 : 0 : internals = bonding_eth_dev->data->dev_private;
2995 : :
2996 : : /* If the device isn't started don't handle interrupts */
2997 [ # # ]: 0 : if (!bonding_eth_dev->data->dev_started)
2998 : : return rc;
2999 : :
3000 : : /* verify that port_id is a valid member of bonding port */
3001 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3002 [ # # ]: 0 : if (internals->members[i].port_id == port_id) {
3003 : : valid_member = 1;
3004 : : member_idx = i;
3005 : : break;
3006 : : }
3007 : : }
3008 : :
3009 : : if (!valid_member)
3010 : : return rc;
3011 : :
3012 : : /* Synchronize lsc callback parallel calls either by real link event
3013 : : * from the members PMDs or by the bonding PMD itself.
3014 : : */
3015 : 0 : rte_spinlock_lock(&internals->lsc_lock);
3016 : :
3017 : : /* Search for port in active port list */
3018 : 0 : active_pos = find_member_by_id(internals->active_members,
3019 : 0 : internals->active_member_count, port_id);
3020 : :
3021 : 0 : ret = rte_eth_link_get_nowait(port_id, &link);
3022 [ # # ]: 0 : if (ret < 0)
3023 : 0 : RTE_BOND_LOG(ERR, "Member (port %u) link get failed", port_id);
3024 : :
3025 [ # # # # ]: 0 : if (ret == 0 && link.link_status) {
3026 [ # # ]: 0 : if (active_pos < internals->active_member_count)
3027 : 0 : goto link_update;
3028 : :
3029 : : /* check link state properties if bonding link is up*/
3030 [ # # ]: 0 : if (bonding_eth_dev->data->dev_link.link_status == RTE_ETH_LINK_UP) {
3031 : : if (link_properties_valid(bonding_eth_dev, &link) != 0)
3032 : 0 : RTE_BOND_LOG(ERR, "Invalid link properties "
3033 : : "for member %d in bonding mode %d",
3034 : : port_id, internals->mode);
3035 : : } else {
3036 : : /* inherit member link properties */
3037 : : link_properties_set(bonding_eth_dev, &link);
3038 : : }
3039 : :
3040 : : /* If no active member ports then set this port to be
3041 : : * the primary port.
3042 : : */
3043 [ # # ]: 0 : if (internals->active_member_count < 1) {
3044 : : /* If first active member, then change link status */
3045 : 0 : bonding_eth_dev->data->dev_link.link_status =
3046 : : RTE_ETH_LINK_UP;
3047 : 0 : internals->current_primary_port = port_id;
3048 : : lsc_flag = 1;
3049 : :
3050 : 0 : mac_address_members_update(bonding_eth_dev);
3051 : 0 : bond_ethdev_promiscuous_update(bonding_eth_dev);
3052 : 0 : bond_ethdev_allmulticast_update(bonding_eth_dev);
3053 : : }
3054 : :
3055 : 0 : activate_member(bonding_eth_dev, port_id);
3056 : :
3057 : : /* If the user has defined the primary port then default to
3058 : : * using it.
3059 : : */
3060 [ # # ]: 0 : if (internals->user_defined_primary_port &&
3061 [ # # ]: 0 : internals->primary_port == port_id)
3062 : 0 : bond_ethdev_primary_set(internals, port_id);
3063 : : } else {
3064 [ # # ]: 0 : if (active_pos == internals->active_member_count)
3065 : 0 : goto link_update;
3066 : :
3067 : : /* Remove from active member list */
3068 : 0 : deactivate_member(bonding_eth_dev, port_id);
3069 : :
3070 [ # # ]: 0 : if (internals->active_member_count < 1)
3071 : : lsc_flag = 1;
3072 : :
3073 : : /* Update primary id, take first active member from list or if none
3074 : : * available set to -1 */
3075 [ # # ]: 0 : if (port_id == internals->current_primary_port) {
3076 [ # # ]: 0 : if (internals->active_member_count > 0)
3077 : 0 : bond_ethdev_primary_set(internals,
3078 : 0 : internals->active_members[0]);
3079 : : else
3080 : 0 : internals->current_primary_port = internals->primary_port;
3081 : 0 : mac_address_members_update(bonding_eth_dev);
3082 : 0 : bond_ethdev_promiscuous_update(bonding_eth_dev);
3083 : 0 : bond_ethdev_allmulticast_update(bonding_eth_dev);
3084 : : }
3085 : : }
3086 : :
3087 : 0 : link_update:
3088 : : /**
3089 : : * Update bonding device link properties after any change to active
3090 : : * members
3091 : : */
3092 : 0 : bond_ethdev_link_update(bonding_eth_dev, 0);
3093 : 0 : internals->members[member_idx].last_link_status = link.link_status;
3094 : :
3095 [ # # ]: 0 : if (lsc_flag) {
3096 : : /* Cancel any possible outstanding interrupts if delays are enabled */
3097 [ # # ]: 0 : if (internals->link_up_delay_ms > 0 ||
3098 : : internals->link_down_delay_ms > 0)
3099 : 0 : rte_eal_alarm_cancel(bond_ethdev_delayed_lsc_propagation,
3100 : : bonding_eth_dev);
3101 : :
3102 [ # # ]: 0 : if (bonding_eth_dev->data->dev_link.link_status) {
3103 [ # # ]: 0 : if (internals->link_up_delay_ms > 0)
3104 : 0 : rte_eal_alarm_set(internals->link_up_delay_ms * 1000,
3105 : : bond_ethdev_delayed_lsc_propagation,
3106 : : (void *)bonding_eth_dev);
3107 : : else
3108 : 0 : rte_eth_dev_callback_process(bonding_eth_dev,
3109 : : RTE_ETH_EVENT_INTR_LSC,
3110 : : NULL);
3111 : :
3112 : : } else {
3113 [ # # ]: 0 : if (internals->link_down_delay_ms > 0)
3114 : 0 : rte_eal_alarm_set(internals->link_down_delay_ms * 1000,
3115 : : bond_ethdev_delayed_lsc_propagation,
3116 : : (void *)bonding_eth_dev);
3117 : : else
3118 : 0 : rte_eth_dev_callback_process(bonding_eth_dev,
3119 : : RTE_ETH_EVENT_INTR_LSC,
3120 : : NULL);
3121 : : }
3122 : : }
3123 : :
3124 : : rte_spinlock_unlock(&internals->lsc_lock);
3125 : :
3126 : 0 : return rc;
3127 : : }
3128 : :
3129 : : static int
3130 : 0 : bond_ethdev_rss_reta_update(struct rte_eth_dev *dev,
3131 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
3132 : : {
3133 : : unsigned i, j;
3134 : : int result = 0;
3135 : : int member_reta_size;
3136 : : unsigned reta_count;
3137 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3138 : :
3139 [ # # ]: 0 : if (reta_size != internals->reta_size)
3140 : : return -EINVAL;
3141 : :
3142 : : /* Copy RETA table */
3143 : 0 : reta_count = (reta_size + RTE_ETH_RETA_GROUP_SIZE - 1) /
3144 : : RTE_ETH_RETA_GROUP_SIZE;
3145 : :
3146 [ # # ]: 0 : for (i = 0; i < reta_count; i++) {
3147 : 0 : internals->reta_conf[i].mask = reta_conf[i].mask;
3148 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++)
3149 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
3150 : 0 : internals->reta_conf[i].reta[j] = reta_conf[i].reta[j];
3151 : : }
3152 : :
3153 : : /* Fill rest of array */
3154 [ # # ]: 0 : for (; i < RTE_DIM(internals->reta_conf); i += reta_count)
3155 : 0 : memcpy(&internals->reta_conf[i], &internals->reta_conf[0],
3156 : : sizeof(internals->reta_conf[0]) * reta_count);
3157 : :
3158 : : /* Propagate RETA over members */
3159 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3160 : 0 : member_reta_size = internals->members[i].reta_size;
3161 : 0 : result = rte_eth_dev_rss_reta_update(internals->members[i].port_id,
3162 : : &internals->reta_conf[0], member_reta_size);
3163 [ # # ]: 0 : if (result < 0)
3164 : 0 : return result;
3165 : : }
3166 : :
3167 : : return 0;
3168 : : }
3169 : :
3170 : : static int
3171 : 0 : bond_ethdev_rss_reta_query(struct rte_eth_dev *dev,
3172 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
3173 : : {
3174 : : int i, j;
3175 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3176 : :
3177 [ # # ]: 0 : if (reta_size != internals->reta_size)
3178 : : return -EINVAL;
3179 : :
3180 : : /* Copy RETA table */
3181 [ # # ]: 0 : for (i = 0; i < reta_size / RTE_ETH_RETA_GROUP_SIZE; i++)
3182 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++)
3183 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
3184 : 0 : reta_conf[i].reta[j] = internals->reta_conf[i].reta[j];
3185 : :
3186 : : return 0;
3187 : : }
3188 : :
3189 : : static int
3190 : 0 : bond_ethdev_rss_hash_update(struct rte_eth_dev *dev,
3191 : : struct rte_eth_rss_conf *rss_conf)
3192 : : {
3193 : : int i, result = 0;
3194 [ # # ]: 0 : struct bond_dev_private *internals = dev->data->dev_private;
3195 : : struct rte_eth_rss_conf bond_rss_conf;
3196 : :
3197 : : memcpy(&bond_rss_conf, rss_conf, sizeof(struct rte_eth_rss_conf));
3198 : :
3199 : 0 : bond_rss_conf.rss_hf &= internals->flow_type_rss_offloads;
3200 : :
3201 [ # # ]: 0 : if (bond_rss_conf.rss_hf != 0)
3202 : 0 : dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf = bond_rss_conf.rss_hf;
3203 : :
3204 [ # # ]: 0 : if (bond_rss_conf.rss_key) {
3205 [ # # ]: 0 : if (bond_rss_conf.rss_key_len < internals->rss_key_len)
3206 : : return -EINVAL;
3207 [ # # ]: 0 : else if (bond_rss_conf.rss_key_len > internals->rss_key_len)
3208 : 0 : RTE_BOND_LOG(WARNING, "rss_key will be truncated");
3209 : :
3210 : 0 : memcpy(internals->rss_key, bond_rss_conf.rss_key,
3211 : 0 : internals->rss_key_len);
3212 : 0 : bond_rss_conf.rss_key_len = internals->rss_key_len;
3213 : : }
3214 : :
3215 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3216 : 0 : result = rte_eth_dev_rss_hash_update(internals->members[i].port_id,
3217 : : &bond_rss_conf);
3218 [ # # ]: 0 : if (result < 0)
3219 : 0 : return result;
3220 : : }
3221 : :
3222 : : return 0;
3223 : : }
3224 : :
3225 : : static int
3226 : 0 : bond_ethdev_rss_hash_conf_get(struct rte_eth_dev *dev,
3227 : : struct rte_eth_rss_conf *rss_conf)
3228 : : {
3229 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3230 : :
3231 : 0 : rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
3232 : 0 : rss_conf->rss_key_len = internals->rss_key_len;
3233 [ # # ]: 0 : if (rss_conf->rss_key)
3234 : 0 : memcpy(rss_conf->rss_key, internals->rss_key, internals->rss_key_len);
3235 : :
3236 : 0 : return 0;
3237 : : }
3238 : :
3239 : : static int
3240 : 0 : bond_ethdev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
3241 : : {
3242 : : struct rte_eth_dev *member_eth_dev;
3243 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3244 : : int ret, i;
3245 : :
3246 : 0 : rte_spinlock_lock(&internals->lock);
3247 : :
3248 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3249 : 0 : member_eth_dev = &rte_eth_devices[internals->members[i].port_id];
3250 [ # # ]: 0 : if (*member_eth_dev->dev_ops->mtu_set == NULL) {
3251 : : rte_spinlock_unlock(&internals->lock);
3252 : 0 : return -ENOTSUP;
3253 : : }
3254 : : }
3255 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3256 : 0 : ret = rte_eth_dev_set_mtu(internals->members[i].port_id, mtu);
3257 [ # # ]: 0 : if (ret < 0) {
3258 : : rte_spinlock_unlock(&internals->lock);
3259 : 0 : return ret;
3260 : : }
3261 : : }
3262 : :
3263 : : rte_spinlock_unlock(&internals->lock);
3264 : 0 : return 0;
3265 : : }
3266 : :
3267 : : static int
3268 : 0 : bond_ethdev_mac_address_set(struct rte_eth_dev *dev,
3269 : : struct rte_ether_addr *addr)
3270 : : {
3271 [ # # ]: 0 : if (mac_address_set(dev, addr)) {
3272 : 0 : RTE_BOND_LOG(ERR, "Failed to update MAC address");
3273 : 0 : return -EINVAL;
3274 : : }
3275 : :
3276 : : return 0;
3277 : : }
3278 : :
3279 : : static int
3280 : 0 : bond_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
3281 : : const struct rte_flow_ops **ops)
3282 : : {
3283 : 0 : *ops = &bond_flow_ops;
3284 : 0 : return 0;
3285 : : }
3286 : :
3287 : : static int
3288 : 0 : bond_ethdev_mac_addr_add(struct rte_eth_dev *dev,
3289 : : struct rte_ether_addr *mac_addr,
3290 : : __rte_unused uint32_t index, uint32_t vmdq)
3291 : : {
3292 : : struct rte_eth_dev *member_eth_dev;
3293 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3294 : : int ret, i;
3295 : :
3296 : 0 : rte_spinlock_lock(&internals->lock);
3297 : :
3298 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3299 : 0 : member_eth_dev = &rte_eth_devices[internals->members[i].port_id];
3300 [ # # ]: 0 : if (*member_eth_dev->dev_ops->mac_addr_add == NULL ||
3301 [ # # ]: 0 : *member_eth_dev->dev_ops->mac_addr_remove == NULL) {
3302 : : ret = -ENOTSUP;
3303 : 0 : goto end;
3304 : : }
3305 : : }
3306 : :
3307 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3308 : 0 : ret = rte_eth_dev_mac_addr_add(internals->members[i].port_id,
3309 : : mac_addr, vmdq);
3310 [ # # ]: 0 : if (ret < 0) {
3311 : : /* rollback */
3312 [ # # ]: 0 : for (i--; i >= 0; i--)
3313 : 0 : rte_eth_dev_mac_addr_remove(
3314 : 0 : internals->members[i].port_id, mac_addr);
3315 : 0 : goto end;
3316 : : }
3317 : : }
3318 : :
3319 : : ret = 0;
3320 : 0 : end:
3321 : : rte_spinlock_unlock(&internals->lock);
3322 : 0 : return ret;
3323 : : }
3324 : :
3325 : : static void
3326 : 0 : bond_ethdev_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
3327 : : {
3328 : : struct rte_eth_dev *member_eth_dev;
3329 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3330 : : int i;
3331 : :
3332 : 0 : rte_spinlock_lock(&internals->lock);
3333 : :
3334 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
3335 : 0 : member_eth_dev = &rte_eth_devices[internals->members[i].port_id];
3336 [ # # ]: 0 : if (*member_eth_dev->dev_ops->mac_addr_remove == NULL)
3337 : 0 : goto end;
3338 : : }
3339 : :
3340 : 0 : struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[index];
3341 : :
3342 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++)
3343 : 0 : rte_eth_dev_mac_addr_remove(internals->members[i].port_id,
3344 : : mac_addr);
3345 : :
3346 : 0 : end:
3347 : : rte_spinlock_unlock(&internals->lock);
3348 : 0 : }
3349 : :
3350 : : static const char *
3351 : : bond_mode_name(uint8_t mode)
3352 : : {
3353 [ # # # # : 0 : switch (mode) {
# # # # ]
3354 : : case BONDING_MODE_ROUND_ROBIN:
3355 : : return "ROUND_ROBIN";
3356 : 0 : case BONDING_MODE_ACTIVE_BACKUP:
3357 : 0 : return "ACTIVE_BACKUP";
3358 : 0 : case BONDING_MODE_BALANCE:
3359 : 0 : return "BALANCE";
3360 : 0 : case BONDING_MODE_BROADCAST:
3361 : 0 : return "BROADCAST";
3362 : 0 : case BONDING_MODE_8023AD:
3363 : 0 : return "8023AD";
3364 : 0 : case BONDING_MODE_TLB:
3365 : 0 : return "TLB";
3366 : 0 : case BONDING_MODE_ALB:
3367 : 0 : return "ALB";
3368 : 0 : default:
3369 : 0 : return "Unknown";
3370 : : }
3371 : : }
3372 : :
3373 : : static void
3374 : 0 : dump_basic(const struct rte_eth_dev *dev, FILE *f)
3375 : : {
3376 : : struct bond_dev_private instant_priv;
3377 : : const struct bond_dev_private *internals = &instant_priv;
3378 : : int mode, i;
3379 : :
3380 : : /* Obtain a instance of dev_private to prevent data from being modified. */
3381 : 0 : memcpy(&instant_priv, dev->data->dev_private, sizeof(struct bond_dev_private));
3382 : 0 : mode = internals->mode;
3383 : :
3384 : : fprintf(f, " - Dev basic:\n");
3385 : : fprintf(f, "\tBonding mode: %s(%d)\n", bond_mode_name(mode), mode);
3386 : :
3387 [ # # ]: 0 : if (mode == BONDING_MODE_BALANCE || mode == BONDING_MODE_8023AD) {
3388 : : fprintf(f, "\tBalance Xmit Policy: ");
3389 [ # # # # ]: 0 : switch (internals->balance_xmit_policy) {
3390 : : case BALANCE_XMIT_POLICY_LAYER2:
3391 : : fprintf(f, "BALANCE_XMIT_POLICY_LAYER2");
3392 : : break;
3393 : : case BALANCE_XMIT_POLICY_LAYER23:
3394 : : fprintf(f, "BALANCE_XMIT_POLICY_LAYER23");
3395 : : break;
3396 : : case BALANCE_XMIT_POLICY_LAYER34:
3397 : : fprintf(f, "BALANCE_XMIT_POLICY_LAYER34");
3398 : : break;
3399 : : default:
3400 : : fprintf(f, "Unknown");
3401 : : }
3402 : : fprintf(f, "\n");
3403 : : }
3404 : :
3405 [ # # ]: 0 : if (mode == BONDING_MODE_8023AD) {
3406 : : fprintf(f, "\tIEEE802.3AD Aggregator Mode: ");
3407 [ # # # # ]: 0 : switch (internals->mode4.agg_selection) {
3408 : : case AGG_BANDWIDTH:
3409 : : fprintf(f, "bandwidth");
3410 : : break;
3411 : : case AGG_STABLE:
3412 : : fprintf(f, "stable");
3413 : : break;
3414 : : case AGG_COUNT:
3415 : : fprintf(f, "count");
3416 : : break;
3417 : : default:
3418 : : fprintf(f, "unknown");
3419 : : }
3420 : : fprintf(f, "\n");
3421 : : }
3422 : :
3423 [ # # ]: 0 : if (internals->member_count > 0) {
3424 : 0 : fprintf(f, "\tMembers (%u): [", internals->member_count);
3425 [ # # ]: 0 : for (i = 0; i < internals->member_count - 1; i++)
3426 : 0 : fprintf(f, "%u ", internals->members[i].port_id);
3427 : :
3428 : 0 : fprintf(f, "%u]\n", internals->members[internals->member_count - 1].port_id);
3429 : : } else {
3430 : : fprintf(f, "\tMembers: []\n");
3431 : : }
3432 : :
3433 [ # # ]: 0 : if (internals->active_member_count > 0) {
3434 : 0 : fprintf(f, "\tActive Members (%u): [", internals->active_member_count);
3435 [ # # ]: 0 : for (i = 0; i < internals->active_member_count - 1; i++)
3436 : 0 : fprintf(f, "%u ", internals->active_members[i]);
3437 : :
3438 : 0 : fprintf(f, "%u]\n", internals->active_members[internals->active_member_count - 1]);
3439 : :
3440 : : } else {
3441 : : fprintf(f, "\tActive Members: []\n");
3442 : : }
3443 : :
3444 [ # # ]: 0 : if (internals->user_defined_primary_port)
3445 : 0 : fprintf(f, "\tUser Defined Primary: [%u]\n", internals->primary_port);
3446 [ # # ]: 0 : if (internals->member_count > 0)
3447 : 0 : fprintf(f, "\tCurrent Primary: [%u]\n", internals->current_primary_port);
3448 : 0 : }
3449 : :
3450 : : static void
3451 : 0 : dump_lacp_conf(const struct rte_eth_bond_8023ad_conf *conf, FILE *f)
3452 : : {
3453 : 0 : fprintf(f, "\tfast period: %u ms\n", conf->fast_periodic_ms);
3454 : 0 : fprintf(f, "\tslow period: %u ms\n", conf->slow_periodic_ms);
3455 : 0 : fprintf(f, "\tshort timeout: %u ms\n", conf->short_timeout_ms);
3456 : 0 : fprintf(f, "\tlong timeout: %u ms\n", conf->long_timeout_ms);
3457 : : fprintf(f, "\taggregate wait timeout: %u ms\n",
3458 : 0 : conf->aggregate_wait_timeout_ms);
3459 : 0 : fprintf(f, "\ttx period: %u ms\n", conf->tx_period_ms);
3460 : 0 : fprintf(f, "\trx marker period: %u ms\n", conf->rx_marker_period_ms);
3461 : 0 : fprintf(f, "\tupdate timeout: %u ms\n", conf->update_timeout_ms);
3462 [ # # # # ]: 0 : switch (conf->agg_selection) {
3463 : : case AGG_BANDWIDTH:
3464 : : fprintf(f, "\taggregation mode: bandwidth\n");
3465 : : break;
3466 : : case AGG_STABLE:
3467 : : fprintf(f, "\taggregation mode: stable\n");
3468 : : break;
3469 : : case AGG_COUNT:
3470 : : fprintf(f, "\taggregation mode: count\n");
3471 : : break;
3472 : : default:
3473 : : fprintf(f, "\taggregation mode: invalid\n");
3474 : : break;
3475 : : }
3476 : : fprintf(f, "\n");
3477 : 0 : }
3478 : :
3479 : : static void
3480 : 0 : dump_lacp_port_param(const struct port_params *params, FILE *f)
3481 : : {
3482 : : char buf[RTE_ETHER_ADDR_FMT_SIZE];
3483 : 0 : fprintf(f, "\t\tsystem priority: %u\n", params->system_priority);
3484 : 0 : rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, ¶ms->system);
3485 : : fprintf(f, "\t\tsystem mac address: %s\n", buf);
3486 : 0 : fprintf(f, "\t\tport key: %u\n", params->key);
3487 : 0 : fprintf(f, "\t\tport priority: %u\n", params->port_priority);
3488 : 0 : fprintf(f, "\t\tport number: %u\n", params->port_number);
3489 : 0 : }
3490 : :
3491 : : static void
3492 : 0 : dump_lacp_member(const struct rte_eth_bond_8023ad_member_info *info, FILE *f)
3493 : : {
3494 : 0 : char a_state[256] = { 0 };
3495 : 0 : char p_state[256] = { 0 };
3496 : : int a_len = 0;
3497 : : int p_len = 0;
3498 : : uint32_t i;
3499 : :
3500 : : static const char * const state[] = {
3501 : : "ACTIVE",
3502 : : "TIMEOUT",
3503 : : "AGGREGATION",
3504 : : "SYNCHRONIZATION",
3505 : : "COLLECTING",
3506 : : "DISTRIBUTING",
3507 : : "DEFAULTED",
3508 : : "EXPIRED"
3509 : : };
3510 : : static const char * const selection[] = {
3511 : : "UNSELECTED",
3512 : : "STANDBY",
3513 : : "SELECTED"
3514 : : };
3515 : :
3516 [ # # ]: 0 : for (i = 0; i < RTE_DIM(state); i++) {
3517 [ # # ]: 0 : if ((info->actor_state >> i) & 1)
3518 : 0 : a_len += snprintf(&a_state[a_len],
3519 : : RTE_DIM(a_state) - a_len, "%s ",
3520 : 0 : state[i]);
3521 : :
3522 [ # # ]: 0 : if ((info->partner_state >> i) & 1)
3523 : 0 : p_len += snprintf(&p_state[p_len],
3524 : : RTE_DIM(p_state) - p_len, "%s ",
3525 : 0 : state[i]);
3526 : : }
3527 : 0 : fprintf(f, "\tAggregator port id: %u\n", info->agg_port_id);
3528 : 0 : fprintf(f, "\tselection: %s\n", selection[info->selected]);
3529 : : fprintf(f, "\tActor detail info:\n");
3530 : 0 : dump_lacp_port_param(&info->actor, f);
3531 : : fprintf(f, "\t\tport state: %s\n", a_state);
3532 : : fprintf(f, "\tPartner detail info:\n");
3533 : 0 : dump_lacp_port_param(&info->partner, f);
3534 : : fprintf(f, "\t\tport state: %s\n", p_state);
3535 : : fprintf(f, "\n");
3536 : 0 : }
3537 : :
3538 : : static void
3539 : 0 : dump_lacp(uint16_t port_id, FILE *f)
3540 : : {
3541 : : struct rte_eth_bond_8023ad_member_info member_info;
3542 : : struct rte_eth_bond_8023ad_conf port_conf;
3543 : : uint16_t members[RTE_MAX_ETHPORTS];
3544 : : int num_active_members;
3545 : : int i, ret;
3546 : :
3547 : : fprintf(f, " - Lacp info:\n");
3548 : :
3549 : 0 : num_active_members = rte_eth_bond_active_members_get(port_id, members,
3550 : : RTE_MAX_ETHPORTS);
3551 [ # # ]: 0 : if (num_active_members < 0) {
3552 : : fprintf(f, "\tFailed to get active member list for port %u\n",
3553 : : port_id);
3554 : 0 : return;
3555 : : }
3556 : :
3557 : : fprintf(f, "\tIEEE802.3 port: %u\n", port_id);
3558 : 0 : ret = rte_eth_bond_8023ad_conf_get(port_id, &port_conf);
3559 [ # # ]: 0 : if (ret) {
3560 : : fprintf(f, "\tGet bonding device %u 8023ad config failed\n",
3561 : : port_id);
3562 : 0 : return;
3563 : : }
3564 : 0 : dump_lacp_conf(&port_conf, f);
3565 : :
3566 [ # # ]: 0 : for (i = 0; i < num_active_members; i++) {
3567 : 0 : ret = rte_eth_bond_8023ad_member_info(port_id, members[i],
3568 : : &member_info);
3569 [ # # ]: 0 : if (ret) {
3570 : 0 : fprintf(f, "\tGet member device %u 8023ad info failed\n",
3571 : 0 : members[i]);
3572 : 0 : return;
3573 : : }
3574 : 0 : fprintf(f, "\tMember Port: %u\n", members[i]);
3575 : 0 : dump_lacp_member(&member_info, f);
3576 : : }
3577 : : }
3578 : :
3579 : : static int
3580 : 0 : bond_ethdev_priv_dump(struct rte_eth_dev *dev, FILE *f)
3581 : : {
3582 : 0 : const struct bond_dev_private *internals = dev->data->dev_private;
3583 : :
3584 : 0 : dump_basic(dev, f);
3585 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD)
3586 : 0 : dump_lacp(dev->data->port_id, f);
3587 : :
3588 : 0 : return 0;
3589 : : }
3590 : :
3591 : : const struct eth_dev_ops default_dev_ops = {
3592 : : .dev_start = bond_ethdev_start,
3593 : : .dev_stop = bond_ethdev_stop,
3594 : : .dev_close = bond_ethdev_close,
3595 : : .dev_configure = bond_ethdev_configure,
3596 : : .dev_infos_get = bond_ethdev_info,
3597 : : .vlan_filter_set = bond_ethdev_vlan_filter_set,
3598 : : .rx_queue_setup = bond_ethdev_rx_queue_setup,
3599 : : .tx_queue_setup = bond_ethdev_tx_queue_setup,
3600 : : .rx_queue_release = bond_ethdev_rx_queue_release,
3601 : : .tx_queue_release = bond_ethdev_tx_queue_release,
3602 : : .link_update = bond_ethdev_link_update,
3603 : : .stats_get = bond_ethdev_stats_get,
3604 : : .stats_reset = bond_ethdev_stats_reset,
3605 : : .promiscuous_enable = bond_ethdev_promiscuous_enable,
3606 : : .promiscuous_disable = bond_ethdev_promiscuous_disable,
3607 : : .allmulticast_enable = bond_ethdev_allmulticast_enable,
3608 : : .allmulticast_disable = bond_ethdev_allmulticast_disable,
3609 : : .reta_update = bond_ethdev_rss_reta_update,
3610 : : .reta_query = bond_ethdev_rss_reta_query,
3611 : : .rss_hash_update = bond_ethdev_rss_hash_update,
3612 : : .rss_hash_conf_get = bond_ethdev_rss_hash_conf_get,
3613 : : .mtu_set = bond_ethdev_mtu_set,
3614 : : .mac_addr_set = bond_ethdev_mac_address_set,
3615 : : .mac_addr_add = bond_ethdev_mac_addr_add,
3616 : : .mac_addr_remove = bond_ethdev_mac_addr_remove,
3617 : : .flow_ops_get = bond_flow_ops_get,
3618 : : .eth_dev_priv_dump = bond_ethdev_priv_dump,
3619 : : };
3620 : :
3621 : : static int
3622 [ # # ]: 0 : bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
3623 : : {
3624 : : const char *name = rte_vdev_device_name(dev);
3625 : 0 : int socket_id = dev->device.numa_node;
3626 : : struct bond_dev_private *internals = NULL;
3627 : : struct rte_eth_dev *eth_dev = NULL;
3628 : : uint32_t vlan_filter_bmp_size;
3629 : :
3630 : : /* now do all data allocation - for eth_dev structure, dummy pci driver
3631 : : * and internal (private) data
3632 : : */
3633 : :
3634 : : /* reserve an ethdev entry */
3635 : 0 : eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals));
3636 [ # # ]: 0 : if (eth_dev == NULL) {
3637 : 0 : RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev");
3638 : 0 : goto err;
3639 : : }
3640 : :
3641 : 0 : internals = eth_dev->data->dev_private;
3642 : 0 : eth_dev->data->nb_rx_queues = (uint16_t)1;
3643 : 0 : eth_dev->data->nb_tx_queues = (uint16_t)1;
3644 : :
3645 : : /* Allocate memory for storing MAC addresses */
3646 : 0 : eth_dev->data->mac_addrs = rte_zmalloc_socket(name, RTE_ETHER_ADDR_LEN *
3647 : : BOND_MAX_MAC_ADDRS, 0, socket_id);
3648 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
3649 : 0 : RTE_BOND_LOG(ERR,
3650 : : "Failed to allocate %u bytes needed to store MAC addresses",
3651 : : RTE_ETHER_ADDR_LEN * BOND_MAX_MAC_ADDRS);
3652 : 0 : goto err;
3653 : : }
3654 : :
3655 : 0 : eth_dev->dev_ops = &default_dev_ops;
3656 : 0 : eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC |
3657 : : RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
3658 : :
3659 : : rte_spinlock_init(&internals->lock);
3660 : : rte_spinlock_init(&internals->lsc_lock);
3661 : :
3662 : 0 : internals->port_id = eth_dev->data->port_id;
3663 : 0 : internals->mode = BONDING_MODE_INVALID;
3664 : 0 : internals->current_primary_port = RTE_MAX_ETHPORTS + 1;
3665 : 0 : internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
3666 : 0 : internals->burst_xmit_hash = burst_xmit_l2_hash;
3667 : 0 : internals->user_defined_mac = 0;
3668 : :
3669 : 0 : internals->link_status_polling_enabled = 0;
3670 : :
3671 : 0 : internals->link_status_polling_interval_ms =
3672 : : DEFAULT_POLLING_INTERVAL_10_MS;
3673 : 0 : internals->link_down_delay_ms = 0;
3674 : 0 : internals->link_up_delay_ms = 0;
3675 : :
3676 : 0 : internals->member_count = 0;
3677 : 0 : internals->active_member_count = 0;
3678 : 0 : internals->rx_offload_capa = 0;
3679 : 0 : internals->tx_offload_capa = 0;
3680 : 0 : internals->rx_queue_offload_capa = 0;
3681 : 0 : internals->tx_queue_offload_capa = 0;
3682 : 0 : internals->candidate_max_rx_pktlen = 0;
3683 : 0 : internals->max_rx_pktlen = 0;
3684 : :
3685 : : /* Initially allow to choose any offload type */
3686 : 0 : internals->flow_type_rss_offloads = RTE_ETH_RSS_PROTO_MASK;
3687 : :
3688 : 0 : memset(&internals->default_rxconf, 0,
3689 : : sizeof(internals->default_rxconf));
3690 : 0 : memset(&internals->default_txconf, 0,
3691 : : sizeof(internals->default_txconf));
3692 : :
3693 : 0 : memset(&internals->rx_desc_lim, 0, sizeof(internals->rx_desc_lim));
3694 : 0 : memset(&internals->tx_desc_lim, 0, sizeof(internals->tx_desc_lim));
3695 : :
3696 : : /*
3697 : : * Do not restrict descriptor counts until
3698 : : * the first back-end device gets attached.
3699 : : */
3700 : 0 : internals->rx_desc_lim.nb_max = UINT16_MAX;
3701 : 0 : internals->tx_desc_lim.nb_max = UINT16_MAX;
3702 : 0 : internals->rx_desc_lim.nb_align = 1;
3703 : 0 : internals->tx_desc_lim.nb_align = 1;
3704 : :
3705 : 0 : memset(internals->active_members, 0, sizeof(internals->active_members));
3706 : 0 : memset(internals->members, 0, sizeof(internals->members));
3707 : :
3708 : 0 : TAILQ_INIT(&internals->flow_list);
3709 : 0 : internals->flow_isolated_valid = 0;
3710 : :
3711 : : /* Set mode 4 default configuration */
3712 : 0 : bond_mode_8023ad_setup(eth_dev, NULL);
3713 [ # # ]: 0 : if (bond_ethdev_mode_set(eth_dev, mode)) {
3714 : 0 : RTE_BOND_LOG(ERR, "Failed to set bonding device %u mode to %u",
3715 : : eth_dev->data->port_id, mode);
3716 : 0 : goto err;
3717 : : }
3718 : :
3719 : : vlan_filter_bmp_size =
3720 : : rte_bitmap_get_memory_footprint(RTE_ETHER_MAX_VLAN_ID + 1);
3721 : 0 : internals->vlan_filter_bmpmem = rte_malloc(name, vlan_filter_bmp_size,
3722 : : RTE_CACHE_LINE_SIZE);
3723 [ # # ]: 0 : if (internals->vlan_filter_bmpmem == NULL) {
3724 : 0 : RTE_BOND_LOG(ERR,
3725 : : "Failed to allocate vlan bitmap for bonding device %u",
3726 : : eth_dev->data->port_id);
3727 : 0 : goto err;
3728 : : }
3729 : :
3730 : 0 : internals->vlan_filter_bmp = rte_bitmap_init(RTE_ETHER_MAX_VLAN_ID + 1,
3731 : : internals->vlan_filter_bmpmem, vlan_filter_bmp_size);
3732 [ # # ]: 0 : if (internals->vlan_filter_bmp == NULL) {
3733 : 0 : RTE_BOND_LOG(ERR,
3734 : : "Failed to init vlan bitmap for bonding device %u",
3735 : : eth_dev->data->port_id);
3736 : 0 : rte_free(internals->vlan_filter_bmpmem);
3737 : 0 : goto err;
3738 : : }
3739 : :
3740 : 0 : return eth_dev->data->port_id;
3741 : :
3742 : 0 : err:
3743 : 0 : rte_free(internals);
3744 [ # # ]: 0 : if (eth_dev != NULL)
3745 : 0 : eth_dev->data->dev_private = NULL;
3746 : 0 : rte_eth_dev_release_port(eth_dev);
3747 : 0 : return -1;
3748 : : }
3749 : :
3750 : : static int
3751 : 0 : bond_probe(struct rte_vdev_device *dev)
3752 : : {
3753 : : const char *name;
3754 : : struct bond_dev_private *internals;
3755 : : struct rte_kvargs *kvlist;
3756 : : uint8_t bonding_mode;
3757 : : int arg_count, port_id;
3758 : : int socket_id;
3759 : : uint8_t agg_mode;
3760 : : struct rte_eth_dev *eth_dev;
3761 : :
3762 [ # # ]: 0 : if (!dev)
3763 : : return -EINVAL;
3764 : :
3765 : : name = rte_vdev_device_name(dev);
3766 : 0 : RTE_BOND_LOG(INFO, "Initializing pmd_bond for %s", name);
3767 : :
3768 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
3769 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
3770 [ # # ]: 0 : if (!eth_dev) {
3771 : 0 : RTE_BOND_LOG(ERR, "Failed to probe %s", name);
3772 : 0 : return -1;
3773 : : }
3774 : : /* TODO: request info from primary to set up Rx and Tx */
3775 : 0 : eth_dev->dev_ops = &default_dev_ops;
3776 : 0 : eth_dev->device = &dev->device;
3777 : 0 : rte_eth_dev_probing_finish(eth_dev);
3778 : 0 : return 0;
3779 : : }
3780 : :
3781 : 0 : kvlist = rte_kvargs_parse(rte_vdev_device_args(dev),
3782 : : pmd_bond_init_valid_arguments);
3783 [ # # ]: 0 : if (kvlist == NULL) {
3784 : 0 : RTE_BOND_LOG(ERR, "Invalid args in %s", rte_vdev_device_args(dev));
3785 : 0 : return -1;
3786 : : }
3787 : :
3788 : : /* Parse link bonding mode */
3789 [ # # ]: 0 : if (rte_kvargs_count(kvlist, PMD_BOND_MODE_KVARG) == 1) {
3790 [ # # ]: 0 : if (rte_kvargs_process(kvlist, PMD_BOND_MODE_KVARG,
3791 : : &bond_ethdev_parse_member_mode_kvarg,
3792 : : &bonding_mode) != 0) {
3793 : 0 : RTE_BOND_LOG(ERR, "Invalid mode for bonding device %s",
3794 : : name);
3795 : 0 : goto parse_error;
3796 : : }
3797 : : } else {
3798 : 0 : RTE_BOND_LOG(ERR, "Mode must be specified only once for bonding "
3799 : : "device %s", name);
3800 : 0 : goto parse_error;
3801 : : }
3802 : :
3803 : : /* Parse socket id to create bonding device on */
3804 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_SOCKET_ID_KVARG);
3805 [ # # ]: 0 : if (arg_count == 1) {
3806 [ # # ]: 0 : if (rte_kvargs_process(kvlist, PMD_BOND_SOCKET_ID_KVARG,
3807 : : &bond_ethdev_parse_socket_id_kvarg, &socket_id)
3808 : : != 0) {
3809 : 0 : RTE_BOND_LOG(ERR, "Invalid socket Id specified for "
3810 : : "bonding device %s", name);
3811 : 0 : goto parse_error;
3812 : : }
3813 [ # # ]: 0 : } else if (arg_count > 1) {
3814 : 0 : RTE_BOND_LOG(ERR, "Socket Id can be specified only once for "
3815 : : "bonding device %s", name);
3816 : 0 : goto parse_error;
3817 : : } else {
3818 : 0 : socket_id = rte_socket_id();
3819 : : }
3820 : :
3821 : 0 : dev->device.numa_node = socket_id;
3822 : :
3823 : : /* Create link bonding eth device */
3824 : 0 : port_id = bond_alloc(dev, bonding_mode);
3825 [ # # ]: 0 : if (port_id < 0) {
3826 : 0 : RTE_BOND_LOG(ERR, "Failed to create socket %s in mode %u on "
3827 : : "socket %d.", name, bonding_mode, socket_id);
3828 : 0 : goto parse_error;
3829 : : }
3830 : 0 : internals = rte_eth_devices[port_id].data->dev_private;
3831 : 0 : internals->kvlist = kvlist;
3832 : :
3833 [ # # ]: 0 : if (rte_kvargs_count(kvlist, PMD_BOND_AGG_MODE_KVARG) == 1) {
3834 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
3835 : : PMD_BOND_AGG_MODE_KVARG,
3836 : : &bond_ethdev_parse_member_agg_mode_kvarg,
3837 : : &agg_mode) != 0) {
3838 : 0 : RTE_BOND_LOG(ERR,
3839 : : "Failed to parse agg selection mode for bonding device %s",
3840 : : name);
3841 : 0 : goto parse_error;
3842 : : }
3843 : :
3844 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD)
3845 : 0 : internals->mode4.agg_selection = agg_mode;
3846 : : } else {
3847 : 0 : internals->mode4.agg_selection = AGG_STABLE;
3848 : : }
3849 : :
3850 : 0 : rte_eth_dev_probing_finish(&rte_eth_devices[port_id]);
3851 : 0 : RTE_BOND_LOG(INFO, "Create bonding device %s on port %d in mode %u on "
3852 : : "socket %u.", name, port_id, bonding_mode, socket_id);
3853 : 0 : return 0;
3854 : :
3855 : 0 : parse_error:
3856 : 0 : rte_kvargs_free(kvlist);
3857 : :
3858 : 0 : return -1;
3859 : : }
3860 : :
3861 : : static int
3862 : 0 : bond_remove(struct rte_vdev_device *dev)
3863 : : {
3864 : : struct rte_eth_dev *eth_dev;
3865 : : struct bond_dev_private *internals;
3866 : : const char *name;
3867 : : int ret = 0;
3868 : :
3869 [ # # ]: 0 : if (!dev)
3870 : : return -EINVAL;
3871 : :
3872 : : name = rte_vdev_device_name(dev);
3873 : 0 : RTE_BOND_LOG(INFO, "Uninitializing pmd_bond for %s", name);
3874 : :
3875 : : /* find an ethdev entry */
3876 : 0 : eth_dev = rte_eth_dev_allocated(name);
3877 [ # # ]: 0 : if (eth_dev == NULL)
3878 : : return 0; /* port already released */
3879 : :
3880 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
3881 : 0 : return rte_eth_dev_release_port(eth_dev);
3882 : :
3883 : : RTE_ASSERT(eth_dev->device == &dev->device);
3884 : :
3885 : 0 : internals = eth_dev->data->dev_private;
3886 [ # # ]: 0 : if (internals->member_count != 0)
3887 : : return -EBUSY;
3888 : :
3889 [ # # ]: 0 : if (eth_dev->data->dev_started == 1) {
3890 : 0 : ret = bond_ethdev_stop(eth_dev);
3891 : 0 : bond_ethdev_close(eth_dev);
3892 : : }
3893 : 0 : rte_eth_dev_release_port(eth_dev);
3894 : :
3895 : 0 : return ret;
3896 : : }
3897 : :
3898 : : /* this part will resolve the member portids after all the other pdev and vdev
3899 : : * have been allocated */
3900 : : static int
3901 : 0 : bond_ethdev_configure(struct rte_eth_dev *dev)
3902 : : {
3903 : 0 : const char *name = dev->device->name;
3904 : 0 : struct bond_dev_private *internals = dev->data->dev_private;
3905 : 0 : struct rte_kvargs *kvlist = internals->kvlist;
3906 : : int arg_count;
3907 : 0 : uint16_t port_id = dev - rte_eth_devices;
3908 : : uint32_t link_speeds;
3909 : : uint8_t agg_mode;
3910 : :
3911 : : static const uint8_t default_rss_key[40] = {
3912 : : 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
3913 : : 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
3914 : : 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B,
3915 : : 0xBE, 0xAC, 0x01, 0xFA
3916 : : };
3917 : :
3918 : : unsigned i, j;
3919 : :
3920 : :
3921 : 0 : bond_ethdev_cfg_cleanup(dev, false);
3922 : :
3923 : : /*
3924 : : * If RSS is enabled, fill table with default values and
3925 : : * set key to the value specified in port RSS configuration.
3926 : : * Fall back to default RSS key if the key is not specified
3927 : : */
3928 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) {
3929 : : struct rte_eth_rss_conf *rss_conf =
3930 : : &dev->data->dev_conf.rx_adv_conf.rss_conf;
3931 : :
3932 [ # # ]: 0 : if (internals->rss_key_len == 0) {
3933 : 0 : internals->rss_key_len = sizeof(default_rss_key);
3934 : : }
3935 : :
3936 [ # # ]: 0 : if (rss_conf->rss_key != NULL) {
3937 [ # # ]: 0 : if (internals->rss_key_len > rss_conf->rss_key_len) {
3938 : 0 : RTE_BOND_LOG(ERR, "Invalid rss key length(%u)",
3939 : : rss_conf->rss_key_len);
3940 : 0 : return -EINVAL;
3941 : : }
3942 : :
3943 : 0 : memcpy(internals->rss_key, rss_conf->rss_key,
3944 : : internals->rss_key_len);
3945 : : } else {
3946 [ # # ]: 0 : if (internals->rss_key_len > sizeof(default_rss_key)) {
3947 : : /*
3948 : : * If the rss_key includes standard_rss_key and
3949 : : * extended_hash_key, the rss key length will be
3950 : : * larger than default rss key length, so it should
3951 : : * re-calculate the hash key.
3952 : : */
3953 [ # # ]: 0 : for (i = 0; i < internals->rss_key_len; i++)
3954 : 0 : internals->rss_key[i] = (uint8_t)rte_rand();
3955 : : } else {
3956 : 0 : memcpy(internals->rss_key, default_rss_key,
3957 : : internals->rss_key_len);
3958 : : }
3959 : : }
3960 : :
3961 [ # # ]: 0 : for (i = 0; i < RTE_DIM(internals->reta_conf); i++) {
3962 : 0 : internals->reta_conf[i].mask = ~0LL;
3963 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++)
3964 : 0 : internals->reta_conf[i].reta[j] =
3965 : 0 : (i * RTE_ETH_RETA_GROUP_SIZE + j) %
3966 : 0 : dev->data->nb_rx_queues;
3967 : : }
3968 : : }
3969 : :
3970 : 0 : link_speeds = dev->data->dev_conf.link_speeds;
3971 : : /*
3972 : : * The default value of 'link_speeds' is zero. From its definition,
3973 : : * this value actually means auto-negotiation. But not all PMDs support
3974 : : * auto-negotiation. So ignore the check for the auto-negotiation and
3975 : : * only consider fixed speed to reduce the impact on PMDs.
3976 : : */
3977 [ # # ]: 0 : if (link_speeds & RTE_ETH_LINK_SPEED_FIXED) {
3978 : 0 : if ((link_speeds &
3979 [ # # ]: 0 : (internals->speed_capa & ~RTE_ETH_LINK_SPEED_FIXED)) == 0) {
3980 : 0 : RTE_BOND_LOG(ERR, "the fixed speed is not supported by all member devices.");
3981 : 0 : return -EINVAL;
3982 : : }
3983 : : /*
3984 : : * Two '1' in binary of 'link_speeds': bit0 and a unique
3985 : : * speed bit.
3986 : : */
3987 [ # # ]: 0 : if (__builtin_popcountl(link_speeds) != 2) {
3988 : 0 : RTE_BOND_LOG(ERR, "please set a unique speed.");
3989 : 0 : return -EINVAL;
3990 : : }
3991 : : }
3992 : :
3993 : : /* set the max_rx_pktlen */
3994 : 0 : internals->max_rx_pktlen = internals->candidate_max_rx_pktlen;
3995 : :
3996 : : /*
3997 : : * if no kvlist, it means that this bonding device has been created
3998 : : * through the bonding api.
3999 : : */
4000 [ # # # # ]: 0 : if (!kvlist || internals->kvargs_processing_is_done)
4001 : : return 0;
4002 : :
4003 : 0 : internals->kvargs_processing_is_done = true;
4004 : :
4005 : : /* Parse MAC address for bonding device */
4006 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_MAC_ADDR_KVARG);
4007 [ # # ]: 0 : if (arg_count == 1) {
4008 : : struct rte_ether_addr bond_mac;
4009 : :
4010 [ # # ]: 0 : if (rte_kvargs_process(kvlist, PMD_BOND_MAC_ADDR_KVARG,
4011 : : &bond_ethdev_parse_bond_mac_addr_kvarg, &bond_mac) < 0) {
4012 : 0 : RTE_BOND_LOG(INFO, "Invalid mac address for bonding device %s",
4013 : : name);
4014 : 0 : return -1;
4015 : : }
4016 : :
4017 : : /* Set MAC address */
4018 [ # # ]: 0 : if (rte_eth_bond_mac_address_set(port_id, &bond_mac) != 0) {
4019 : 0 : RTE_BOND_LOG(ERR,
4020 : : "Failed to set mac address on bonding device %s",
4021 : : name);
4022 : 0 : return -1;
4023 : : }
4024 [ # # ]: 0 : } else if (arg_count > 1) {
4025 : 0 : RTE_BOND_LOG(ERR,
4026 : : "MAC address can be specified only once for bonding device %s",
4027 : : name);
4028 : 0 : return -1;
4029 : : }
4030 : :
4031 : : /* Parse/set balance mode transmit policy */
4032 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_XMIT_POLICY_KVARG);
4033 [ # # ]: 0 : if (arg_count == 1) {
4034 : : uint8_t xmit_policy;
4035 : :
4036 [ # # ]: 0 : if (rte_kvargs_process(kvlist, PMD_BOND_XMIT_POLICY_KVARG,
4037 : : &bond_ethdev_parse_balance_xmit_policy_kvarg, &xmit_policy) !=
4038 : : 0) {
4039 : 0 : RTE_BOND_LOG(INFO,
4040 : : "Invalid xmit policy specified for bonding device %s",
4041 : : name);
4042 : 0 : return -1;
4043 : : }
4044 : :
4045 : : /* Set balance mode transmit policy*/
4046 [ # # ]: 0 : if (rte_eth_bond_xmit_policy_set(port_id, xmit_policy) != 0) {
4047 : 0 : RTE_BOND_LOG(ERR,
4048 : : "Failed to set balance xmit policy on bonding device %s",
4049 : : name);
4050 : 0 : return -1;
4051 : : }
4052 [ # # ]: 0 : } else if (arg_count > 1) {
4053 : 0 : RTE_BOND_LOG(ERR,
4054 : : "Transmit policy can be specified only once for bonding device %s",
4055 : : name);
4056 : 0 : return -1;
4057 : : }
4058 : :
4059 [ # # ]: 0 : if (rte_kvargs_count(kvlist, PMD_BOND_AGG_MODE_KVARG) == 1) {
4060 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
4061 : : PMD_BOND_AGG_MODE_KVARG,
4062 : : &bond_ethdev_parse_member_agg_mode_kvarg,
4063 : : &agg_mode) != 0) {
4064 : 0 : RTE_BOND_LOG(ERR,
4065 : : "Failed to parse agg selection mode for bonding device %s",
4066 : : name);
4067 : : }
4068 [ # # ]: 0 : if (internals->mode == BONDING_MODE_8023AD) {
4069 : 0 : int ret = rte_eth_bond_8023ad_agg_selection_set(port_id,
4070 : : agg_mode);
4071 [ # # ]: 0 : if (ret < 0) {
4072 : 0 : RTE_BOND_LOG(ERR,
4073 : : "Invalid args for agg selection set for bonding device %s",
4074 : : name);
4075 : 0 : return -1;
4076 : : }
4077 : : }
4078 : : }
4079 : :
4080 : : /* Parse/add member ports to bonding device */
4081 [ # # ]: 0 : if (rte_kvargs_count(kvlist, PMD_BOND_MEMBER_PORT_KVARG) > 0) {
4082 : : struct bond_ethdev_member_ports member_ports;
4083 : : unsigned i;
4084 : :
4085 : : memset(&member_ports, 0, sizeof(member_ports));
4086 : :
4087 [ # # ]: 0 : if (rte_kvargs_process(kvlist, PMD_BOND_MEMBER_PORT_KVARG,
4088 : : &bond_ethdev_parse_member_port_kvarg, &member_ports) != 0) {
4089 : 0 : RTE_BOND_LOG(ERR,
4090 : : "Failed to parse member ports for bonding device %s",
4091 : : name);
4092 : 0 : return -1;
4093 : : }
4094 : :
4095 [ # # ]: 0 : for (i = 0; i < member_ports.member_count; i++) {
4096 [ # # ]: 0 : if (rte_eth_bond_member_add(port_id, member_ports.members[i]) != 0) {
4097 : 0 : RTE_BOND_LOG(ERR,
4098 : : "Failed to add port %d as member to bonding device %s",
4099 : : member_ports.members[i], name);
4100 : : }
4101 : : }
4102 : :
4103 : : } else {
4104 : 0 : RTE_BOND_LOG(INFO, "No members specified for bonding device %s", name);
4105 : 0 : return -1;
4106 : : }
4107 : :
4108 : : /* Parse/set primary member port id*/
4109 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_PRIMARY_MEMBER_KVARG);
4110 [ # # ]: 0 : if (arg_count == 1) {
4111 : : uint16_t primary_member_port_id;
4112 : :
4113 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
4114 : : PMD_BOND_PRIMARY_MEMBER_KVARG,
4115 : : &bond_ethdev_parse_primary_member_port_id_kvarg,
4116 : : &primary_member_port_id) < 0) {
4117 : 0 : RTE_BOND_LOG(INFO,
4118 : : "Invalid primary member port id specified for bonding device %s",
4119 : : name);
4120 : 0 : return -1;
4121 : : }
4122 : :
4123 : : /* Set balance mode transmit policy*/
4124 [ # # ]: 0 : if (rte_eth_bond_primary_set(port_id, primary_member_port_id)
4125 : : != 0) {
4126 : 0 : RTE_BOND_LOG(ERR,
4127 : : "Failed to set primary member port %d on bonding device %s",
4128 : : primary_member_port_id, name);
4129 : 0 : return -1;
4130 : : }
4131 [ # # ]: 0 : } else if (arg_count > 1) {
4132 : 0 : RTE_BOND_LOG(INFO,
4133 : : "Primary member can be specified only once for bonding device %s",
4134 : : name);
4135 : 0 : return -1;
4136 : : }
4137 : :
4138 : : /* Parse link status monitor polling interval */
4139 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_LSC_POLL_PERIOD_KVARG);
4140 [ # # ]: 0 : if (arg_count == 1) {
4141 : : uint32_t lsc_poll_interval_ms;
4142 : :
4143 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
4144 : : PMD_BOND_LSC_POLL_PERIOD_KVARG,
4145 : : &bond_ethdev_parse_time_ms_kvarg,
4146 : : &lsc_poll_interval_ms) < 0) {
4147 : 0 : RTE_BOND_LOG(INFO,
4148 : : "Invalid lsc polling interval value specified for bonding"
4149 : : " device %s", name);
4150 : 0 : return -1;
4151 : : }
4152 : :
4153 [ # # ]: 0 : if (rte_eth_bond_link_monitoring_set(port_id, lsc_poll_interval_ms)
4154 : : != 0) {
4155 : 0 : RTE_BOND_LOG(ERR,
4156 : : "Failed to set lsc monitor polling interval (%u ms) on bonding device %s",
4157 : : lsc_poll_interval_ms, name);
4158 : 0 : return -1;
4159 : : }
4160 [ # # ]: 0 : } else if (arg_count > 1) {
4161 : 0 : RTE_BOND_LOG(INFO,
4162 : : "LSC polling interval can be specified only once for bonding"
4163 : : " device %s", name);
4164 : 0 : return -1;
4165 : : }
4166 : :
4167 : : /* Parse link up interrupt propagation delay */
4168 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_UP_PROP_DELAY_KVARG);
4169 [ # # ]: 0 : if (arg_count == 1) {
4170 : : uint32_t link_up_delay_ms;
4171 : :
4172 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
4173 : : PMD_BOND_LINK_UP_PROP_DELAY_KVARG,
4174 : : &bond_ethdev_parse_time_ms_kvarg,
4175 : : &link_up_delay_ms) < 0) {
4176 : 0 : RTE_BOND_LOG(INFO,
4177 : : "Invalid link up propagation delay value specified for"
4178 : : " bonding device %s", name);
4179 : 0 : return -1;
4180 : : }
4181 : :
4182 : : /* Set balance mode transmit policy*/
4183 [ # # ]: 0 : if (rte_eth_bond_link_up_prop_delay_set(port_id, link_up_delay_ms)
4184 : : != 0) {
4185 : 0 : RTE_BOND_LOG(ERR,
4186 : : "Failed to set link up propagation delay (%u ms) on bonding"
4187 : : " device %s", link_up_delay_ms, name);
4188 : 0 : return -1;
4189 : : }
4190 [ # # ]: 0 : } else if (arg_count > 1) {
4191 : 0 : RTE_BOND_LOG(INFO,
4192 : : "Link up propagation delay can be specified only once for"
4193 : : " bonding device %s", name);
4194 : 0 : return -1;
4195 : : }
4196 : :
4197 : : /* Parse link down interrupt propagation delay */
4198 : 0 : arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG);
4199 [ # # ]: 0 : if (arg_count == 1) {
4200 : : uint32_t link_down_delay_ms;
4201 : :
4202 [ # # ]: 0 : if (rte_kvargs_process(kvlist,
4203 : : PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG,
4204 : : &bond_ethdev_parse_time_ms_kvarg,
4205 : : &link_down_delay_ms) < 0) {
4206 : 0 : RTE_BOND_LOG(INFO,
4207 : : "Invalid link down propagation delay value specified for"
4208 : : " bonding device %s", name);
4209 : 0 : return -1;
4210 : : }
4211 : :
4212 : : /* Set balance mode transmit policy*/
4213 [ # # ]: 0 : if (rte_eth_bond_link_down_prop_delay_set(port_id, link_down_delay_ms)
4214 : : != 0) {
4215 : 0 : RTE_BOND_LOG(ERR,
4216 : : "Failed to set link down propagation delay (%u ms) on bonding device %s",
4217 : : link_down_delay_ms, name);
4218 : 0 : return -1;
4219 : : }
4220 [ # # ]: 0 : } else if (arg_count > 1) {
4221 : 0 : RTE_BOND_LOG(INFO,
4222 : : "Link down propagation delay can be specified only once for bonding device %s",
4223 : : name);
4224 : 0 : return -1;
4225 : : }
4226 : :
4227 : : /* configure members so we can pass mtu setting */
4228 [ # # ]: 0 : for (i = 0; i < internals->member_count; i++) {
4229 : 0 : struct rte_eth_dev *member_ethdev =
4230 : 0 : &(rte_eth_devices[internals->members[i].port_id]);
4231 [ # # ]: 0 : if (member_configure(dev, member_ethdev) != 0) {
4232 : 0 : RTE_BOND_LOG(ERR,
4233 : : "bonding port (%d) failed to configure member device (%d)",
4234 : : dev->data->port_id,
4235 : : internals->members[i].port_id);
4236 : 0 : return -1;
4237 : : }
4238 : : }
4239 : : return 0;
4240 : : }
4241 : :
4242 : : struct rte_vdev_driver pmd_bond_drv = {
4243 : : .probe = bond_probe,
4244 : : .remove = bond_remove,
4245 : : };
4246 : :
4247 : 235 : RTE_PMD_REGISTER_VDEV(net_bonding, pmd_bond_drv);
4248 : : RTE_PMD_REGISTER_ALIAS(net_bonding, eth_bond);
4249 : :
4250 : : RTE_PMD_REGISTER_PARAM_STRING(net_bonding,
4251 : : "member=<ifc> "
4252 : : "primary=<ifc> "
4253 : : "mode=[0-6] "
4254 : : "xmit_policy=[l2 | l23 | l34] "
4255 : : "agg_mode=[count | stable | bandwidth] "
4256 : : "socket_id=<int> "
4257 : : "mac=<mac addr> "
4258 : : "lsc_poll_period_ms=<int> "
4259 : : "up_delay=<int> "
4260 : : "down_delay=<int>");
4261 : :
4262 : : /* We can't use RTE_LOG_REGISTER_DEFAULT because of the forced name for
4263 : : * this library, see meson.build.
4264 : : */
4265 [ - + ]: 235 : RTE_LOG_REGISTER(bond_logtype, pmd.net.bonding, NOTICE);
|