/* * lacp_init_port * * LACP Agent is being enabled/disabled. * * Start/Stop the necessay timers and enable/disable agent states. */ extern void lacpa_init_port (lacpa_system_t *system, lacpa_info_t *info, uint8_t lacp_enabled) { lacpa_port_t *port = NULL; if (!info || !system) return; /* * Find any port corresponding to the info received */ port = lacpa_find_port(system, info->port_no); if (!port) return; AIM_LOG_TRACE("LACP %s received for port: %d", lacp_enabled? "ENABLE": "DISABLE", port->actor.port_no); lacpa_copy_info(info, &port->actor); lacpa_dump_port(port); if (lacp_enabled) { port->lacp_event = LACPA_EVENT_ENABLED; } else { port->lacp_event = LACPA_EVENT_DISABLED; } port->system = system; lacpa_machine(port, NULL); }
/* * lacpa_current_while_expiration_timer_cb * * Current while Expiration callback */ static void lacpa_current_while_expiration_timer_cb (void *cookie) { lacpa_event_t event; if (!cookie) return; lacpa_port_t *port = (lacpa_port_t *)cookie; if (!port) return; AIM_LOG_TRACE("current_while timer callback for port: %d", port->actor.port_no); if (port->lacp_state == LACPA_MACHINE_AGENT_CURRENT) { event = LACPA_EVENT_CURRENT_TIMER_EXPIRED; } else if (port->lacp_state == LACPA_MACHINE_AGENT_EXPIRED) { event = LACPA_EVENT_EXPIRY_TIMER_EXPIRED; } else { /* * Sanity check, disable the timer */ lacpa_stop_current_while_timer(port); return; } lacpa_machine(port, NULL, event); }
/* * lacpa_churn_expiration_timer_cb * * Churn Detection Timer Expiration callback */ static void lacpa_churn_expiration_timer_cb (void *cookie) { if (!cookie) return; lacpa_port_t *port = (lacpa_port_t *)cookie; if (!port) return; AIM_LOG_TRACE("Churn Detection timer callback for port: %d", port->actor.port_no); lacpa_machine(port, NULL, LACPA_EVENT_CHURN_DETECTION_EXPIRED); }
/* * lacpa_receive * * Process incoming LACPDU and take appropriate action */ extern bool lacpa_receive (lacpa_port_t *port, uint8_t *data, uint32_t bytes) { lacpa_pdu_t pdu; ppe_packet_t ppep; if (!port || !data) return FALSE; if (!port->lacp_enabled) { AIM_LOG_ERROR("LACPDU-Rx-FAILED - Agent is Disabled on port: %d", port->actor.port_no); return FALSE; } LACPA_MEMSET(&pdu, DEFAULT_ZERO, sizeof(lacpa_pdu_t)); AIM_LOG_TRACE("LACPDU Received on port: %d", port->actor.port_no); /* * Use ppe api's to fill info from data in our pdu */ ppe_packet_init(&ppep, data, bytes); if (ppe_parse(&ppep) < 0) { AIM_LOG_ERROR("Packet parsing failed. packet=%{data}", data, bytes); return FALSE; } if (!ppe_header_get(&ppep, PPE_HEADER_LACP)) { AIM_LOG_ERROR("Not a Valid LCAP Packet"); return FALSE; } /* * Retrieve the information from the LCAP packet */ if (!lacpa_parse_pdu(&ppep, &pdu)) { AIM_LOG_ERROR("Packet parsing failed."); return FALSE; } port->lacp_event = LACPA_EVENT_PDU_RECEIVED; lacpa_machine(port, &pdu); return TRUE; }
/* * lacpa_update_convergence * * Decide Protocol Converged/Unconverged based on following: * 1. If Partner aggregation state = FALSE; Unconverged * 2. If Partner sync state = FALSE; Unconverged * 3. If Partner collecting state = FALSE; Unconverged * 4. If Partner distributing state = FALSE; Unconverged * Else, Converged */ static void lacpa_update_convergence (lacpa_port_t *port, bool *ntt) { lacpa_error_t prev_error = port->error; if (!port || !ntt) return; if (!LACPA_IS_STATE_AGGREGATION(port->partner.state)) { if (prev_error != LACPA_ERROR_PARTNER_AGGREGATION_OFF) { AIM_LOG_ERROR("Setting unconverged, Mis-match in aggregation state"); port->error = LACPA_ERROR_PARTNER_AGGREGATION_OFF; port->lacp_event = LACPA_EVENT_PROTOCOL_UNCONVERGED; lacpa_machine(port, NULL); } else { AIM_LOG_ERROR("Protocol Already Unconverged..No action required"); } return; } if (!LACPA_IS_STATE_SYNCHRONIZATION(port->actor.state)) { AIM_LOG_TRACE("Setting Actor sync state for Port: %d", port->actor.port_no); LACPA_SET_STATE_SYNCHRONIZATION(port->actor.state); port->ntt_reason = LACPA_TRANSMIT_SYNCHRONIZATION_SET; *ntt = TRUE; } if (!LACPA_IS_STATE_SYNCHRONIZATION(port->partner.state)) { port->error = LACPA_ERROR_PARTNER_INSYNC; goto unconverged; } if (!LACPA_IS_STATE_COLLECTING(port->actor.state)) { AIM_LOG_TRACE("Setting Actor collection state for Port: %d", port->actor.port_no); LACPA_SET_STATE_COLLECTING(port->actor.state); port->ntt_reason = LACPA_TRANSMIT_COLLECTING_SET; *ntt = TRUE; } if (!LACPA_IS_STATE_COLLECTING(port->partner.state)) { port->error = LACPA_ERROR_PARTNER_COLLECTION_OFF; goto unconverged; } if (!LACPA_IS_STATE_DISTRIBUTING(port->actor.state)) { AIM_LOG_TRACE("Setting Actor distribution state Port: %d", port->actor.port_no); LACPA_SET_STATE_DISTRIBUTING(port->actor.state); port->ntt_reason = LACPA_TRANSMIT_DISTRIBUTING_SET; *ntt = TRUE; } if (!LACPA_IS_STATE_DISTRIBUTING(port->partner.state)) { port->error = LACPA_ERROR_PARTNER_DISTRIBUTION_OFF; goto unconverged; } AIM_LOG_TRACE("Setting Port: %d to Converged, ntt_reason: %{lacpa_transmit}", port->actor.port_no, port->ntt_reason); port->error = LACPA_ERROR_NONE; port->is_converged = TRUE; return; unconverged: AIM_LOG_TRACE("Setting Port: %d to Unconverged, reason: %{lacpa_error}, " "ntt_reason: %{lacpa_transmit}", port->actor.port_no, port->error, port->ntt_reason); port->is_converged = FALSE; }