Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LACP Mode Support for LAG #79

Merged
merged 4 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 211 additions & 12 deletions switchapi/es2k/switch_lag.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,78 @@ switch_status_t switch_api_lag_update(const switch_device_t device,
status = switch_lag_get(device, lag_h, &lag_info);
CHECK_RET(status != SWITCH_STATUS_SUCCESS, status);

if (lag_info->api_lag_info.bond_mode == SWITCHAPI_BOND_MODE_ACTIVE_BACKUP) {
if (!SWITCH_LAG_MEMBER_HANDLE(lag_member_h)) {
status = SWITCH_STATUS_INVALID_PARAMETER;
krnlmon_log_error(
"LAG get: Invalid LAG member handle on device %d, "
"LAG member handle 0x%lx: "
"error: %s\n",
device, lag_member_h, switch_error_to_string(status));
return status;
}
status = switch_lag_member_get(device, lag_member_h, &lag_member_info);
CHECK_RET(status != SWITCH_STATUS_SUCCESS, status);

if (lag_info->active_lag_member != 0) {
// delete rx path
status = switch_pd_rx_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete rx_lag_table entry on device %d: "
",error: %s\n",
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
device, switch_error_to_string(status));
return status;
}

// insert lag member
status = SWITCH_LIST_INSERT(&(lag_info->lag_members),
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
&(lag_member_info->node), lag_member_info);
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);

// create rx path
status = switch_pd_rx_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create rx_lag_table entry on device %d: "
",error: %s\n",
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
device, switch_error_to_string(status));
return status;
}
} else {
// update lag members list with the lag_member_h
status = SWITCH_LIST_INSERT(&(lag_info->lag_members),
&(lag_member_info->node), lag_member_info);
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);
}
}

return status;
}

/**
* Routine Description:
* @brief On change of oper_state of a LAG member,
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
* update the number of active ports of a LAG and
* re-populate the Tx and Rx LAG table entries with
* active port.
*
* Arguments:
* @param[in] device - device
* @param[in] lag_member_h - LAG member handle
* @param[in] oper_state - oper state of LAG member
*
* Return Values:
* @return SWITCH_STATUS_SUCCESS on success
* Failure status code on error
*/
switch_status_t switch_api_lag_member_update(const switch_device_t device,
const switch_handle_t lag_member_h,
bool oper_state) {
switch_lag_info_t* lag_info = NULL;
switch_lag_member_info_t* lag_member_info = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;

if (!SWITCH_LAG_MEMBER_HANDLE(lag_member_h)) {
status = SWITCH_STATUS_INVALID_PARAMETER;
krnlmon_log_error(
Expand All @@ -296,36 +368,163 @@ switch_status_t switch_api_lag_update(const switch_device_t device,
status = switch_lag_member_get(device, lag_member_h, &lag_member_info);
CHECK_RET(status != SWITCH_STATUS_SUCCESS, status);

if (lag_info->active_lag_member != 0) {
// delete rx path
status = switch_pd_rx_lag_table_entry(device, lag_info, false);
lag_member_info->api_lag_member_info.oper_state = oper_state;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You update oper_state before you've validated lag_h or tried to fetch lag_info.

Will the lag member be in a valid state if any of the following calls does a return on error?


switch_handle_t lag_h = lag_member_info->api_lag_member_info.lag_h;

if (!SWITCH_LAG_HANDLE(lag_h)) {
status = SWITCH_STATUS_INVALID_PARAMETER;
krnlmon_log_error(
"LAG get: Invalid LAG handle on device %d, "
"LAG handle 0x%lx: "
"error: %s\n",
device, lag_h, switch_error_to_string(status));
return status;
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
}
status = switch_lag_get(device, lag_h, &lag_info);
CHECK_RET(status != SWITCH_STATUS_SUCCESS, status);
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved

// update the active num ports of LAG
if (oper_state)
lag_info->active_num_ports++;
else
lag_info->active_num_ports--;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. What prevents lag_info->active_num_ports from "going negative" (wrapping to 0xff, 0xfe, etc.)?
  2. You've changed the number of active ports. Will the system be in a valid state if one of the succeeding calls returns on error?


if (lag_info->active_num_ports == 0 &&
(SWITCH_LIST_COUNT(&lag_info->lag_members) != 0)) {
// delete the existing tx and rx entries
status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete rx_lag_table entry on device %d: "
"Failed to delete tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
}

// insert lag member
status = SWITCH_LIST_INSERT(&(lag_info->lag_members),
&(lag_member_info->node), lag_member_info);
status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
}

// delete the lag_member from the LAG
status =
SWITCH_LIST_DELETE(&(lag_info->lag_members), &(lag_member_info->node));
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);

// create rx path
status = switch_pd_rx_lag_table_entry(device, lag_info, true);
} else if (lag_info->active_num_ports == 1) {
// from 2->1:oper_state is false or 0->1:oper_state is true
aashishkuma marked this conversation as resolved.
Show resolved Hide resolved
if (oper_state) {
// populate the tx and rx entries with single active member
status = SWITCH_LIST_INSERT(&(lag_info->lag_members),
&(lag_member_info->node), lag_member_info);
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);
status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}
} else {
// delete the existing entries and populate the tx and rx entries with
// other active member
status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = SWITCH_LIST_DELETE(&(lag_info->lag_members),
&(lag_member_info->node));
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);

status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}
}
} else if (lag_info->active_num_ports == 2) {
// delete the existing entries and re-distribute
// table entries between both active ports
status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create rx_lag_table entry on device %d: "
"Failed to delete tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, false);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to delete rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}
} else {
// update lag members list with the lag_member_h

status = SWITCH_LIST_INSERT(&(lag_info->lag_members),
&(lag_member_info->node), lag_member_info);
SWITCH_ASSERT(status == SWITCH_STATUS_SUCCESS);

status = switch_pd_tx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create tx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}

status = switch_pd_rx_lacp_lag_table_entry(device, lag_info, true);
if (status != SWITCH_STATUS_SUCCESS) {
krnlmon_log_error(
"Failed to create rx_lacp_lag_table entry on device %d: "
",error: %s\n",
device, switch_error_to_string(status));
return status;
}
}

return status;
Expand Down
Loading