Exemple #1
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;
}
/**
 *  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;
}
Exemple #3
0
/**
 *  This function inits lacp DB, it allocates MLAG_MAX_PORTS
 *  port entries in pool
 *
 * @return 0 when successful, otherwise ERROR
 */
int
lacp_db_init(void)
{
    int err = 0;
    cl_status_t cl_status = CL_SUCCESS;

    cl_status = cl_qpool_init(&(mlag_lacp_db.port_pool),
                              MLAG_MAX_PORTS, MLAG_MAX_PORTS, 0,
                              sizeof(struct mlag_lacp_entry), lacp_entry_init,
                              lacp_entry_deinit, NULL );
    if (cl_status != CL_SUCCESS) {
        err = -ENOMEM;
        MLAG_BAIL_ERROR_MSG(err, "Failed to Init LACP DB port pool\n");
    }
    cl_qmap_init(&(mlag_lacp_db.port_map));

    cl_status = cl_qpool_init(&(mlag_lacp_db.pending_pool),
                              MLAG_MAX_PORTS, MLAG_MAX_PORTS, 0,
                              sizeof(struct lacp_pending_entry),
                              pending_entry_init, pending_entry_deinit, NULL );
    if (cl_status != CL_SUCCESS) {
        err = -ENOMEM;
        MLAG_BAIL_ERROR_MSG(err, "Failed to Init LACP DB pending pool\n");
    }
    cl_qmap_init(&(mlag_lacp_db.pending_map));
    mlag_lacp_db.local_sys_id = 0;
    mlag_lacp_db.master_sys_id = 0;

bail:
    return err;
}
/**
 *  This function starts mlag l3 interface peer sub-module
 *
 *  @param data - event data
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_start(uint8_t *data)
{
    int err = 0;
    int i;
    UNUSED_PARAM(data);

    if (!is_inited) {
    	err = ECANCELED;
    	MLAG_BAIL_ERROR_MSG(err, "l3 interface peer start called before init\n");
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "l3 interface peer manager start\n");

    is_started = 1;
    is_peer_start = 0;
    is_master_sync_done = 0;
    for (i = 0; i < VLAN_N_VID; i++) {
        ipl_vlan_list[i] = 0;
    }

    /* Configure IPL as member of vlan of ipl l3 interface for control messages */
    if ((ipl_vlan_id > 0) &&
    	(ipl_vlan_id < VLAN_N_VID)) {

        err = mlag_topology_ipl_port_get(0, &ipl_ifindex);
        MLAG_BAIL_ERROR_MSG(err,
        		"Failed to get ipl data from mlag topology database upon start, err=%d\n",
        		err);

        /* For start after disable mlag protocol vlan_id as well as
         * ipl ifindex are not relevant.
         * In that case ipl ifindex 0 will be returned.
         * Ignore it up to peer add event that should configure
         * above mentioned parameters.
         */
        if (ipl_ifindex == 0) {
            goto bail;
        }

        MLAG_LOG(MLAG_LOG_NOTICE, "Add ipl %lu to vlan %d\n",
                 ipl_ifindex, ipl_vlan_id);

        /* Add IPL to vlan */
        err = sl_api_ipl_vlan_membership_action(OES_ACCESS_CMD_ADD,
                                                ipl_ifindex,
                                                &ipl_vlan_id, 1);
        MLAG_BAIL_ERROR_MSG(err,
        		"Failed to set ipl vlan membership, err=%d, ipl=%lu, vlan_id=%d\n",
        		err, ipl_ifindex, ipl_vlan_id);

        ipl_vlan_list[ipl_vlan_id] = 1;
        mlag_l3_interface_inc_cnt(ADD_IPL_TO_VLAN_EVENTS_SENT);
    }

