/* * Copyright (c) 2017 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include static int lacp_set_port_selected (vlib_main_t *vm, bond_if_t *bif, member_if_t *mif) { uword p; member_if_t *mif2; /* Handle loopback port */ if (!memcmp (mif->partner.system, mif->actor.system, 6) && (mif->partner.key == mif->actor.key)) { mif->loopback_port = 1; mif->actor.state &= ~LACP_STATE_AGGREGATION; mif->selected = LACP_PORT_UNSELECTED; lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_UNSELECTED, &mif->mux_state); return LACP_ERROR_LOOPBACK_PORT; } if (vec_len (bif->active_members)) { p = *vec_elt_at_index (bif->active_members, 0); mif2 = bond_get_member_by_sw_if_index (p); if (mif2 && ((mif2->partner.key != mif->partner.key) || memcmp (mif2->partner.system, mif->partner.system, 6))) { mif->selected = LACP_PORT_UNSELECTED; lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_UNSELECTED, &mif->mux_state); return LACP_ERROR_BAD_KEY; } } mif->selected = LACP_PORT_SELECTED; switch (mif->mux_state) { case LACP_MUX_STATE_DETACHED: break; case LACP_MUX_STATE_WAITING: if (!mif->ready) return LACP_ERROR_NONE; break; case LACP_MUX_STATE_ATTACHED: if (!(mif->partner.state & LACP_STATE_SYNCHRONIZATION)) return LACP_ERROR_NONE; break; case LACP_MUX_STATE_COLLECTING_DISTRIBUTING: break; default: break; } return lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_SELECTED, &mif->mux_state); } int lacp_selection_logic (vlib_main_t *vm, member_if_t *mif) { member_if_t *mif2; bond_if_t *bif; u32 *sw_if_index; bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance); vec_foreach (sw_if_index, bif->members) { mif2 = bond_get_member_by_sw_if_index (*sw_if_index); if (mif2 && (mif2->actor.state & LACP_STATE_SYNCHRONIZATION) && (mif2->ready_n == 0)) goto out; } vec_foreach (sw_if_index, bif->members) { mif2 = bond_get_member_by_sw_if_index (*sw_if_index); if (mif2) { mif2->ready = 1; if (mif2->selected == LACP_PORT_SELECTED) lacp_machine_dispatch (&lacp_mux_machine, vm, mif2, LACP_MUX_EVENT_READY, &mif2->mux_state); } } out: return lacp_set_port_selected (vm, bif, mif); } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */