예제 #1
0
/**
 *  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;
}
예제 #2
0
/*
 * 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;
}
예제 #3
0
/*
 *  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;
}
예제 #4
0
/**
 * 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;
}
예제 #5
0
/**
 *  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;
}
예제 #6
0
/**
 *  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;
}
예제 #7
0
/*
 *  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;
}