bail:
    return err;
}
Exemple #5
0
/*
 *  This function is called to handle IBC message
 *
 * @param[in] data - message body
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
rcv_msg_handler(uint8_t *data)
{
    int err = 0;
    struct recv_payload_data *payload_data = (struct recv_payload_data*) data;
    uint16_t opcode;

    struct peer_lacp_sync_message *lacp_sync;
    struct lacp_aggregation_message_data *select_req;
    struct lacp_aggregator_release_message *rel_msg;

    opcode = *((uint16_t*)(payload_data->payload[0]));

    if ((started == FALSE) || (lacp_enabled == FALSE)) {
        goto bail;
    }

    MLAG_LOG(MLAG_LOG_INFO,
             "lacp manager rcv_msg_handler: opcode=%d\n", opcode);

    lacp_db_counters_inc(LM_CNT_PROTOCOL_RX);

    switch (opcode) {
    case MLAG_LACP_SYNC_MSG:
        lacp_sync =
            (struct peer_lacp_sync_message*) payload_data->payload[0];
        err = handle_lacp_sync_msg(lacp_sync);
        MLAG_BAIL_ERROR_MSG(err, "Failed in handling LACP sync message\n");
        break;
    case MLAG_LACP_SELECTION_EVENT:
        select_req =
            (struct lacp_aggregation_message_data *) payload_data->payload[0];

        err = lacp_manager_aggregator_selection_handle(select_req);
        MLAG_BAIL_ERROR_MSG(err,
                            "Failed to handle aggregation selection event\n");
        break;
    case MLAG_LACP_RELEASE_EVENT:
        rel_msg =
            (struct lacp_aggregator_release_message *) payload_data->payload[0];

        err = lacp_manager_aggregator_free_handle(rel_msg);
        MLAG_BAIL_ERROR_MSG(err, "Failed to handle aggregation free event\n");
        break;
    default:
        /* Unknown opcode */
        err = -ENOENT;
        MLAG_BAIL_ERROR_MSG(err, "Unknown opcode [%u] in lacp manager\n",
                            opcode);
        break;
    }

bail:
    return err;
}
/**
 *  This function adds IPL to vlan of l3 interface
 *  to exchange control messages
 *
 * @param[in] data - event data
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_vlan_interface_add(struct peer_conf_event_data *data)
{
    int err = 0;

    ASSERT(data);

    if (!is_inited) {
    	MLAG_BAIL_ERROR_MSG(err, "Add ipl to vlan interface called before init\n");
    }

    /* vlan_id can be 0 when delete peer event accepted */
    if (!(data->vlan_id < VLAN_N_VID)) {
    	MLAG_BAIL_ERROR_MSG(err, "vlan id %d is not valid\n", data->vlan_id);
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "Add ipl to vlan interface %d\n", data->vlan_id);

    ipl_vlan_id = data->vlan_id;

    if (!is_started) {
        MLAG_LOG(MLAG_LOG_NOTICE,
                 "Add ipl to vlan interface %d ignored because called before start\n",
                 ipl_vlan_id);
        goto bail;
    }

    /* Check if IPL is not a member of the vlan */
    if ((ipl_vlan_id != 0) &&
    	(ipl_vlan_list[ipl_vlan_id] == 0)) {

        /* Add IPL to vlan */
        err = mlag_topology_ipl_port_get(0, &ipl_ifindex);
        MLAG_BAIL_ERROR_MSG(err,
        		"Failed to get ipl port data from mlag topology: ipl vlan id=%d, ipl ifindex=%lu, err=%d\n",
        		ipl_vlan_id, ipl_ifindex, err);

        if (ipl_ifindex == 0) {
            goto bail;
        }
        err = sl_api_ipl_vlan_membership_action(OES_ACCESS_CMD_ADD,
                                                ipl_ifindex,
                                                &ipl_vlan_id, 1);
        MLAG_BAIL_ERROR_MSG(err,
        		"Failed to add ipl %lu to vlan interface %d, err %d\n",
        		ipl_ifindex, ipl_vlan_id, err);

        ipl_vlan_list[ipl_vlan_id] = 1;
        mlag_l3_interface_inc_cnt(ADD_IPL_TO_VLAN_EVENTS_SENT);
    }

