/** * This function handles local sync done event * * @param[in] data - event data * * @return 0 when successful, otherwise ERROR */ int mlag_l3_interface_peer_local_sync_done(uint8_t *data) { int err = 0; UNUSED_PARAM(data); struct sync_event_data ev; struct mlag_master_election_status master_election_current_status; MLAG_LOG(MLAG_LOG_NOTICE, "send MLAG_L3_SYNC_FINISH_EVENT to master logic\n"); err = mlag_master_election_get_status(&master_election_current_status); MLAG_BAIL_ERROR_MSG(err, "Failed to get status from master election in handling of local sync done event, err=%d\n", err); /* Send MLAG_L3_SYNC_FINISH_EVENT to Master Logic */ ev.peer_id = master_election_current_status.my_peer_id; ev.state = 1; err = mlag_dispatcher_message_send(MLAG_L3_SYNC_FINISH_EVENT, &ev, sizeof(ev), MASTER_PEER_ID, PEER_MANAGER); MLAG_BAIL_ERROR_MSG(err, "Failed in sending MLAG_L3_SYNC_FINISH_EVENT, err=%d\n", err); bail: return err; }
/* * Sends release requests * * @param[in] request - selection request data * * @return 0 when successful, otherwise ERROR */ static int send_release_message(struct lacp_aggregation_message_data *request) { int err = 0; struct mlag_master_election_status me_status; err = mlag_master_election_get_status(&me_status); MLAG_BAIL_ERROR_MSG(err, "Failed getting ME status\n"); /* send message to logic */ request->mlag_id = me_status.my_peer_id; request->select = FALSE; if ((current_role == SLAVE) && (use_local_lacp_logic == TRUE)) { err = send_system_event(MLAG_LACP_SELECTION_EVENT, request, sizeof(*request)); MLAG_BAIL_ERROR_MSG(err, "Failed in sending MLAG_LACP_SELECTION_EVENT event\n"); } else { err = lacp_manager_message_send(MLAG_LACP_SELECTION_EVENT, request, sizeof(*request), me_status.master_peer_id, PEER_MANAGER); MLAG_BAIL_ERROR_MSG(err, "Failed sending release request id [%u] port [%lu]\n", request->request_id, request->port_id); } bail: return err; }
/* * Used for sending messages * with implementation of counting mechanism * * @param[in] opcode - message opcode * @param[in] payload - pointer to message data * @param[in] payload_len - message data length * @param[in] dest_peer_id - mlag id of dest peer * @param[in] orig - message originator * * @return 0 if operation completes successfully. */ static int lacp_manager_message_send(enum mlag_events opcode, void* payload, uint32_t payload_len, uint8_t dest_peer_id, enum message_originator orig) { int err = 0; struct mlag_master_election_status me_status; err = mlag_dispatcher_message_send(opcode, payload, payload_len, dest_peer_id, orig); MLAG_BAIL_CHECK_NO_MSG(err); err = mlag_master_election_get_status(&me_status); MLAG_BAIL_ERROR_MSG(err, "Failed getting ME status\n"); /* Counters */ if ((dest_peer_id != me_status.my_peer_id) || ((orig == PEER_MANAGER) && (current_role == SLAVE))) { /* increment IPL counter */ lacp_db_counters_inc(LM_CNT_PROTOCOL_TX); } bail: return err; }
/** * Returns actor attributes. The actor attributes are * system ID, system priority to be used in the LACP PDU * and a chassis ID which is an index of this node within the MLAG * cluster, with a value in the range of 0..15 * * @param[out] actor_sys_id - actor sys ID (for LACP PDU) * @param[out] chassis_id - MLAG cluster chassis ID, range 0..15 * * @return 0 when successful, otherwise ERROR */ int lacp_manager_actor_parameters_get(unsigned long long *actor_sys_id, unsigned int *chassis_id) { int err = 0; struct mlag_master_election_status me_status; ASSERT(actor_sys_id != NULL); ASSERT(chassis_id != NULL); if ((started == FALSE) || (lacp_enabled == FALSE)) { *chassis_id = 0; MLAG_LOG(MLAG_LOG_NOTICE, "Actor parameters requested although LACP module inactive\n"); err = lacp_db_local_system_id_get(actor_sys_id); MLAG_BAIL_ERROR_MSG(err, "Failed to retrieve local LACP attributes\n"); goto bail; } err = mlag_master_election_get_status(&me_status); MLAG_BAIL_ERROR_MSG(err, "Failed getting ME status\n"); /* If slave we return master's parameters, otherwise we * return the local parameters */ if ((me_status.current_status == SLAVE) && (use_local_lacp_logic == FALSE)) { err = lacp_db_master_system_id_get(actor_sys_id); MLAG_BAIL_ERROR_MSG(err, "Failed to retrieve master LACP attributes\n"); /* Chassis ID is set by master election module */ *chassis_id = me_status.my_peer_id; } else { *chassis_id = 0; err = lacp_db_local_system_id_get(actor_sys_id); MLAG_BAIL_ERROR_MSG(err, "Failed to retrieve master LACP attributes\n"); } bail: return err; }
/** * Handles peer start notification.Peer start * triggers lacp sync process start. The Master * sends its actor attributes to the remotes. * * @param[in] mlag_peer_id - peer global index * * @return 0 if operation completes successfully. */ int lacp_manager_peer_start(int mlag_peer_id) { int err = 0; struct peer_lacp_sync_message sync_message; struct mlag_master_election_status me_status; ASSERT(mlag_peer_id < MLAG_MAX_PEERS); if ((started == FALSE) || (lacp_enabled == FALSE)) { goto bail; } err = mlag_master_election_get_status(&me_status); MLAG_BAIL_ERROR_MSG(err, "Failed getting ME status\n"); /* Master will send sync done for itself */ if (me_status.current_status == SLAVE) { /* Slave will send sync start message */ sync_message.mlag_id = me_status.my_peer_id; sync_message.phase = LACP_SYNC_START; /* Send message to master */ MLAG_LOG(MLAG_LOG_DEBUG, "LACP peer [%d] sync send to master \n", sync_message.mlag_id); /* Send to master logic sync message */ err = lacp_manager_message_send(MLAG_LACP_SYNC_MSG, &sync_message, sizeof(sync_message), me_status.master_peer_id, PEER_MANAGER); MLAG_BAIL_ERROR_MSG(err, "Failed in sending ports sync message \n"); } else if (mlag_peer_id == me_status.my_peer_id) { MLAG_LOG(MLAG_LOG_NOTICE, "Send LACP peer sync\n"); err = lacp_send_sync_done(mlag_peer_id); MLAG_BAIL_ERROR_MSG(err, "Failed in sending lacp sync done\n"); } bail: return err; }
/** * This function handles vlan local state change event * * @param[in] data - event data * * @return 0 when successful, otherwise ERROR */ int mlag_l3_interface_peer_vlan_local_state_change( struct vlan_state_change_event_data *data) { int err = 0; int ev_len = 0; struct mlag_master_election_status master_election_current_status; int i; ASSERT(data); if (!is_started) { MLAG_LOG(MLAG_LOG_NOTICE, "Vlan local state change event accepted before start of module\n"); goto bail; } if (!is_master_sync_done) { MLAG_LOG(MLAG_LOG_NOTICE, "Vlan local state change event accepted before master sync done\n"); goto bail; } MLAG_LOG(MLAG_LOG_INFO, "Vlan local state change event: number vlans %d\n", data->vlans_arr_cnt); if ((!data->vlans_arr_cnt) || (data->vlans_arr_cnt >= VLAN_N_VID)) { err = -EINVAL; MLAG_BAIL_ERROR_MSG(EINVAL, "Invalid vlans array_counter %d", data->vlans_arr_cnt); } for (i=0; i < data->vlans_arr_cnt; i++) { if (!(((data->vlan_data[i].vlan_id > 0) && (data->vlan_data[i].vlan_id < VLAN_N_VID)) && ((data->vlan_data[i].vlan_state == VLAN_DOWN) || (data->vlan_data[i].vlan_state == VLAN_UP)))) { MLAG_BAIL_ERROR_MSG(EINVAL, "Invalid vlan parameters: vlan id=%d, vlan state=%s", data->vlan_data[i].vlan_id, (data->vlan_data[i].vlan_state == VLAN_UP) ? "up" : "down"); } } mlag_l3_interface_inc_cnt(VLAN_LOCAL_STATE_EVENTS_RCVD); /* Send MLAG_L3_INTERFACE_VLAN_LOCAL_STATE_CHANGE_FROM_PEER_EVENT * to Master Logic */ err = mlag_master_election_get_status(&master_election_current_status); MLAG_BAIL_ERROR_MSG(err, "Failed to get status from master election in handling of vlan local state change event, err=%d\n", err); ev_len = sizeof(struct vlan_state_change_base_event_data) + sizeof(data->vlan_data[0]) * data->vlans_arr_cnt; data->peer_id = master_election_current_status.my_peer_id; err = mlag_dispatcher_message_send( MLAG_L3_INTERFACE_VLAN_LOCAL_STATE_CHANGE_FROM_PEER_EVENT, data, ev_len, MASTER_PEER_ID, PEER_MANAGER); MLAG_BAIL_ERROR_MSG(err, "Failed in sending MLAG_L3_INTERFACE_VLAN_LOCAL_STATE_CHANGE_FROM_PEER_EVENT, err=%d\n", err); bail: return err; }
/* * Handle incoming LACP sync message * * @param[in] lacp_sync - message body * * @return 0 when successful, otherwise ERROR */ static int handle_lacp_sync_msg(struct peer_lacp_sync_message *lacp_sync) { int err = 0; struct mlag_master_election_status me_status; struct peer_lacp_sync_message sync_message; ASSERT(lacp_sync != NULL); err = mlag_master_election_get_status(&me_status); MLAG_BAIL_ERROR_MSG(err, "Failed getting ME status\n"); switch (lacp_sync->phase) { case LACP_SYNC_START: /* send sync data if master */ sync_message.mlag_id = me_status.my_peer_id; sync_message.phase = LACP_SYNC_DATA; err = lacp_db_local_system_id_get(&sync_message.sys_id); MLAG_BAIL_ERROR_MSG(err, "Failed getting local actor attributes\n"); /* Send message to master */ MLAG_LOG(MLAG_LOG_DEBUG, "send LACP data to peer [%u] \n", lacp_sync->mlag_id); /* Send sync message with data */ err = lacp_manager_message_send(MLAG_LACP_SYNC_MSG, &sync_message, sizeof(sync_message), lacp_sync->mlag_id, MASTER_LOGIC); break; case LACP_SYNC_DATA: /* slave handles sync data */ err = update_lacp_master_attributes(lacp_sync); MLAG_BAIL_ERROR_MSG(err, "Failed updating master LACP attributes\n"); /* send sync done message */ sync_message.mlag_id = me_status.my_peer_id; sync_message.phase = LACP_SYNC_DONE; set_lacp_logic_origin(FALSE); /* Send message to master */ MLAG_LOG(MLAG_LOG_DEBUG, "send LACP data to peer [%u] \n", lacp_sync->mlag_id); /* Send to master logic sync message */ err = lacp_manager_message_send(MLAG_LACP_SYNC_MSG, &sync_message, sizeof(sync_message), lacp_sync->mlag_id, PEER_MANAGER); break; case LACP_SYNC_DONE: /* sync done received in master */ err = lacp_send_sync_done(lacp_sync->mlag_id); MLAG_BAIL_ERROR(err); break; case LACP_SYS_ID_UPDATE: /* slave handles lacp system id update from master */ err = update_lacp_master_attributes(lacp_sync); MLAG_BAIL_ERROR_MSG(err, "Failed updating master LACP attributes upon LACP_SYS_ID_UPDATE\n"); break; default: err = -ENOENT; MLAG_BAIL_ERROR_MSG(err, "Invalid LACP sync message\n"); break; } bail: return err; }