]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/drivers/net/bonding/rte_eth_bond_8023ad.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / drivers / net / bonding / rte_eth_bond_8023ad.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
7c673cae
FG
3 */
4
5#include <stddef.h>
6#include <string.h>
7#include <stdbool.h>
8
9#include <rte_alarm.h>
10#include <rte_malloc.h>
11#include <rte_errno.h>
12#include <rte_cycles.h>
13#include <rte_compat.h>
14
15#include "rte_eth_bond_private.h"
16
17static void bond_mode_8023ad_ext_periodic_cb(void *arg);
7c673cae 18#ifdef RTE_LIBRTE_BOND_DEBUG_8023AD
11fdf7f2
TL
19
20#define MODE4_DEBUG(fmt, ...) \
21 rte_log(RTE_LOG_DEBUG, bond_logtype, \
22 "%6u [Port %u: %s] " fmt, \
23 bond_dbg_get_time_diff_ms(), slave_id, \
24 __func__, ##__VA_ARGS__)
7c673cae
FG
25
26static uint64_t start_time;
27
28static unsigned
29bond_dbg_get_time_diff_ms(void)
30{
31 uint64_t now;
32
33 now = rte_rdtsc();
34 if (start_time == 0)
35 start_time = now;
36
37 return ((now - start_time) * 1000) / rte_get_tsc_hz();
38}
39
40static void
41bond_print_lacp(struct lacpdu *l)
42{
43 char a_address[18];
44 char p_address[18];
45 char a_state[256] = { 0 };
46 char p_state[256] = { 0 };
47
48 static const char * const state_labels[] = {
49 "ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST", "DEF", "EXP"
50 };
51
52 int a_len = 0;
53 int p_len = 0;
54 uint8_t i;
55 uint8_t *addr;
56
57 addr = l->actor.port_params.system.addr_bytes;
58 snprintf(a_address, sizeof(a_address), "%02X:%02X:%02X:%02X:%02X:%02X",
59 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
60
61 addr = l->partner.port_params.system.addr_bytes;
62 snprintf(p_address, sizeof(p_address), "%02X:%02X:%02X:%02X:%02X:%02X",
63 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
64
65 for (i = 0; i < 8; i++) {
66 if ((l->actor.state >> i) & 1) {
67 a_len += snprintf(&a_state[a_len], RTE_DIM(a_state) - a_len, "%s ",
68 state_labels[i]);
69 }
70
71 if ((l->partner.state >> i) & 1) {
72 p_len += snprintf(&p_state[p_len], RTE_DIM(p_state) - p_len, "%s ",
73 state_labels[i]);
74 }
75 }
76
77 if (a_len && a_state[a_len-1] == ' ')
78 a_state[a_len-1] = '\0';
79
80 if (p_len && p_state[p_len-1] == ' ')
81 p_state[p_len-1] = '\0';
82
11fdf7f2
TL
83 RTE_BOND_LOG(DEBUG,
84 "LACP: {\n"
85 " subtype= %02X\n"
86 " ver_num=%02X\n"
87 " actor={ tlv=%02X, len=%02X\n"
88 " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"
89 " state={ %s }\n"
90 " }\n"
91 " partner={ tlv=%02X, len=%02X\n"
92 " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"
93 " state={ %s }\n"
94 " }\n"
95 " collector={info=%02X, length=%02X, max_delay=%04X\n, "
96 "type_term=%02X, terminator_length = %02X }",
97 l->subtype,
98 l->version_number,
99 l->actor.tlv_type_info,
100 l->actor.info_length,
101 l->actor.port_params.system_priority,
102 a_address,
103 l->actor.port_params.key,
104 l->actor.port_params.port_priority,
105 l->actor.port_params.port_number,
106 a_state,
107 l->partner.tlv_type_info,
108 l->partner.info_length,
109 l->partner.port_params.system_priority,
110 p_address,
111 l->partner.port_params.key,
112 l->partner.port_params.port_priority,
113 l->partner.port_params.port_number,
114 p_state,
115 l->tlv_type_collector_info,
116 l->collector_info_length,
117 l->collector_max_delay,
118 l->tlv_type_terminator,
119 l->terminator_length);
7c673cae
FG
120
121}
11fdf7f2 122
7c673cae
FG
123#define BOND_PRINT_LACP(lacpdu) bond_print_lacp(lacpdu)
124#else
125#define BOND_PRINT_LACP(lacpdu) do { } while (0)
126#define MODE4_DEBUG(fmt, ...) do { } while (0)
127#endif
128
129static const struct ether_addr lacp_mac_addr = {
130 .addr_bytes = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
131};
132
9f95a23c 133struct port bond_mode_8023ad_ports[RTE_MAX_ETHPORTS];
7c673cae
FG
134
135static void
136timer_cancel(uint64_t *timer)
137{
138 *timer = 0;
139}
140
141static void
142timer_set(uint64_t *timer, uint64_t timeout)
143{
144 *timer = rte_rdtsc() + timeout;
145}
146
147/* Forces given timer to be in expired state. */
148static void
149timer_force_expired(uint64_t *timer)
150{
151 *timer = rte_rdtsc();
152}
153
154static bool
155timer_is_stopped(uint64_t *timer)
156{
157 return *timer == 0;
158}
159
160static bool
161timer_is_expired(uint64_t *timer)
162{
163 return *timer < rte_rdtsc();
164}
165
166/* Timer is in running state if it is not stopped nor expired */
167static bool
168timer_is_running(uint64_t *timer)
169{
170 return !timer_is_stopped(timer) && !timer_is_expired(timer);
171}
172
173static void
174set_warning_flags(struct port *port, uint16_t flags)
175{
176 int retval;
177 uint16_t old;
178 uint16_t new_flag = 0;
179
180 do {
181 old = port->warnings_to_show;
182 new_flag = old | flags;
183 retval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag);
184 } while (unlikely(retval == 0));
185}
186
187static void
11fdf7f2 188show_warnings(uint16_t slave_id)
7c673cae 189{
9f95a23c 190 struct port *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
191 uint8_t warnings;
192
193 do {
194 warnings = port->warnings_to_show;
195 } while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0);
196
197 if (!warnings)
198 return;
199
200 if (!timer_is_expired(&port->warning_timer))
201 return;
202
203
204 timer_set(&port->warning_timer, BOND_8023AD_WARNINGS_PERIOD_MS *
205 rte_get_tsc_hz() / 1000);
206
207 if (warnings & WRN_RX_QUEUE_FULL) {
11fdf7f2
TL
208 RTE_BOND_LOG(DEBUG,
209 "Slave %u: failed to enqueue LACP packet into RX ring.\n"
210 "Receive and transmit functions must be invoked on bonded"
211 "interface at least 10 times per second or LACP will notwork correctly",
212 slave_id);
7c673cae
FG
213 }
214
215 if (warnings & WRN_TX_QUEUE_FULL) {
11fdf7f2
TL
216 RTE_BOND_LOG(DEBUG,
217 "Slave %u: failed to enqueue LACP packet into TX ring.\n"
218 "Receive and transmit functions must be invoked on bonded"
219 "interface at least 10 times per second or LACP will not work correctly",
220 slave_id);
7c673cae
FG
221 }
222
223 if (warnings & WRN_RX_MARKER_TO_FAST)
11fdf7f2
TL
224 RTE_BOND_LOG(INFO, "Slave %u: marker to early - ignoring.",
225 slave_id);
7c673cae
FG
226
227 if (warnings & WRN_UNKNOWN_SLOW_TYPE) {
11fdf7f2
TL
228 RTE_BOND_LOG(INFO,
229 "Slave %u: ignoring unknown slow protocol frame type",
230 slave_id);
7c673cae
FG
231 }
232
233 if (warnings & WRN_UNKNOWN_MARKER_TYPE)
11fdf7f2
TL
234 RTE_BOND_LOG(INFO, "Slave %u: ignoring unknown marker type",
235 slave_id);
7c673cae
FG
236
237 if (warnings & WRN_NOT_LACP_CAPABLE)
238 MODE4_DEBUG("Port %u is not LACP capable!\n", slave_id);
239}
240
241static void
242record_default(struct port *port)
243{
244 /* Record default parameters for partner. Partner admin parameters
245 * are not implemented so set them to arbitrary default (last known) and
246 * mark actor that parner is in defaulted state. */
247 port->partner_state = STATE_LACP_ACTIVE;
248 ACTOR_STATE_SET(port, DEFAULTED);
249}
250
251/** Function handles rx state machine.
252 *
253 * This function implements Receive State Machine from point 5.4.12 in
254 * 802.1AX documentation. It should be called periodically.
255 *
256 * @param lacpdu LACPDU received.
257 * @param port Port on which LACPDU was received.
258 */
259static void
11fdf7f2 260rx_machine(struct bond_dev_private *internals, uint16_t slave_id,
7c673cae
FG
261 struct lacpdu *lacp)
262{
9f95a23c 263 struct port *agg, *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
264 uint64_t timeout;
265
266 if (SM_FLAG(port, BEGIN)) {
267 /* Initialize stuff */
268 MODE4_DEBUG("-> INITIALIZE\n");
269 SM_FLAG_CLR(port, MOVED);
270 port->selected = UNSELECTED;
271
272 record_default(port);
273
274 ACTOR_STATE_CLR(port, EXPIRED);
275 timer_cancel(&port->current_while_timer);
276
277 /* DISABLED: On initialization partner is out of sync */
278 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
279
280 /* LACP DISABLED stuff if LACP not enabled on this port */
281 if (!SM_FLAG(port, LACP_ENABLED))
282 PARTNER_STATE_CLR(port, AGGREGATION);
283 else
284 PARTNER_STATE_SET(port, AGGREGATION);
285 }
286
287 if (!SM_FLAG(port, LACP_ENABLED)) {
288 /* Update parameters only if state changed */
289 if (!timer_is_stopped(&port->current_while_timer)) {
290 port->selected = UNSELECTED;
291 record_default(port);
292 PARTNER_STATE_CLR(port, AGGREGATION);
293 ACTOR_STATE_CLR(port, EXPIRED);
294 timer_cancel(&port->current_while_timer);
295 }
296 return;
297 }
298
299 if (lacp) {
300 MODE4_DEBUG("LACP -> CURRENT\n");
301 BOND_PRINT_LACP(lacp);
302 /* Update selected flag. If partner parameters are defaulted assume they
303 * are match. If not defaulted compare LACP actor with ports parner
304 * params. */
305 if (!ACTOR_STATE(port, DEFAULTED) &&
306 (ACTOR_STATE(port, AGGREGATION) != PARTNER_STATE(port, AGGREGATION)
307 || memcmp(&port->partner, &lacp->actor.port_params,
308 sizeof(port->partner)) != 0)) {
309 MODE4_DEBUG("selected <- UNSELECTED\n");
310 port->selected = UNSELECTED;
311 }
312
313 /* Record this PDU actor params as partner params */
314 memcpy(&port->partner, &lacp->actor.port_params,
315 sizeof(struct port_params));
316 port->partner_state = lacp->actor.state;
317
318 /* Partner parameters are not defaulted any more */
319 ACTOR_STATE_CLR(port, DEFAULTED);
320
321 /* If LACP partner params match this port actor params */
9f95a23c 322 agg = &bond_mode_8023ad_ports[port->aggregator_port_id];
7c673cae
FG
323 bool match = port->actor.system_priority ==
324 lacp->partner.port_params.system_priority &&
325 is_same_ether_addr(&agg->actor.system,
326 &lacp->partner.port_params.system) &&
327 port->actor.port_priority ==
328 lacp->partner.port_params.port_priority &&
329 port->actor.port_number ==
330 lacp->partner.port_params.port_number;
331
332 /* Update NTT if partners information are outdated (xored and masked
333 * bits are set)*/
334 uint8_t state_mask = STATE_LACP_ACTIVE | STATE_LACP_SHORT_TIMEOUT |
335 STATE_SYNCHRONIZATION | STATE_AGGREGATION;
336
337 if (((port->actor_state ^ lacp->partner.state) & state_mask) ||
338 match == false) {
339 SM_FLAG_SET(port, NTT);
340 }
341
342 /* If LACP partner params match this port actor params */
343 if (match == true && ACTOR_STATE(port, AGGREGATION) ==
344 PARTNER_STATE(port, AGGREGATION))
345 PARTNER_STATE_SET(port, SYNCHRONIZATION);
346 else if (!PARTNER_STATE(port, AGGREGATION) && ACTOR_STATE(port,
347 AGGREGATION))
348 PARTNER_STATE_SET(port, SYNCHRONIZATION);
349 else
350 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
351
352 if (ACTOR_STATE(port, LACP_SHORT_TIMEOUT))
353 timeout = internals->mode4.short_timeout;
354 else
355 timeout = internals->mode4.long_timeout;
356
357 timer_set(&port->current_while_timer, timeout);
358 ACTOR_STATE_CLR(port, EXPIRED);
359 return; /* No state change */
360 }
361
362 /* If CURRENT state timer is not running (stopped or expired)
363 * transit to EXPIRED state from DISABLED or CURRENT */
364 if (!timer_is_running(&port->current_while_timer)) {
365 ACTOR_STATE_SET(port, EXPIRED);
366 PARTNER_STATE_CLR(port, SYNCHRONIZATION);
367 PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);
368 timer_set(&port->current_while_timer, internals->mode4.short_timeout);
369 }
370}
371
372/**
373 * Function handles periodic tx state machine.
374 *
375 * Function implements Periodic Transmission state machine from point 5.4.13
376 * in 802.1AX documentation. It should be called periodically.
377 *
378 * @param port Port to handle state machine.
379 */
380static void
11fdf7f2 381periodic_machine(struct bond_dev_private *internals, uint16_t slave_id)
7c673cae 382{
9f95a23c 383 struct port *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
384 /* Calculate if either site is LACP enabled */
385 uint64_t timeout;
386 uint8_t active = ACTOR_STATE(port, LACP_ACTIVE) ||
387 PARTNER_STATE(port, LACP_ACTIVE);
388
389 uint8_t is_partner_fast, was_partner_fast;
390 /* No periodic is on BEGIN, LACP DISABLE or when both sides are pasive */
391 if (SM_FLAG(port, BEGIN) || !SM_FLAG(port, LACP_ENABLED) || !active) {
392 timer_cancel(&port->periodic_timer);
393 timer_force_expired(&port->tx_machine_timer);
394 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
395
396 MODE4_DEBUG("-> NO_PERIODIC ( %s%s%s)\n",
397 SM_FLAG(port, BEGIN) ? "begind " : "",
398 SM_FLAG(port, LACP_ENABLED) ? "" : "LACP disabled ",
399 active ? "LACP active " : "LACP pasive ");
400 return;
401 }
402
403 is_partner_fast = PARTNER_STATE(port, LACP_SHORT_TIMEOUT);
404 was_partner_fast = SM_FLAG(port, PARTNER_SHORT_TIMEOUT);
405
406 /* If periodic timer is not started, transit from NO PERIODIC to FAST/SLOW.
407 * Other case: check if timer expire or partners settings changed. */
408 if (!timer_is_stopped(&port->periodic_timer)) {
409 if (timer_is_expired(&port->periodic_timer)) {
410 SM_FLAG_SET(port, NTT);
411 } else if (is_partner_fast != was_partner_fast) {
412 /* Partners timeout was slow and now it is fast -> send LACP.
413 * In other case (was fast and now it is slow) just switch
414 * timeout to slow without forcing send of LACP (because standard
415 * say so)*/
11fdf7f2 416 if (is_partner_fast)
7c673cae
FG
417 SM_FLAG_SET(port, NTT);
418 } else
419 return; /* Nothing changed */
420 }
421
422 /* Handle state transition to FAST/SLOW LACP timeout */
423 if (is_partner_fast) {
424 timeout = internals->mode4.fast_periodic_timeout;
425 SM_FLAG_SET(port, PARTNER_SHORT_TIMEOUT);
426 } else {
427 timeout = internals->mode4.slow_periodic_timeout;
428 SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT);
429 }
430
431 timer_set(&port->periodic_timer, timeout);
432}
433
434/**
435 * Function handles mux state machine.
436 *
437 * Function implements Mux Machine from point 5.4.15 in 802.1AX documentation.
438 * It should be called periodically.
439 *
440 * @param port Port to handle state machine.
441 */
442static void
11fdf7f2 443mux_machine(struct bond_dev_private *internals, uint16_t slave_id)
7c673cae 444{
9f95a23c 445 struct port *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
446
447 /* Save current state for later use */
448 const uint8_t state_mask = STATE_SYNCHRONIZATION | STATE_DISTRIBUTING |
449 STATE_COLLECTING;
450
451 /* Enter DETACHED state on BEGIN condition or from any other state if
452 * port was unselected */
453 if (SM_FLAG(port, BEGIN) ||
454 port->selected == UNSELECTED || (port->selected == STANDBY &&
455 (port->actor_state & state_mask) != 0)) {
456 /* detach mux from aggregator */
457 port->actor_state &= ~state_mask;
458 /* Set ntt to true if BEGIN condition or transition from any other state
459 * which is indicated that wait_while_timer was started */
460 if (SM_FLAG(port, BEGIN) ||
461 !timer_is_stopped(&port->wait_while_timer)) {
462 SM_FLAG_SET(port, NTT);
463 MODE4_DEBUG("-> DETACHED\n");
464 }
465 timer_cancel(&port->wait_while_timer);
466 }
467
468 if (timer_is_stopped(&port->wait_while_timer)) {
469 if (port->selected == SELECTED || port->selected == STANDBY) {
470 timer_set(&port->wait_while_timer,
471 internals->mode4.aggregate_wait_timeout);
472
473 MODE4_DEBUG("DETACHED -> WAITING\n");
474 }
475 /* Waiting state entered */
476 return;
477 }
478
479 /* Transit next state if port is ready */
480 if (!timer_is_expired(&port->wait_while_timer))
481 return;
482
483 if ((ACTOR_STATE(port, DISTRIBUTING) || ACTOR_STATE(port, COLLECTING)) &&
484 !PARTNER_STATE(port, SYNCHRONIZATION)) {
485 /* If in COLLECTING or DISTRIBUTING state and partner becomes out of
486 * sync transit to ATACHED state. */
487 ACTOR_STATE_CLR(port, DISTRIBUTING);
488 ACTOR_STATE_CLR(port, COLLECTING);
489 /* Clear actor sync to activate transit ATACHED in condition bellow */
490 ACTOR_STATE_CLR(port, SYNCHRONIZATION);
491 MODE4_DEBUG("Out of sync -> ATTACHED\n");
492 }
493
494 if (!ACTOR_STATE(port, SYNCHRONIZATION)) {
495 /* attach mux to aggregator */
496 RTE_ASSERT((port->actor_state & (STATE_COLLECTING |
497 STATE_DISTRIBUTING)) == 0);
498
499 ACTOR_STATE_SET(port, SYNCHRONIZATION);
500 SM_FLAG_SET(port, NTT);
501 MODE4_DEBUG("ATTACHED Entered\n");
502 } else if (!ACTOR_STATE(port, COLLECTING)) {
503 /* Start collecting if in sync */
504 if (PARTNER_STATE(port, SYNCHRONIZATION)) {
505 MODE4_DEBUG("ATTACHED -> COLLECTING\n");
506 ACTOR_STATE_SET(port, COLLECTING);
507 SM_FLAG_SET(port, NTT);
508 }
509 } else if (ACTOR_STATE(port, COLLECTING)) {
510 /* Check if partner is in COLLECTING state. If so this port can
511 * distribute frames to it */
512 if (!ACTOR_STATE(port, DISTRIBUTING)) {
513 if (PARTNER_STATE(port, COLLECTING)) {
514 /* Enable DISTRIBUTING if partner is collecting */
515 ACTOR_STATE_SET(port, DISTRIBUTING);
516 SM_FLAG_SET(port, NTT);
517 MODE4_DEBUG("COLLECTING -> DISTRIBUTING\n");
11fdf7f2
TL
518 RTE_BOND_LOG(INFO,
519 "Bond %u: slave id %u distributing started.",
7c673cae
FG
520 internals->port_id, slave_id);
521 }
522 } else {
523 if (!PARTNER_STATE(port, COLLECTING)) {
524 /* Disable DISTRIBUTING (enter COLLECTING state) if partner
525 * is not collecting */
526 ACTOR_STATE_CLR(port, DISTRIBUTING);
527 SM_FLAG_SET(port, NTT);
528 MODE4_DEBUG("DISTRIBUTING -> COLLECTING\n");
11fdf7f2
TL
529 RTE_BOND_LOG(INFO,
530 "Bond %u: slave id %u distributing stopped.",
7c673cae
FG
531 internals->port_id, slave_id);
532 }
533 }
534 }
535}
536
537/**
538 * Function handles transmit state machine.
539 *
540 * Function implements Transmit Machine from point 5.4.16 in 802.1AX
541 * documentation.
542 *
543 * @param port
544 */
545static void
11fdf7f2 546tx_machine(struct bond_dev_private *internals, uint16_t slave_id)
7c673cae 547{
9f95a23c 548 struct port *agg, *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
549
550 struct rte_mbuf *lacp_pkt = NULL;
551 struct lacpdu_header *hdr;
552 struct lacpdu *lacpdu;
553
554 /* If periodic timer is not running periodic machine is in NO PERIODIC and
555 * according to 802.3ax standard tx machine should not transmit any frames
556 * and set ntt to false. */
557 if (timer_is_stopped(&port->periodic_timer))
558 SM_FLAG_CLR(port, NTT);
559
560 if (!SM_FLAG(port, NTT))
561 return;
562
563 if (!timer_is_expired(&port->tx_machine_timer))
564 return;
565
566 lacp_pkt = rte_pktmbuf_alloc(port->mbuf_pool);
567 if (lacp_pkt == NULL) {
11fdf7f2 568 RTE_BOND_LOG(ERR, "Failed to allocate LACP packet from pool");
7c673cae
FG
569 return;
570 }
571
572 lacp_pkt->data_len = sizeof(*hdr);
573 lacp_pkt->pkt_len = sizeof(*hdr);
574
575 hdr = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
576
577 /* Source and destination MAC */
578 ether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.d_addr);
579 rte_eth_macaddr_get(slave_id, &hdr->eth_hdr.s_addr);
580 hdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW);
581
582 lacpdu = &hdr->lacpdu;
583 memset(lacpdu, 0, sizeof(*lacpdu));
584
585 /* Initialize LACP part */
586 lacpdu->subtype = SLOW_SUBTYPE_LACP;
587 lacpdu->version_number = 1;
588
589 /* ACTOR */
590 lacpdu->actor.tlv_type_info = TLV_TYPE_ACTOR_INFORMATION;
591 lacpdu->actor.info_length = sizeof(struct lacpdu_actor_partner_params);
592 memcpy(&hdr->lacpdu.actor.port_params, &port->actor,
593 sizeof(port->actor));
9f95a23c 594 agg = &bond_mode_8023ad_ports[port->aggregator_port_id];
7c673cae
FG
595 ether_addr_copy(&agg->actor.system, &hdr->lacpdu.actor.port_params.system);
596 lacpdu->actor.state = port->actor_state;
597
598 /* PARTNER */
599 lacpdu->partner.tlv_type_info = TLV_TYPE_PARTNER_INFORMATION;
600 lacpdu->partner.info_length = sizeof(struct lacpdu_actor_partner_params);
601 memcpy(&lacpdu->partner.port_params, &port->partner,
602 sizeof(struct port_params));
603 lacpdu->partner.state = port->partner_state;
604
605 /* Other fields */
606 lacpdu->tlv_type_collector_info = TLV_TYPE_COLLECTOR_INFORMATION;
607 lacpdu->collector_info_length = 0x10;
608 lacpdu->collector_max_delay = 0;
609
610 lacpdu->tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;
611 lacpdu->terminator_length = 0;
612
11fdf7f2
TL
613 MODE4_DEBUG("Sending LACP frame\n");
614 BOND_PRINT_LACP(lacpdu);
615
616 if (internals->mode4.dedicated_queues.enabled == 0) {
617 int retval = rte_ring_enqueue(port->tx_ring, lacp_pkt);
618 if (retval != 0) {
619 /* If TX ring full, drop packet and free message.
620 Retransmission will happen in next function call. */
621 rte_pktmbuf_free(lacp_pkt);
622 set_warning_flags(port, WRN_TX_QUEUE_FULL);
623 return;
624 }
625 } else {
626 uint16_t pkts_sent = rte_eth_tx_burst(slave_id,
627 internals->mode4.dedicated_queues.tx_qid,
628 &lacp_pkt, 1);
629 if (pkts_sent != 1) {
630 rte_pktmbuf_free(lacp_pkt);
631 set_warning_flags(port, WRN_TX_QUEUE_FULL);
632 return;
633 }
7c673cae
FG
634 }
635
7c673cae
FG
636
637 timer_set(&port->tx_machine_timer, internals->mode4.tx_period_timeout);
638 SM_FLAG_CLR(port, NTT);
639}
640
11fdf7f2
TL
641static uint8_t
642max_index(uint64_t *a, int n)
643{
644 if (n <= 0)
645 return -1;
646
647 int i, max_i = 0;
648 uint64_t max = a[0];
649
650 for (i = 1; i < n; ++i) {
651 if (a[i] > max) {
652 max = a[i];
653 max_i = i;
654 }
655 }
656
657 return max_i;
658}
659
7c673cae
FG
660/**
661 * Function assigns port to aggregator.
662 *
663 * @param bond_dev_private Pointer to bond_dev_private structure.
664 * @param port_pos Port to assign.
665 */
666static void
9f95a23c 667selection_logic(struct bond_dev_private *internals, uint16_t slave_id)
7c673cae
FG
668{
669 struct port *agg, *port;
11fdf7f2
TL
670 uint16_t slaves_count, new_agg_id, i, j = 0;
671 uint16_t *slaves;
672 uint64_t agg_bandwidth[8] = {0};
673 uint64_t agg_count[8] = {0};
674 uint16_t default_slave = 0;
675 uint8_t mode_count_id, mode_band_id;
676 struct rte_eth_link link_info;
7c673cae
FG
677
678 slaves = internals->active_slaves;
679 slaves_count = internals->active_slave_count;
9f95a23c 680 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
681
682 /* Search for aggregator suitable for this port */
683 for (i = 0; i < slaves_count; ++i) {
9f95a23c 684 agg = &bond_mode_8023ad_ports[slaves[i]];
7c673cae
FG
685 /* Skip ports that are not aggreagators */
686 if (agg->aggregator_port_id != slaves[i])
687 continue;
688
11fdf7f2
TL
689 agg_count[agg->aggregator_port_id] += 1;
690 rte_eth_link_get_nowait(slaves[i], &link_info);
691 agg_bandwidth[agg->aggregator_port_id] += link_info.link_speed;
692
7c673cae
FG
693 /* Actors system ID is not checked since all slave device have the same
694 * ID (MAC address). */
695 if ((agg->actor.key == port->actor.key &&
696 agg->partner.system_priority == port->partner.system_priority &&
697 is_same_ether_addr(&agg->partner.system, &port->partner.system) == 1
698 && (agg->partner.key == port->partner.key)) &&
699 is_zero_ether_addr(&port->partner.system) != 1 &&
700 (agg->actor.key &
701 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) != 0) {
702
11fdf7f2
TL
703 if (j == 0)
704 default_slave = i;
705 j++;
7c673cae
FG
706 }
707 }
708
11fdf7f2
TL
709 switch (internals->mode4.agg_selection) {
710 case AGG_COUNT:
711 mode_count_id = max_index(
712 (uint64_t *)agg_count, slaves_count);
713 new_agg_id = mode_count_id;
714 break;
715 case AGG_BANDWIDTH:
716 mode_band_id = max_index(
717 (uint64_t *)agg_bandwidth, slaves_count);
718 new_agg_id = mode_band_id;
719 break;
720 case AGG_STABLE:
721 if (default_slave == slaves_count)
722 new_agg_id = slave_id;
723 else
724 new_agg_id = slaves[default_slave];
725 break;
726 default:
727 if (default_slave == slaves_count)
728 new_agg_id = slave_id;
729 else
730 new_agg_id = slaves[default_slave];
731 break;
732 }
7c673cae
FG
733
734 if (new_agg_id != port->aggregator_port_id) {
735 port->aggregator_port_id = new_agg_id;
736
737 MODE4_DEBUG("-> SELECTED: ID=%3u\n"
738 "\t%s aggregator ID=%3u\n",
739 port->aggregator_port_id,
740 port->aggregator_port_id == slave_id ?
741 "aggregator not found, using default" : "aggregator found",
742 port->aggregator_port_id);
743 }
744
745 port->selected = SELECTED;
746}
747
748/* Function maps DPDK speed to bonding speed stored in key field */
749static uint16_t
750link_speed_key(uint16_t speed) {
751 uint16_t key_speed;
752
753 switch (speed) {
754 case ETH_SPEED_NUM_NONE:
755 key_speed = 0x00;
756 break;
757 case ETH_SPEED_NUM_10M:
758 key_speed = BOND_LINK_SPEED_KEY_10M;
759 break;
760 case ETH_SPEED_NUM_100M:
761 key_speed = BOND_LINK_SPEED_KEY_100M;
762 break;
763 case ETH_SPEED_NUM_1G:
764 key_speed = BOND_LINK_SPEED_KEY_1000M;
765 break;
766 case ETH_SPEED_NUM_10G:
767 key_speed = BOND_LINK_SPEED_KEY_10G;
768 break;
769 case ETH_SPEED_NUM_20G:
770 key_speed = BOND_LINK_SPEED_KEY_20G;
771 break;
772 case ETH_SPEED_NUM_40G:
773 key_speed = BOND_LINK_SPEED_KEY_40G;
774 break;
775 default:
776 /* Unknown speed*/
777 key_speed = 0xFFFF;
778 }
779
780 return key_speed;
781}
782
11fdf7f2 783static void
9f95a23c 784rx_machine_update(struct bond_dev_private *internals, uint16_t slave_id,
11fdf7f2
TL
785 struct rte_mbuf *lacp_pkt) {
786 struct lacpdu_header *lacp;
9f95a23c 787 struct lacpdu_actor_partner_params *partner;
11fdf7f2
TL
788
789 if (lacp_pkt != NULL) {
790 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
791 RTE_ASSERT(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
792
9f95a23c
TL
793 partner = &lacp->lacpdu.partner;
794 if (is_same_ether_addr(&partner->port_params.system,
795 &internals->mode4.mac_addr)) {
796 /* This LACP frame is sending to the bonding port
797 * so pass it to rx_machine.
798 */
799 rx_machine(internals, slave_id, &lacp->lacpdu);
800 }
11fdf7f2
TL
801 rte_pktmbuf_free(lacp_pkt);
802 } else
803 rx_machine(internals, slave_id, NULL);
804}
805
7c673cae
FG
806static void
807bond_mode_8023ad_periodic_cb(void *arg)
808{
809 struct rte_eth_dev *bond_dev = arg;
810 struct bond_dev_private *internals = bond_dev->data->dev_private;
811 struct port *port;
812 struct rte_eth_link link_info;
813 struct ether_addr slave_addr;
11fdf7f2 814 struct rte_mbuf *lacp_pkt = NULL;
9f95a23c
TL
815 uint16_t slave_id;
816 uint16_t i;
7c673cae
FG
817
818
819 /* Update link status on each port */
820 for (i = 0; i < internals->active_slave_count; i++) {
821 uint16_t key;
822
823 slave_id = internals->active_slaves[i];
11fdf7f2 824 rte_eth_link_get_nowait(slave_id, &link_info);
7c673cae
FG
825 rte_eth_macaddr_get(slave_id, &slave_addr);
826
827 if (link_info.link_status != 0) {
828 key = link_speed_key(link_info.link_speed) << 1;
829 if (link_info.link_duplex == ETH_LINK_FULL_DUPLEX)
830 key |= BOND_LINK_FULL_DUPLEX_KEY;
831 } else
832 key = 0;
833
9f95a23c 834 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
835
836 key = rte_cpu_to_be_16(key);
837 if (key != port->actor.key) {
838 if (!(key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)))
839 set_warning_flags(port, WRN_NOT_LACP_CAPABLE);
840
841 port->actor.key = key;
842 SM_FLAG_SET(port, NTT);
843 }
844
845 if (!is_same_ether_addr(&port->actor.system, &slave_addr)) {
846 ether_addr_copy(&slave_addr, &port->actor.system);
847 if (port->aggregator_port_id == slave_id)
848 SM_FLAG_SET(port, NTT);
849 }
850 }
851
852 for (i = 0; i < internals->active_slave_count; i++) {
853 slave_id = internals->active_slaves[i];
9f95a23c 854 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
855
856 if ((port->actor.key &
857 rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) == 0) {
858
859 SM_FLAG_SET(port, BEGIN);
860
861 /* LACP is disabled on half duples or link is down */
862 if (SM_FLAG(port, LACP_ENABLED)) {
863 /* If port was enabled set it to BEGIN state */
864 SM_FLAG_CLR(port, LACP_ENABLED);
865 ACTOR_STATE_CLR(port, DISTRIBUTING);
866 ACTOR_STATE_CLR(port, COLLECTING);
867 }
868
869 /* Skip this port processing */
870 continue;
871 }
872
873 SM_FLAG_SET(port, LACP_ENABLED);
874
11fdf7f2
TL
875 if (internals->mode4.dedicated_queues.enabled == 0) {
876 /* Find LACP packet to this port. Do not check subtype,
877 * it is done in function that queued packet
878 */
879 int retval = rte_ring_dequeue(port->rx_ring,
880 (void **)&lacp_pkt);
7c673cae 881
11fdf7f2
TL
882 if (retval != 0)
883 lacp_pkt = NULL;
7c673cae 884
11fdf7f2
TL
885 rx_machine_update(internals, slave_id, lacp_pkt);
886 } else {
887 uint16_t rx_count = rte_eth_rx_burst(slave_id,
888 internals->mode4.dedicated_queues.rx_qid,
889 &lacp_pkt, 1);
890
891 if (rx_count == 1)
892 bond_mode_8023ad_handle_slow_pkt(internals,
893 slave_id, lacp_pkt);
894 else
895 rx_machine_update(internals, slave_id, NULL);
896 }
7c673cae
FG
897
898 periodic_machine(internals, slave_id);
899 mux_machine(internals, slave_id);
900 tx_machine(internals, slave_id);
901 selection_logic(internals, slave_id);
902
903 SM_FLAG_CLR(port, BEGIN);
904 show_warnings(slave_id);
905 }
906
907 rte_eal_alarm_set(internals->mode4.update_timeout_us,
908 bond_mode_8023ad_periodic_cb, arg);
909}
910
911void
11fdf7f2
TL
912bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev,
913 uint16_t slave_id)
7c673cae
FG
914{
915 struct bond_dev_private *internals = bond_dev->data->dev_private;
916
9f95a23c 917 struct port *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
918 struct port_params initial = {
919 .system = { { 0 } },
920 .system_priority = rte_cpu_to_be_16(0xFFFF),
921 .key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY),
922 .port_priority = rte_cpu_to_be_16(0x00FF),
923 .port_number = 0,
924 };
925
926 char mem_name[RTE_ETH_NAME_MAX_LEN];
927 int socket_id;
928 unsigned element_size;
929 uint32_t total_tx_desc;
930 struct bond_tx_queue *bd_tx_q;
931 uint16_t q_id;
932
933 /* Given slave mus not be in active list */
934 RTE_ASSERT(find_slave_by_id(internals->active_slaves,
935 internals->active_slave_count, slave_id) == internals->active_slave_count);
936 RTE_SET_USED(internals); /* used only for assert when enabled */
937
938 memcpy(&port->actor, &initial, sizeof(struct port_params));
939 /* Standard requires that port ID must be grater than 0.
940 * Add 1 do get corresponding port_number */
11fdf7f2 941 port->actor.port_number = rte_cpu_to_be_16(slave_id + 1);
7c673cae
FG
942
943 memcpy(&port->partner, &initial, sizeof(struct port_params));
944
945 /* default states */
946 port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;
11fdf7f2 947 port->partner_state = STATE_LACP_ACTIVE | STATE_AGGREGATION;
7c673cae
FG
948 port->sm_flags = SM_FLAGS_BEGIN;
949
950 /* use this port as agregator */
951 port->aggregator_port_id = slave_id;
952 rte_eth_promiscuous_enable(slave_id);
953
954 timer_cancel(&port->warning_timer);
955
956 if (port->mbuf_pool != NULL)
957 return;
958
959 RTE_ASSERT(port->rx_ring == NULL);
960 RTE_ASSERT(port->tx_ring == NULL);
7c673cae 961
11fdf7f2
TL
962 socket_id = rte_eth_dev_socket_id(slave_id);
963 if (socket_id == (int)LCORE_ID_ANY)
964 socket_id = rte_socket_id();
965
966 element_size = sizeof(struct slow_protocol_frame) +
967 RTE_PKTMBUF_HEADROOM;
7c673cae
FG
968
969 /* The size of the mempool should be at least:
970 * the sum of the TX descriptors + BOND_MODE_8023AX_SLAVE_TX_PKTS */
971 total_tx_desc = BOND_MODE_8023AX_SLAVE_TX_PKTS;
972 for (q_id = 0; q_id < bond_dev->data->nb_tx_queues; q_id++) {
973 bd_tx_q = (struct bond_tx_queue*)bond_dev->data->tx_queues[q_id];
974 total_tx_desc += bd_tx_q->nb_tx_desc;
975 }
976
977 snprintf(mem_name, RTE_DIM(mem_name), "slave_port%u_pool", slave_id);
11fdf7f2
TL
978 port->mbuf_pool = rte_pktmbuf_pool_create(mem_name, total_tx_desc,
979 RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ?
980 32 : RTE_MEMPOOL_CACHE_MAX_SIZE,
981 0, element_size, socket_id);
7c673cae 982
11fdf7f2 983 /* Any memory allocation failure in initialization is critical because
7c673cae
FG
984 * resources can't be free, so reinitialization is impossible. */
985 if (port->mbuf_pool == NULL) {
986 rte_panic("Slave %u: Failed to create memory pool '%s': %s\n",
987 slave_id, mem_name, rte_strerror(rte_errno));
988 }
989
990 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_rx", slave_id);
991 port->rx_ring = rte_ring_create(mem_name,
992 rte_align32pow2(BOND_MODE_8023AX_SLAVE_RX_PKTS), socket_id, 0);
993
994 if (port->rx_ring == NULL) {
995 rte_panic("Slave %u: Failed to create rx ring '%s': %s\n", slave_id,
996 mem_name, rte_strerror(rte_errno));
997 }
998
999 /* TX ring is at least one pkt longer to make room for marker packet. */
1000 snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_tx", slave_id);
1001 port->tx_ring = rte_ring_create(mem_name,
1002 rte_align32pow2(BOND_MODE_8023AX_SLAVE_TX_PKTS + 1), socket_id, 0);
1003
1004 if (port->tx_ring == NULL) {
1005 rte_panic("Slave %u: Failed to create tx ring '%s': %s\n", slave_id,
1006 mem_name, rte_strerror(rte_errno));
1007 }
1008}
1009
1010int
11fdf7f2
TL
1011bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev __rte_unused,
1012 uint16_t slave_id)
7c673cae 1013{
7c673cae 1014 void *pkt = NULL;
11fdf7f2
TL
1015 struct port *port = NULL;
1016 uint8_t old_partner_state;
7c673cae 1017
9f95a23c 1018 port = &bond_mode_8023ad_ports[slave_id];
7c673cae 1019
11fdf7f2
TL
1020 ACTOR_STATE_CLR(port, AGGREGATION);
1021 port->selected = UNSELECTED;
7c673cae 1022
11fdf7f2
TL
1023 old_partner_state = port->partner_state;
1024 record_default(port);
7c673cae 1025
11fdf7f2
TL
1026 /* If partner timeout state changes then disable timer */
1027 if (!((old_partner_state ^ port->partner_state) &
1028 STATE_LACP_SHORT_TIMEOUT))
1029 timer_cancel(&port->current_while_timer);
7c673cae 1030
11fdf7f2
TL
1031 PARTNER_STATE_CLR(port, AGGREGATION);
1032 ACTOR_STATE_CLR(port, EXPIRED);
7c673cae 1033
11fdf7f2 1034 /* flush rx/tx rings */
7c673cae
FG
1035 while (rte_ring_dequeue(port->rx_ring, &pkt) == 0)
1036 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1037
1038 while (rte_ring_dequeue(port->tx_ring, &pkt) == 0)
1039 rte_pktmbuf_free((struct rte_mbuf *)pkt);
1040 return 0;
1041}
1042
1043void
1044bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev)
1045{
1046 struct bond_dev_private *internals = bond_dev->data->dev_private;
1047 struct ether_addr slave_addr;
1048 struct port *slave, *agg_slave;
11fdf7f2 1049 uint16_t slave_id, i, j;
7c673cae
FG
1050
1051 bond_mode_8023ad_stop(bond_dev);
1052
1053 for (i = 0; i < internals->active_slave_count; i++) {
1054 slave_id = internals->active_slaves[i];
9f95a23c 1055 slave = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1056 rte_eth_macaddr_get(slave_id, &slave_addr);
1057
1058 if (is_same_ether_addr(&slave_addr, &slave->actor.system))
1059 continue;
1060
1061 ether_addr_copy(&slave_addr, &slave->actor.system);
1062 /* Do nothing if this port is not an aggregator. In other case
1063 * Set NTT flag on every port that use this aggregator. */
1064 if (slave->aggregator_port_id != slave_id)
1065 continue;
1066
1067 for (j = 0; j < internals->active_slave_count; j++) {
9f95a23c 1068 agg_slave = &bond_mode_8023ad_ports[internals->active_slaves[j]];
7c673cae
FG
1069 if (agg_slave->aggregator_port_id == slave_id)
1070 SM_FLAG_SET(agg_slave, NTT);
1071 }
1072 }
1073
1074 if (bond_dev->data->dev_started)
1075 bond_mode_8023ad_start(bond_dev);
1076}
1077
1078static void
1079bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
1080 struct rte_eth_bond_8023ad_conf *conf)
1081{
1082 struct bond_dev_private *internals = dev->data->dev_private;
1083 struct mode8023ad_private *mode4 = &internals->mode4;
1084 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1085
1086 conf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks;
1087 conf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks;
1088 conf->short_timeout_ms = mode4->short_timeout / ms_ticks;
1089 conf->long_timeout_ms = mode4->long_timeout / ms_ticks;
1090 conf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks;
1091 conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;
1092 conf->update_timeout_ms = mode4->update_timeout_us / 1000;
1093 conf->rx_marker_period_ms = mode4->rx_marker_timeout / ms_ticks;
7c673cae 1094 conf->slowrx_cb = mode4->slowrx_cb;
11fdf7f2 1095 conf->agg_selection = mode4->agg_selection;
7c673cae
FG
1096}
1097
1098static void
1099bond_mode_8023ad_conf_get_default(struct rte_eth_bond_8023ad_conf *conf)
1100{
1101 conf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS;
1102 conf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS;
1103 conf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS;
1104 conf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS;
1105 conf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS;
1106 conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;
1107 conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;
1108 conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;
1109 conf->slowrx_cb = NULL;
11fdf7f2 1110 conf->agg_selection = AGG_STABLE;
7c673cae
FG
1111}
1112
1113static void
1114bond_mode_8023ad_conf_assign(struct mode8023ad_private *mode4,
1115 struct rte_eth_bond_8023ad_conf *conf)
1116{
1117 uint64_t ms_ticks = rte_get_tsc_hz() / 1000;
1118
1119 mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;
1120 mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;
1121 mode4->short_timeout = conf->short_timeout_ms * ms_ticks;
1122 mode4->long_timeout = conf->long_timeout_ms * ms_ticks;
1123 mode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks;
1124 mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;
1125 mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;
1126 mode4->update_timeout_us = conf->update_timeout_ms * 1000;
7c673cae 1127
11fdf7f2
TL
1128 mode4->dedicated_queues.enabled = 0;
1129 mode4->dedicated_queues.rx_qid = UINT16_MAX;
1130 mode4->dedicated_queues.tx_qid = UINT16_MAX;
7c673cae
FG
1131}
1132
7c673cae
FG
1133void
1134bond_mode_8023ad_setup(struct rte_eth_dev *dev,
1135 struct rte_eth_bond_8023ad_conf *conf)
1136{
1137 struct rte_eth_bond_8023ad_conf def_conf;
1138 struct bond_dev_private *internals = dev->data->dev_private;
1139 struct mode8023ad_private *mode4 = &internals->mode4;
1140
1141 if (conf == NULL) {
1142 conf = &def_conf;
1143 bond_mode_8023ad_conf_get_default(conf);
1144 }
1145
1146 bond_mode_8023ad_stop(dev);
1147 bond_mode_8023ad_conf_assign(mode4, conf);
1148 mode4->slowrx_cb = conf->slowrx_cb;
11fdf7f2 1149 mode4->agg_selection = AGG_STABLE;
7c673cae
FG
1150
1151 if (dev->data->dev_started)
1152 bond_mode_8023ad_start(dev);
1153}
1154
1155int
1156bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
1157{
1158 struct bond_dev_private *internals = bond_dev->data->dev_private;
9f95a23c 1159 uint16_t i;
7c673cae
FG
1160
1161 for (i = 0; i < internals->active_slave_count; i++)
11fdf7f2
TL
1162 bond_mode_8023ad_activate_slave(bond_dev,
1163 internals->active_slaves[i]);
7c673cae
FG
1164
1165 return 0;
1166}
1167
1168int
1169bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
1170{
1171 struct bond_dev_private *internals = bond_dev->data->dev_private;
1172 struct mode8023ad_private *mode4 = &internals->mode4;
1173 static const uint64_t us = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000;
1174
9f95a23c 1175 rte_eth_macaddr_get(internals->port_id, &mode4->mac_addr);
7c673cae
FG
1176 if (mode4->slowrx_cb)
1177 return rte_eal_alarm_set(us, &bond_mode_8023ad_ext_periodic_cb,
1178 bond_dev);
1179
1180 return rte_eal_alarm_set(us, &bond_mode_8023ad_periodic_cb, bond_dev);
1181}
1182
1183void
1184bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)
1185{
1186 struct bond_dev_private *internals = bond_dev->data->dev_private;
1187 struct mode8023ad_private *mode4 = &internals->mode4;
1188
1189 if (mode4->slowrx_cb) {
1190 rte_eal_alarm_cancel(&bond_mode_8023ad_ext_periodic_cb,
1191 bond_dev);
1192 return;
1193 }
1194 rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev);
1195}
1196
1197void
1198bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
11fdf7f2 1199 uint16_t slave_id, struct rte_mbuf *pkt)
7c673cae
FG
1200{
1201 struct mode8023ad_private *mode4 = &internals->mode4;
9f95a23c 1202 struct port *port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1203 struct marker_header *m_hdr;
1204 uint64_t marker_timer, old_marker_timer;
1205 int retval;
1206 uint8_t wrn, subtype;
1207 /* If packet is a marker, we send response now by reusing given packet
1208 * and update only source MAC, destination MAC is multicast so don't
1209 * update it. Other frames will be handled later by state machines */
1210 subtype = rte_pktmbuf_mtod(pkt,
1211 struct slow_protocol_frame *)->slow_protocol.subtype;
1212
1213 if (subtype == SLOW_SUBTYPE_MARKER) {
1214 m_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *);
1215
1216 if (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) {
1217 wrn = WRN_UNKNOWN_MARKER_TYPE;
1218 goto free_out;
1219 }
1220
1221 /* Setup marker timer. Do it in loop in case concurrent access. */
1222 do {
1223 old_marker_timer = port->rx_marker_timer;
1224 if (!timer_is_expired(&old_marker_timer)) {
1225 wrn = WRN_RX_MARKER_TO_FAST;
1226 goto free_out;
1227 }
1228
1229 timer_set(&marker_timer, mode4->rx_marker_timeout);
1230 retval = rte_atomic64_cmpset(&port->rx_marker_timer,
1231 old_marker_timer, marker_timer);
1232 } while (unlikely(retval == 0));
1233
1234 m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP;
1235 rte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr);
1236
11fdf7f2
TL
1237 if (internals->mode4.dedicated_queues.enabled == 0) {
1238 int retval = rte_ring_enqueue(port->tx_ring, pkt);
1239 if (retval != 0) {
1240 /* reset timer */
1241 port->rx_marker_timer = 0;
1242 wrn = WRN_TX_QUEUE_FULL;
1243 goto free_out;
1244 }
1245 } else {
1246 /* Send packet directly to the slow queue */
1247 uint16_t tx_count = rte_eth_tx_burst(slave_id,
1248 internals->mode4.dedicated_queues.tx_qid,
1249 &pkt, 1);
1250 if (tx_count != 1) {
1251 /* reset timer */
1252 port->rx_marker_timer = 0;
1253 wrn = WRN_TX_QUEUE_FULL;
1254 goto free_out;
1255 }
7c673cae
FG
1256 }
1257 } else if (likely(subtype == SLOW_SUBTYPE_LACP)) {
11fdf7f2
TL
1258 if (internals->mode4.dedicated_queues.enabled == 0) {
1259 int retval = rte_ring_enqueue(port->rx_ring, pkt);
1260 if (retval != 0) {
1261 /* If RX fing full free lacpdu message and drop packet */
1262 wrn = WRN_RX_QUEUE_FULL;
1263 goto free_out;
1264 }
1265 } else
1266 rx_machine_update(internals, slave_id, pkt);
7c673cae
FG
1267 } else {
1268 wrn = WRN_UNKNOWN_SLOW_TYPE;
1269 goto free_out;
1270 }
1271
1272 return;
1273
1274free_out:
1275 set_warning_flags(port, wrn);
1276 rte_pktmbuf_free(pkt);
1277}
1278
1279int
11fdf7f2 1280rte_eth_bond_8023ad_conf_get(uint16_t port_id,
7c673cae
FG
1281 struct rte_eth_bond_8023ad_conf *conf)
1282{
1283 struct rte_eth_dev *bond_dev;
1284
1285 if (valid_bonded_port_id(port_id) != 0)
1286 return -EINVAL;
1287
1288 if (conf == NULL)
1289 return -EINVAL;
1290
1291 bond_dev = &rte_eth_devices[port_id];
1292 bond_mode_8023ad_conf_get(bond_dev, conf);
1293 return 0;
1294}
7c673cae
FG
1295
1296int
11fdf7f2
TL
1297rte_eth_bond_8023ad_agg_selection_set(uint16_t port_id,
1298 enum rte_bond_8023ad_agg_selection agg_selection)
7c673cae
FG
1299{
1300 struct rte_eth_dev *bond_dev;
11fdf7f2
TL
1301 struct bond_dev_private *internals;
1302 struct mode8023ad_private *mode4;
1303
1304 bond_dev = &rte_eth_devices[port_id];
1305 internals = bond_dev->data->dev_private;
7c673cae
FG
1306
1307 if (valid_bonded_port_id(port_id) != 0)
1308 return -EINVAL;
11fdf7f2 1309 if (internals->mode != 4)
7c673cae
FG
1310 return -EINVAL;
1311
11fdf7f2
TL
1312 mode4 = &internals->mode4;
1313 if (agg_selection == AGG_COUNT || agg_selection == AGG_BANDWIDTH
1314 || agg_selection == AGG_STABLE)
1315 mode4->agg_selection = agg_selection;
7c673cae
FG
1316 return 0;
1317}
11fdf7f2
TL
1318
1319int rte_eth_bond_8023ad_agg_selection_get(uint16_t port_id)
1320{
1321 struct rte_eth_dev *bond_dev;
1322 struct bond_dev_private *internals;
1323 struct mode8023ad_private *mode4;
1324
1325 bond_dev = &rte_eth_devices[port_id];
1326 internals = bond_dev->data->dev_private;
1327
1328 if (valid_bonded_port_id(port_id) != 0)
1329 return -EINVAL;
1330 if (internals->mode != 4)
1331 return -EINVAL;
1332 mode4 = &internals->mode4;
1333
1334 return mode4->agg_selection;
1335}
1336
1337
7c673cae
FG
1338
1339static int
11fdf7f2 1340bond_8023ad_setup_validate(uint16_t port_id,
7c673cae
FG
1341 struct rte_eth_bond_8023ad_conf *conf)
1342{
1343 if (valid_bonded_port_id(port_id) != 0)
1344 return -EINVAL;
1345
1346 if (conf != NULL) {
1347 /* Basic sanity check */
1348 if (conf->slow_periodic_ms == 0 ||
1349 conf->fast_periodic_ms >= conf->slow_periodic_ms ||
1350 conf->long_timeout_ms == 0 ||
1351 conf->short_timeout_ms >= conf->long_timeout_ms ||
1352 conf->aggregate_wait_timeout_ms == 0 ||
1353 conf->tx_period_ms == 0 ||
1354 conf->rx_marker_period_ms == 0 ||
1355 conf->update_timeout_ms == 0) {
11fdf7f2 1356 RTE_BOND_LOG(ERR, "given mode 4 configuration is invalid");
7c673cae
FG
1357 return -EINVAL;
1358 }
1359 }
1360
1361 return 0;
1362}
1363
11fdf7f2 1364
7c673cae 1365int
11fdf7f2 1366rte_eth_bond_8023ad_setup(uint16_t port_id,
7c673cae
FG
1367 struct rte_eth_bond_8023ad_conf *conf)
1368{
1369 struct rte_eth_dev *bond_dev;
1370 int err;
1371
1372 err = bond_8023ad_setup_validate(port_id, conf);
1373 if (err != 0)
1374 return err;
1375
1376 bond_dev = &rte_eth_devices[port_id];
11fdf7f2 1377 bond_mode_8023ad_setup(bond_dev, conf);
7c673cae
FG
1378
1379 return 0;
1380}
7c673cae 1381
7c673cae 1382
7c673cae 1383
7c673cae 1384
7c673cae
FG
1385
1386int
11fdf7f2 1387rte_eth_bond_8023ad_slave_info(uint16_t port_id, uint16_t slave_id,
7c673cae
FG
1388 struct rte_eth_bond_8023ad_slave_info *info)
1389{
1390 struct rte_eth_dev *bond_dev;
1391 struct bond_dev_private *internals;
1392 struct port *port;
1393
1394 if (info == NULL || valid_bonded_port_id(port_id) != 0 ||
1395 rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1396 return -EINVAL;
1397
1398 bond_dev = &rte_eth_devices[port_id];
1399
1400 internals = bond_dev->data->dev_private;
1401 if (find_slave_by_id(internals->active_slaves,
1402 internals->active_slave_count, slave_id) ==
1403 internals->active_slave_count)
1404 return -EINVAL;
1405
9f95a23c 1406 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1407 info->selected = port->selected;
1408
1409 info->actor_state = port->actor_state;
1410 rte_memcpy(&info->actor, &port->actor, sizeof(port->actor));
1411
1412 info->partner_state = port->partner_state;
1413 rte_memcpy(&info->partner, &port->partner, sizeof(port->partner));
1414
1415 info->agg_port_id = port->aggregator_port_id;
1416 return 0;
1417}
1418
1419static int
11fdf7f2 1420bond_8023ad_ext_validate(uint16_t port_id, uint16_t slave_id)
7c673cae
FG
1421{
1422 struct rte_eth_dev *bond_dev;
1423 struct bond_dev_private *internals;
1424 struct mode8023ad_private *mode4;
1425
1426 if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
1427 return -EINVAL;
1428
1429 bond_dev = &rte_eth_devices[port_id];
1430
1431 if (!bond_dev->data->dev_started)
1432 return -EINVAL;
1433
1434 internals = bond_dev->data->dev_private;
1435 if (find_slave_by_id(internals->active_slaves,
1436 internals->active_slave_count, slave_id) ==
1437 internals->active_slave_count)
1438 return -EINVAL;
1439
1440 mode4 = &internals->mode4;
1441 if (mode4->slowrx_cb == NULL)
1442 return -EINVAL;
1443
1444 return 0;
1445}
1446
1447int
11fdf7f2
TL
1448rte_eth_bond_8023ad_ext_collect(uint16_t port_id, uint16_t slave_id,
1449 int enabled)
7c673cae
FG
1450{
1451 struct port *port;
1452 int res;
1453
1454 res = bond_8023ad_ext_validate(port_id, slave_id);
1455 if (res != 0)
1456 return res;
1457
9f95a23c 1458 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1459
1460 if (enabled)
1461 ACTOR_STATE_SET(port, COLLECTING);
1462 else
1463 ACTOR_STATE_CLR(port, COLLECTING);
1464
1465 return 0;
1466}
1467
1468int
11fdf7f2
TL
1469rte_eth_bond_8023ad_ext_distrib(uint16_t port_id, uint16_t slave_id,
1470 int enabled)
7c673cae
FG
1471{
1472 struct port *port;
1473 int res;
1474
1475 res = bond_8023ad_ext_validate(port_id, slave_id);
1476 if (res != 0)
1477 return res;
1478
9f95a23c 1479 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1480
1481 if (enabled)
1482 ACTOR_STATE_SET(port, DISTRIBUTING);
1483 else
1484 ACTOR_STATE_CLR(port, DISTRIBUTING);
1485
1486 return 0;
1487}
1488
1489int
11fdf7f2 1490rte_eth_bond_8023ad_ext_distrib_get(uint16_t port_id, uint16_t slave_id)
7c673cae
FG
1491{
1492 struct port *port;
1493 int err;
1494
1495 err = bond_8023ad_ext_validate(port_id, slave_id);
1496 if (err != 0)
1497 return err;
1498
9f95a23c 1499 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1500 return ACTOR_STATE(port, DISTRIBUTING);
1501}
1502
1503int
11fdf7f2 1504rte_eth_bond_8023ad_ext_collect_get(uint16_t port_id, uint16_t slave_id)
7c673cae
FG
1505{
1506 struct port *port;
1507 int err;
1508
1509 err = bond_8023ad_ext_validate(port_id, slave_id);
1510 if (err != 0)
1511 return err;
1512
9f95a23c 1513 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1514 return ACTOR_STATE(port, COLLECTING);
1515}
1516
1517int
11fdf7f2 1518rte_eth_bond_8023ad_ext_slowtx(uint16_t port_id, uint16_t slave_id,
7c673cae
FG
1519 struct rte_mbuf *lacp_pkt)
1520{
1521 struct port *port;
1522 int res;
1523
1524 res = bond_8023ad_ext_validate(port_id, slave_id);
1525 if (res != 0)
1526 return res;
1527
9f95a23c 1528 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1529
1530 if (rte_pktmbuf_pkt_len(lacp_pkt) < sizeof(struct lacpdu_header))
1531 return -EINVAL;
1532
1533 struct lacpdu_header *lacp;
1534
1535 /* only enqueue LACPDUs */
1536 lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
1537 if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
1538 return -EINVAL;
1539
1540 MODE4_DEBUG("sending LACP frame\n");
1541
1542 return rte_ring_enqueue(port->tx_ring, lacp_pkt);
1543}
1544
1545static void
1546bond_mode_8023ad_ext_periodic_cb(void *arg)
1547{
1548 struct rte_eth_dev *bond_dev = arg;
1549 struct bond_dev_private *internals = bond_dev->data->dev_private;
1550 struct mode8023ad_private *mode4 = &internals->mode4;
1551 struct port *port;
1552 void *pkt = NULL;
1553 uint16_t i, slave_id;
1554
1555 for (i = 0; i < internals->active_slave_count; i++) {
1556 slave_id = internals->active_slaves[i];
9f95a23c 1557 port = &bond_mode_8023ad_ports[slave_id];
7c673cae
FG
1558
1559 if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {
1560 struct rte_mbuf *lacp_pkt = pkt;
1561 struct lacpdu_header *lacp;
1562
1563 lacp = rte_pktmbuf_mtod(lacp_pkt,
1564 struct lacpdu_header *);
1565 RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
1566
1567 /* This is LACP frame so pass it to rx callback.
1568 * Callback is responsible for freeing mbuf.
1569 */
1570 mode4->slowrx_cb(slave_id, lacp_pkt);
1571 }
1572 }
1573
1574 rte_eal_alarm_set(internals->mode4.update_timeout_us,
1575 bond_mode_8023ad_ext_periodic_cb, arg);
1576}
11fdf7f2
TL
1577
1578int
1579rte_eth_bond_8023ad_dedicated_queues_enable(uint16_t port)
1580{
1581 int retval = 0;
1582 struct rte_eth_dev *dev = &rte_eth_devices[port];
1583 struct bond_dev_private *internals = (struct bond_dev_private *)
1584 dev->data->dev_private;
1585
1586 if (check_for_bonded_ethdev(dev) != 0)
1587 return -1;
1588
1589 if (bond_8023ad_slow_pkt_hw_filter_supported(port) != 0)
1590 return -1;
1591
1592 /* Device must be stopped to set up slow queue */
1593 if (dev->data->dev_started)
1594 return -1;
1595
1596 internals->mode4.dedicated_queues.enabled = 1;
1597
1598 bond_ethdev_mode_set(dev, internals->mode);
1599 return retval;
1600}
1601
1602int
1603rte_eth_bond_8023ad_dedicated_queues_disable(uint16_t port)
1604{
1605 int retval = 0;
1606 struct rte_eth_dev *dev = &rte_eth_devices[port];
1607 struct bond_dev_private *internals = (struct bond_dev_private *)
1608 dev->data->dev_private;
1609
1610 if (check_for_bonded_ethdev(dev) != 0)
1611 return -1;
1612
1613 /* Device must be stopped to set up slow queue */
1614 if (dev->data->dev_started)
1615 return -1;
1616
1617 internals->mode4.dedicated_queues.enabled = 0;
1618
1619 bond_ethdev_mode_set(dev, internals->mode);
1620
1621 return retval;
1622}