bail:
    return err;
}
Exemple #7
0
/*
 * Sends notification to reject request
 *
 * @param[in] request - selection request data
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
reject_pending_request(struct lacp_aggregation_message_data *request)
{
    int err = 0;

    MLAG_LOG(MLAG_LOG_DEBUG, "Reject pending request id [%u] port [%lu]\n",
             request->request_id, request->port_id);

    request->is_response = TRUE;
    request->response = LACP_AGGREGATE_DECLINE;

    err = notify_aggregator_selection_response(request);
    MLAG_BAIL_ERROR(err);

    err = lacp_db_pending_request_delete(request->port_id);
    if (err && (err != -ENOENT)) {
        MLAG_BAIL_ERROR_MSG(err,
                            "Failed to clear pending request port [%lu] request [%u]",
                            request->port_id, request->request_id);
    }
    else {
        err = 0;
    }

bail:
    return err;
}
Exemple #8
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;
}
/**
 *  This function inits mlag l3 interface peer sub-module
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_init(void)
{
    int err = 0;
    int i;

    if (is_inited) {
    	err = ECANCELED;
    	MLAG_BAIL_ERROR_MSG(err, "l3 interface peer init called twice\n");
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "l3 interface peer init\n");

    is_inited = 1;
    is_started = 0;
    is_peer_start = 0;
    ipl_ifindex = 0;
    ipl_vlan_id = 0;
    is_master_sync_done = 0;
    for (i = 0; i < VLAN_N_VID; i++) {
        ipl_vlan_list[i] = 0;
    }

bail:
    return err;
}
Exemple #10
0
/*
 *  This function implements LACP selection
 *
 * @param[in] mlag_id - mlag id of requester
 * @param[in] port_id - port ID
 * @param[out] is_free - indicate if aggregator became free
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
lacp_aggregator_free_logic(int mlag_id,
                           unsigned long port_id,
                           int *is_free)
{
    int err = 0;
    int i;
    struct mlag_lacp_data *lacp_data = NULL;
    *is_free = TRUE;

    err = lacp_db_entry_get(port_id, &lacp_data);
    if (err == -ENOENT) {
        /* there is no entry for that port */
        err = 0;
        *is_free = TRUE;
        goto bail;
    }
    /* Update users and ACCEPT request */
    lacp_data->peer_state[mlag_id] = FALSE;
    for (i = 0; i < MLAG_MAX_PEERS; i++) {
        if (lacp_data->peer_state[i] == TRUE) {
            *is_free = FALSE;
        }
    }

    if (*is_free == TRUE) {
        /* delete entry from DB */
        err = lacp_db_entry_delete(port_id);
        MLAG_BAIL_ERROR_MSG(err, "Failed to delete free lacp port [%lu]\n",
                            port_id);
    }

bail:
    return err;
}
Exemple #11
0
/*
 * Clear pending requests from pending queue
 *
 * @param[in] request - struct containing pending request
 * @param[in] data - an optional parameter, not in use
 *
 * @return 0 if operation completes successfully.
 */
static int
clear_pending_request(struct lacp_aggregation_message_data *request,
                      void *data)
{
    int err = 0;
    struct mlag_notification notify;
    UNUSED_PARAM(data);

    ASSERT(request != NULL);

    /* fill notification msg */
    notify.notification_type = MLAG_NOTIFY_AGGREGATOR_RESPONSE;
    notify.notification_info.agg_response.response = LACP_AGGREGATE_DECLINE;
    notify.notification_info.agg_response.request_id = request->request_id;
    notify.notification_info.agg_response.req_partner_id = request->partner_id;
    notify.notification_info.agg_response.req_partner_key =
        request->partner_key;
    notify.notification_info.agg_response.req_port_id = request->port_id;


    err = mlag_notify(&notify);
    MLAG_BAIL_ERROR_MSG(err,
                        "Failed to reject pending port [%lu] req [%u]\n",
                        request->port_id, request->request_id);

bail:
    return err;
}
/**
 *  This function stops mlag l3 interface peer sub-module
 *
 *  @param data - event data
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_stop(uint8_t *data)
{
    int err = 0;
    int i;
    UNUSED_PARAM(data);
    int num_vlans_to_del = 0;

    if (!is_started) {
        goto bail;
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "l3 interface peer manager stop\n");

    /* Check on ipl ifindex validity */
	err = mlag_topology_ipl_port_get(0, &ipl_ifindex);
    MLAG_BAIL_ERROR_MSG(err,
    		"Failed to get ipl data from mlag topology database upon stop, err=%d\n",
    		err);

    if (ipl_ifindex == 0) {
    	goto bail;
    }
    /* Remove IPL from all vlans */
    for (i = 1; i < VLAN_N_VID; i++) {
        if (ipl_vlan_list[i]) {
            /* Remove IPL from vlan */
            ipl_vlan_list[i] = 0;
            sl_vlan_list[num_vlans_to_del++] = i;
            mlag_l3_interface_inc_cnt(DEL_IPL_FROM_VLAN_EVENTS_SENT);
        }
    }

    if (num_vlans_to_del) {
    	err = sl_api_ipl_vlan_membership_action(OES_ACCESS_CMD_DELETE,
    			ipl_ifindex, sl_vlan_list, num_vlans_to_del);
        MLAG_BAIL_ERROR_MSG(err,
        		"Failed to delete ipl vlan membership, err=%d, ipl_ifindex=%lu, num_vlans_to_del=%d\n",
        		err, ipl_ifindex, num_vlans_to_del);
    }

