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