Home | History | Annotate | Line # | Download | only in agr
ieee8023ad_lacp_sm_rx.c revision 1.1
      1 /*	$NetBSD: ieee8023ad_lacp_sm_rx.c,v 1.1 2005/03/18 11:11:50 yamt Exp $	*/
      2 
      3 /*-
      4  * Copyright (c)2005 YAMAMOTO Takashi,
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: ieee8023ad_lacp_sm_rx.c,v 1.1 2005/03/18 11:11:50 yamt Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/mbuf.h>
     34 #include <sys/systm.h>
     35 
     36 #include <net/if.h>
     37 #include <net/if_ether.h>
     38 
     39 #include <net/agr/ieee8023_slowprotocols.h>
     40 #include <net/agr/ieee8023_tlv.h>
     41 #include <net/agr/ieee8023ad_lacp.h>
     42 #include <net/agr/ieee8023ad_lacp_impl.h>
     43 #include <net/agr/ieee8023ad_lacp_sm.h>
     44 #include <net/agr/ieee8023ad_lacp_debug.h>
     45 
     46 /* receive machine */
     47 
     48 static void lacp_sm_rx_update_ntt(struct lacp_port *, const struct lacpdu *);
     49 static void lacp_sm_rx_record_pdu(struct lacp_port *, const struct lacpdu *);
     50 static void lacp_sm_rx_update_selected(struct lacp_port *, const struct lacpdu *);
     51 
     52 static void lacp_sm_rx_record_default(struct lacp_port *);
     53 static void lacp_sm_rx_update_default_selected(struct lacp_port *);
     54 
     55 static void lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *,
     56     const struct lacp_peerinfo *);
     57 
     58 /*
     59  * partner administration variables.
     60  * XXX should be configurable.
     61  */
     62 
     63 static const struct lacp_peerinfo lacp_partner_admin = {
     64 	.lip_systemid = { .lsi_prio = 0xffff },
     65 	.lip_portid = { .lpi_prio = 0xffff },
     66 #if 1
     67 	/* optimistic */
     68 	.lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION |
     69 	    LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING,
     70 #else
     71 	/* pessimistic */
     72 	.lip_state = 0,
     73 #endif
     74 };
     75 
     76 void
     77 lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du)
     78 {
     79 	int timeout;
     80 
     81 	/*
     82 	 * check LACP_DISABLED first
     83 	 */
     84 
     85 	if (!(lp->lp_state & LACP_STATE_AGGREGATION)) {
     86 		return;
     87 	}
     88 
     89 	/*
     90 	 * check loopback condition.
     91 	 */
     92 
     93 	if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid,
     94 	    &lp->lp_actor.lip_systemid)) {
     95 		return;
     96 	}
     97 
     98 	/*
     99 	 * EXPIRED, DEFAULTED, CURRENT -> CURRENT
    100 	 */
    101 
    102 	lacp_sm_rx_update_selected(lp, du);
    103 	lacp_sm_rx_update_ntt(lp, du);
    104 	lacp_sm_rx_record_pdu(lp, du);
    105 
    106 	timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ?
    107 	    LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME;
    108 	LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout);
    109 
    110 	lp->lp_state &= ~LACP_STATE_EXPIRED;
    111 
    112 	/*
    113 	 * kick transmit machine without waiting the next tick.
    114 	 */
    115 
    116 	lacp_sm_tx(lp);
    117 }
    118 
    119 void
    120 lacp_sm_rx_set_expired(struct lacp_port *lp)
    121 {
    122 
    123 	lp->lp_partner.lip_state &= ~LACP_STATE_SYNC;
    124 	lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT;
    125 	LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME);
    126 	lp->lp_state |= LACP_STATE_EXPIRED;
    127 }
    128 
    129 void
    130 lacp_sm_rx_timer(struct lacp_port *lp)
    131 {
    132 
    133 	if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) {
    134 		/* CURRENT -> EXPIRED */
    135 		LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__));
    136 		lacp_sm_rx_set_expired(lp);
    137 	} else {
    138 		/* EXPIRED -> DEFAULTED */
    139 		LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__));
    140 		lacp_sm_rx_update_default_selected(lp);
    141 		lacp_sm_rx_record_default(lp);
    142 		lp->lp_state &= ~LACP_STATE_EXPIRED;
    143 	}
    144 }
    145 
    146 static void
    147 lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du)
    148 {
    149 	boolean_t active;
    150 	uint8_t oldpstate;
    151 #if defined(LACP_DEBUG)
    152 	char buf[LACP_STATESTR_MAX+1];
    153 #endif
    154 
    155 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    156 
    157 	oldpstate = lp->lp_partner.lip_state;
    158 
    159 	active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY)
    160 	    || ((lp->lp_state & LACP_STATE_ACTIVITY) &&
    161 	    (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY));
    162 
    163 	lp->lp_partner = du->ldu_actor;
    164 	if (active &&
    165 	    ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state,
    166 	    LACP_STATE_AGGREGATION) &&
    167 	    !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner))
    168 	    || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) {
    169 		/* nothing */
    170 	} else {
    171 		lp->lp_partner.lip_state &= ~LACP_STATE_SYNC;
    172 	}
    173 
    174 	lp->lp_state &= ~LACP_STATE_DEFAULTED;
    175 
    176 	LACP_DPRINTF((lp, "old pstate %s\n",
    177 	    lacp_format_state(oldpstate, buf, sizeof(buf))));
    178 	LACP_DPRINTF((lp, "new pstate %s\n",
    179 	    lacp_format_state(lp->lp_partner.lip_state, buf, sizeof(buf))));
    180 
    181 	lacp_sm_ptx_update_timeout(lp, oldpstate);
    182 }
    183 
    184 static void
    185 lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du)
    186 {
    187 
    188 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    189 
    190 	if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) ||
    191 	    !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state,
    192 	    LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) {
    193 		LACP_DPRINTF((lp, "%s: assert ntt\n", __func__));
    194 		lacp_sm_assert_ntt(lp);
    195 	}
    196 }
    197 
    198 static void
    199 lacp_sm_rx_record_default(struct lacp_port *lp)
    200 {
    201 	uint8_t oldpstate;
    202 
    203 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    204 
    205 	oldpstate = lp->lp_partner.lip_state;
    206 	lp->lp_partner = lacp_partner_admin;
    207 	lp->lp_state |= LACP_STATE_DEFAULTED;
    208 	lacp_sm_ptx_update_timeout(lp, oldpstate);
    209 }
    210 
    211 static void
    212 lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp,
    213     const struct lacp_peerinfo *info)
    214 {
    215 
    216 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    217 
    218 	if (lacp_compare_peerinfo(&lp->lp_partner, info) ||
    219 	    !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state,
    220 	    LACP_STATE_AGGREGATION)) {
    221 		lp->lp_selected = LACP_UNSELECTED;
    222 		/* mux machine will clean up lp->lp_aggregator */
    223 	}
    224 }
    225 
    226 static void
    227 lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du)
    228 {
    229 
    230 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    231 
    232 	lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor);
    233 }
    234 
    235 static void
    236 lacp_sm_rx_update_default_selected(struct lacp_port *lp)
    237 {
    238 
    239 	/* LACP_DPRINTF((lp, "%s\n", __func__)); */
    240 
    241 	lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin);
    242 }
    243