bail:
    is_started = 0;
    return err;
}
Exemple #13
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;
}
Exemple #14
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;
}
Exemple #15
0
/**
 *  This function handles peer state change notification.
 *
 * @param[in] state_change - state  change data
 *
 * @return 0 if operation completes successfully.
 */
int
lacp_manager_peer_state_change(struct peer_state_change_data *state_change)
{
    int err = 0;
    int i;
    struct lacp_peer_down_ports_data peer_down_data;

    MLAG_LOG(MLAG_LOG_NOTICE, "LACP manager peer state change [%d]\n",
             state_change->state);

    if ((started == FALSE) || (lacp_enabled == FALSE)) {
        goto bail;
    }

    if ((current_role == SLAVE) && (state_change->state != HEALTH_PEER_UP)) {
        /* reject all pending requests */
        err = lacp_db_pending_foreach(clear_pending_request, NULL);
        MLAG_BAIL_ERROR_MSG(err,
                            "Failed to reject pending requests on peer down\n");
        /* switch to local LACP logic */
        set_lacp_logic_origin(TRUE);
    }
    if ((current_role == MASTER) && (state_change->state != HEALTH_PEER_UP)) {
        peer_down_data.mlag_id = state_change->mlag_id;
        peer_down_data.port_num = 0;
        /* peer down, clear all active system IDs taken by this peer */
        err = lacp_db_port_foreach(clear_peer, &peer_down_data);
        MLAG_BAIL_ERROR_MSG(err, "Failed to clear peer usage on peer down\n");

        /* clear DB from unused entries */
        for (i = 0; i < peer_down_data.port_num; i++) {
            err = lacp_db_entry_delete(peer_down_data.ports_to_delete[i]);
            MLAG_BAIL_ERROR_MSG(err,
                                "Failed to remove port [%lu] entry on peer down\n",
                                peer_down_data.ports_to_delete[i]);
        }
    }

bail:
    return err;
}
Exemple #16
0
/*
 * Sends notification to reject request
 *
 * @param[in] msg - selection request data
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
notify_aggregator_selection_response(struct lacp_aggregation_message_data *msg)
{
    int err = 0;
    struct lacp_aggregation_message_data *db_req = NULL;
    struct mlag_notification notify;

    /* check if there is a pending request in DB */
    err = lacp_db_pending_request_get(msg->port_id, &db_req);
    if ((err == -ENOENT) || (db_req == NULL) ||
        (db_req->request_id != msg->request_id)) {
        /* no pending request - ignore */
        err = 0;
        MLAG_LOG(MLAG_LOG_DEBUG, "Ignore response port ID [%lu] req ID [%u]\n",
                 msg->port_id, msg->request_id);
        goto bail;
    }
    MLAG_BAIL_ERROR(err);

    /* fill notification msg */
    notify.notification_type = MLAG_NOTIFY_AGGREGATOR_RESPONSE;
    notify.notification_info.agg_response.request_id = msg->request_id;
    notify.notification_info.agg_response.req_partner_id = msg->partner_id;
    notify.notification_info.agg_response.req_partner_key = msg->partner_key;
    notify.notification_info.agg_response.req_port_id = msg->port_id;
    notify.notification_info.agg_response.response = msg->response;

    err = mlag_notify(&notify);
    MLAG_BAIL_ERROR_MSG(err,
                        "Failed to notify response for port [%lu] req [%u]",
                        msg->port_id, msg->request_id);

    err = lacp_db_pending_request_delete(msg->port_id);
    MLAG_BAIL_ERROR_MSG(err,
                        "Failed to clear pending request port [%lu] request [%u]",
                        msg->port_id, msg->request_id);

bail:
    return err;
}
Exemple #17
0
/**
 * Handles a aggregator release
 * This may involve a remote peer,
 *
 * @param[in] request_id - index given by caller that will appear in reply
 * @param[in] port_id - Interface index of port. Must represent MLAG port.
 *
 * @return 0 when successful, otherwise ERROR
 */
int
lacp_manager_aggregator_selection_release(unsigned int request_id,
                                          unsigned long port_id)
{
    int err = 0;
    struct lacp_aggregation_message_data *previous_req = NULL;
    struct lacp_aggregation_message_data selection_req;

    if (lacp_enabled == FALSE) {
        MLAG_LOG(MLAG_LOG_NOTICE,
                 "Request for selection release while LACP disabled\n");
        goto bail;
    }

    /* Expect there is an outstanding request -> reject it */
    err = lacp_db_pending_request_get(port_id, &previous_req);
    if (err && (err != -ENOENT)) {
        MLAG_BAIL_ERROR_MSG(err, "Failed in pending request lookup\n");
    }
    else if (err == 0) {
        /* Found a pending request - drop it */
        err = lacp_db_pending_request_delete(port_id);
        MLAG_BAIL_ERROR_MSG(err,
                            "Failed to delete pending request for port [%lu]",
                            port_id);
    }

    /* prepare selection request */
    selection_req.is_response = FALSE;
    selection_req.request_id = request_id;
    selection_req.port_id = port_id;

    /* send selection request to master logic */
    err = send_release_message(&selection_req);
    MLAG_BAIL_ERROR(err);

bail:
    return err;
}
Exemple #18
0
/*
 * Insert to pending requests queue (according to role)
 *
 * @param[in] request - selection request data
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
update_pending_selection_queue(struct lacp_aggregation_message_data *request)
{
    int err = 0;

    err = lacp_db_pending_request_add(request->port_id, request);
    MLAG_BAIL_ERROR_MSG(err,
                        "Request ID [%u] port [%lu] insertion to pending DB Failed\n",
                        request->request_id, request->port_id);

bail:
    return err;
}
Exemple #19
0
/*
 * Move to use local or remote LACP logic
 *
 * @param[in] use_local - whether to use local LACP logic or not
 *
 */
void
set_lacp_logic_origin(int use_local)
{
    int err = 0;

    use_local_lacp_logic = use_local;

    err = lacp_db_port_clear();
    MLAG_BAIL_ERROR_MSG(err,
                        "Failed to clear LACP selection db on role change\n");
bail:
    return;
}
/**
 *  This function de-inits mlag l3 interface peer sub-module
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_deinit(void)
{
    int err = 0;

    if (!is_inited) {
    	err = ECANCELED;
    	MLAG_BAIL_ERROR_MSG(err, "l3 interface peer deinit called before init\n");
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "l3 interface peer deinit\n");

bail:
    return err;
}
Exemple #21
0
/*
 *  This function is called to handle network order for IBC message
 *
 * @param[in] payload_data - message body
 * @param[in] oper - on send or receive
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
net_order_msg_handler(uint8_t *data, int oper)
{
    int err = 0;
    uint16_t opcode;
    struct peer_lacp_sync_message *lacp_sync;
    struct lacp_aggregator_release_message *rel_msg;
    struct lacp_aggregation_message_data *agg_msg;

    if (oper == MESSAGE_SENDING) {
        opcode = *(uint16_t*)data;
        *(uint16_t*)data = htons(opcode);
    }
    else {
        opcode = ntohs(*(uint16_t*)data);
        *(uint16_t*)data = opcode;
    }

    MLAG_LOG(MLAG_LOG_DEBUG,
             "lacp_manager net_order_msg_handler: opcode=%d\n",
             opcode);

    switch (opcode) {
    case MLAG_LACP_SYNC_MSG:
        lacp_sync = (struct peer_lacp_sync_message *) data;
        net_order_lacp_sync_data(lacp_sync, oper);
        break;
    case MLAG_LACP_SELECTION_EVENT:
        agg_msg = (struct lacp_aggregation_message_data *) data;
        net_order_aggregator_selection_data(agg_msg, oper);
        break;
    case MLAG_LACP_RELEASE_EVENT:
        rel_msg = (struct lacp_aggregator_release_message *) data;
        net_order_aggregator_release_data(rel_msg, oper);
        break;

    default:
        /* Unknown opcode */
        err = -ENOENT;
        MLAG_BAIL_ERROR_MSG(err, "Unknown opcode [%u] in lacp manager\n",
                            opcode);
        break;
    }
