19cd2d7a5SSteven/*
29cd2d7a5SSteven * Copyright (c) 2017 Cisco and/or its affiliates.
39cd2d7a5SSteven * Licensed under the Apache License, Version 2.0 (the "License");
49cd2d7a5SSteven * you may not use this file except in compliance with the License.
59cd2d7a5SSteven * You may obtain a copy of the License at:
69cd2d7a5SSteven *
79cd2d7a5SSteven *     http://www.apache.org/licenses/LICENSE-2.0
89cd2d7a5SSteven *
99cd2d7a5SSteven * Unless required by applicable law or agreed to in writing, software
109cd2d7a5SSteven * distributed under the License is distributed on an "AS IS" BASIS,
119cd2d7a5SSteven * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129cd2d7a5SSteven * See the License for the specific language governing permissions and
139cd2d7a5SSteven * limitations under the License.
149cd2d7a5SSteven */
159cd2d7a5SSteven
169cd2d7a5SSteven#include <stdint.h>
179cd2d7a5SSteven#include <vlib/vlib.h>
189cd2d7a5SSteven#include <vlib/unix/unix.h>
199cd2d7a5SSteven#include <vnet/bonding/node.h>
209cd2d7a5SSteven#include <lacp/node.h>
219cd2d7a5SSteven
229cd2d7a5SStevenstatic void
239cd2d7a5SStevenlacp_set_port_selected (vlib_main_t * vm, slave_if_t * sif)
249cd2d7a5SSteven{
259cd2d7a5SSteven  /* Handle loopback port */
269cd2d7a5SSteven  if (!memcmp (sif->partner.system, sif->actor.system, 6) &&
279cd2d7a5SSteven      (sif->partner.key == sif->actor.key))
289cd2d7a5SSteven    {
299cd2d7a5SSteven      sif->loopback_port = 1;
309cd2d7a5SSteven      sif->actor.state &= ~LACP_STATE_AGGREGATION;
319cd2d7a5SSteven    }
329cd2d7a5SSteven  sif->selected = LACP_PORT_SELECTED;
339cd2d7a5SSteven
349cd2d7a5SSteven  switch (sif->mux_state)
359cd2d7a5SSteven    {
369cd2d7a5SSteven    case LACP_MUX_STATE_DETACHED:
379cd2d7a5SSteven      break;
389cd2d7a5SSteven    case LACP_MUX_STATE_WAITING:
399cd2d7a5SSteven      if (!sif->ready)
409cd2d7a5SSteven	return;
419cd2d7a5SSteven      break;
429cd2d7a5SSteven    case LACP_MUX_STATE_ATTACHED:
439cd2d7a5SSteven      if (!(sif->partner.state & LACP_STATE_SYNCHRONIZATION))
449cd2d7a5SSteven	return;
459cd2d7a5SSteven      break;
469cd2d7a5SSteven    case LACP_MUX_STATE_COLLECTING_DISTRIBUTING:
479cd2d7a5SSteven      break;
489cd2d7a5SSteven    default:
499cd2d7a5SSteven      break;
509cd2d7a5SSteven    }
519cd2d7a5SSteven  lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_SELECTED,
529cd2d7a5SSteven			 &sif->mux_state);
539cd2d7a5SSteven}
549cd2d7a5SSteven
559cd2d7a5SStevenvoid
569cd2d7a5SStevenlacp_selection_logic (vlib_main_t * vm, slave_if_t * sif)
579cd2d7a5SSteven{
589cd2d7a5SSteven  slave_if_t *sif2;
599cd2d7a5SSteven  bond_if_t *bif;
609cd2d7a5SSteven  u32 *sw_if_index;
619cd2d7a5SSteven
629cd2d7a5SSteven  bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
639cd2d7a5SSteven  vec_foreach (sw_if_index, bif->slaves)
649cd2d7a5SSteven  {
659cd2d7a5SSteven    sif2 = bond_get_slave_by_sw_if_index (*sw_if_index);
669cd2d7a5SSteven    if (sif2 && (sif2->actor.state & LACP_STATE_SYNCHRONIZATION) &&
679cd2d7a5SSteven	(sif2->ready_n == 0))
689cd2d7a5SSteven      goto out;
699cd2d7a5SSteven  }
709cd2d7a5SSteven
719cd2d7a5SSteven  vec_foreach (sw_if_index, bif->slaves)
729cd2d7a5SSteven  {
739cd2d7a5SSteven    sif2 = bond_get_slave_by_sw_if_index (*sw_if_index);
749cd2d7a5SSteven    if (sif2)
759cd2d7a5SSteven      {
769cd2d7a5SSteven	sif2->ready = 1;
779cd2d7a5SSteven	if (sif2->selected == LACP_PORT_SELECTED)
789cd2d7a5SSteven	  lacp_machine_dispatch (&lacp_mux_machine, vm, sif2,
799cd2d7a5SSteven				 LACP_MUX_EVENT_READY, &sif2->mux_state);
809cd2d7a5SSteven      }
819cd2d7a5SSteven  }
829cd2d7a5SStevenout:
839cd2d7a5SSteven  lacp_set_port_selected (vm, sif);
849cd2d7a5SSteven}
859cd2d7a5SSteven
869cd2d7a5SSteven/*
879cd2d7a5SSteven * fd.io coding-style-patch-verification: ON
889cd2d7a5SSteven *
899cd2d7a5SSteven * Local Variables:
909cd2d7a5SSteven * eval: (c-set-style "gnu")
919cd2d7a5SSteven * End:
929cd2d7a5SSteven */
93