bail:
    return err;
}
Exemple #22
0
/*
 * Sends notification to reject request
 *
 * @param[in] msg - selection request data
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
notify_aggregator_release(struct lacp_aggregator_release_message *msg)
{
    int err = 0;
    struct mlag_notification notify;

    notify.notification_type = MLAG_NOTIFY_AGGREGATOR_RELEASE;
    notify.notification_info.agg_release.port_id = msg->port_id;

    /* notify on response */
    err = mlag_notify(&notify);
    MLAG_BAIL_ERROR_MSG(err,
                        "Failed to notify aggregator release for port [%lu]\n",
                        msg->port_id);

bail:
    return err;
}
Exemple #23
0
/**
 *  This function sets IPL port state
 *
 * @param[in] ipl_id - IPL index
 * @param[in] port_state - the IPL port state
 *
 *
 * @return 0 if operation completes successfully.
 * @return -EINVAL if IPL is not defined
 */
int
mlag_topology_ipl_port_state_set(unsigned int ipl_id,
                                 enum oes_port_oper_state port_state)
{
    int err = 0;

    ASSERT(ipl_id < MLAG_MAX_IPLS);

    if (ipl_db[ipl_id].valid == VALID) {
        ipl_db[ipl_id].current_state = port_state;
    }
    else {
        err = -EINVAL;
        MLAG_BAIL_ERROR_MSG(err, "IPL index [%u] not found\n", ipl_id);
    }

bail:
    return err;
}
Exemple #24
0
/**
 *  This function gets IPL peer IP
 *
 * @param[in] ipl_id - IPL index
 * @param[out] peer_ip - the peer IP of the IPL
 *
 *
 * @return 0 if operation completes successfully.
 * @return -EINVAL if IPL is not defined
 */
int
mlag_topology_ipl_peer_ip_get(unsigned int ipl_id, struct oes_ip_addr *peer_ip)
{
    int err = 0;

    ASSERT(ipl_id < MLAG_MAX_IPLS);
    ASSERT(peer_ip != NULL);

    if (ipl_db[ipl_id].valid == VALID) {
        *peer_ip = ipl_db[ipl_id].peer_ip;
    }
    else {
        err = -EINVAL;
        MLAG_BAIL_ERROR_MSG(err, "IPL index [%u] not found\n", ipl_id);
    }

bail:
    return err;
}
Exemple #25
0
/**
 * This function sets IPL local IP.
 *
 * @param[in] ipl_id - IPL index.
 * @param[in] local_ip - the local IP of the IPL.
 *
 * @return 0 - Operation completed successfully.
 * @return -EINVAL if IPL is not defined.
 */
int
mlag_topology_ipl_local_ip_set(unsigned int ipl_id,
                               const struct oes_ip_addr *local_ip)
{
    int err = 0;

    ASSERT(ipl_id < MLAG_MAX_IPLS);

    if (ipl_db[ipl_id].valid == VALID) {
        ipl_db[ipl_id].local_ip = *local_ip;
    }
    else {
        err = -EINVAL;
        MLAG_BAIL_ERROR_MSG(err, "IPL index [%u] not found\n", ipl_id);
    }

bail:
    return err;
}
Exemple #26
0
/**
 * This function sets IPL vlan id.
 *
 * @param[in] ipl_id - IPL index.
 * @param[in] vlan_id - Vlan id of the IPL.
 *
 * @return 0 - Operation completed successfully.
 * @return -EINVAL if IPL is not defined.
 */
int
mlag_topology_ipl_vlan_id_set(unsigned int ipl_id,
                              const unsigned short vlan_id)
{
    int err = 0;

    ASSERT(ipl_id < MLAG_MAX_IPLS);

    if (ipl_db[ipl_id].valid == VALID) {
        ipl_db[ipl_id].vlan_id = vlan_id;
    }
    else {
        err = -EINVAL;
        MLAG_BAIL_ERROR_MSG(err, "IPL index [%u] not found\n", ipl_id);
    }

bail:
    return err;
}
/**
 *  This function handles master sync done event
 *
 * @param[in] data - event data
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_master_sync_done(uint8_t *data)
{
    int err = 0;
    UNUSED_PARAM(data);

    is_master_sync_done = 1;

    MLAG_LOG(MLAG_LOG_NOTICE, "send local vlan oper status trigger\n");

    /* Send query to update local vlans operational states */
    err = sl_api_vlan_oper_status_trigger_get();
    MLAG_BAIL_ERROR_MSG(err,
    		"Failed in local vlan oper status trigger, err=%d\n",
    		err);

bail:
    return err;
}
Exemple #28
0
/*
 *  This function implements LACP selection
 *
 * @param[in] mlag_id - mlag id of requestor
 * @param[in] port_id - port ID
 * @param[in] partner_id - request partner ID
 * @param[out] response - selected or not
 * @param[out] current_partner_id - currently selected partner id
 * @param[out] current_partner_key - currently selected partner key
 *
 * @return 0 when successful, otherwise ERROR
 */
static int
lacp_aggregator_select_logic(int mlag_id,
                             unsigned long port_id,
                             unsigned long long partner_id,
                             unsigned int partner_key,
                             enum aggregate_select_response *response,
                             unsigned long long *current_partner_id,
                             unsigned int *current_partner_key)
{
    int err = 0;
    int i;
    struct mlag_lacp_data *lacp_data = NULL;
    *response = LACP_AGGREGATE_DECLINE;

    MLAG_LOG(MLAG_LOG_INFO,
             "Aggregator select logic for port [%lu] partner [%llu] key [%u]\n",
             port_id, partner_id, partner_key);

    err = lacp_db_entry_get(port_id, &lacp_data);
    if (err == -ENOENT) {
        /* create entry for first entry */
        err = lacp_db_entry_allocate(port_id, &lacp_data);
        MLAG_BAIL_ERROR_MSG(err, "Failed to create lacp entry port [%lu]\n",
                            port_id);
        lacp_data->partner_id = partner_id;
        lacp_data->partner_key = partner_key;
        for (i = 0; i < MLAG_MAX_PEERS; i++) {
            lacp_data->peer_state[i] = FALSE;
        }
    }
    if ((lacp_data->partner_id == partner_id) &&
        (lacp_data->partner_key == partner_key)) {
        /* Update users and ACCEPT request */
        lacp_data->peer_state[mlag_id] = TRUE;
        *response = LACP_AGGREGATE_ACCEPT;
    }
    *current_partner_key = lacp_data->partner_key;
    *current_partner_id = lacp_data->partner_id;

bail:
    return err;
}
/**
 *  This function removes IPL from vlan of l3 interface
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_vlan_interface_del()
{
    int err = 0;

    if (!is_inited) {
    	MLAG_BAIL_ERROR_MSG(err, "Delete ipl from vlan interface called before init\n");
    }

    MLAG_LOG(MLAG_LOG_NOTICE, "Delete ipl from vlan interface: ipl_vlan_id=%d\n",
    		 ipl_vlan_id);

    /* Check if IPL is not a member of the vlan */
    if ((ipl_vlan_id != 0) &&
    	(ipl_vlan_list[ipl_vlan_id] == 1)) {
        ipl_vlan_list[ipl_vlan_id] = 0;
    }

bail:
    return err;
}
/**
 *  This function handles peer start event
 *
 * @param[in] data - event data
 *
 * @return 0 when successful, otherwise ERROR
 */
int
mlag_l3_interface_peer_peer_start(struct peer_state_change_data *data)
{
    int err = 0;
    struct sync_event_data ev;

    MLAG_LOG(MLAG_LOG_NOTICE,
             "Sending MLAG_L3_SYNC_START_EVENT to master logic\n");

    is_peer_start = 1;

    /* Send MLAG_SYNC_START_EVENT event to Master Logic */
    ev.peer_id = data->mlag_id;
    ev.state = 0;
    err = mlag_dispatcher_message_send(MLAG_L3_SYNC_START_EVENT, &ev,
                                       sizeof(ev), MASTER_PEER_ID,
                                       PEER_MANAGER);
    MLAG_BAIL_ERROR_MSG(err,
    		"Failed in sending MLAG_L3_SYNC_START_EVENT, err=%d\n",
    		err);

bail:
    return err;
}