diff options
author | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2005-11-27 09:27:15 +0000 |
---|---|---|
committer | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2005-11-27 09:27:15 +0000 |
commit | 18a1691e9e1699c22823ccb665712ee9a7c6f83f (patch) | |
tree | c2e44d8b287197747edbd85e16d164a32307333d | |
parent | 24d821b4bdeaecda24d55cf921d4b6c31c1160a2 (diff) |
Make the trunk interface link state depend on the link states of the
trunkports (link is UP as long as at least one of the trunkports is up)
ok reyk@
-rw-r--r-- | sys/net/if_trunk.c | 56 | ||||
-rw-r--r-- | sys/net/if_trunk.h | 3 |
2 files changed, 49 insertions, 10 deletions
diff --git a/sys/net/if_trunk.c b/sys/net/if_trunk.c index 5e84069799c..554c0fa6357 100644 --- a/sys/net/if_trunk.c +++ b/sys/net/if_trunk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_trunk.c,v 1.10 2005/10/23 14:07:11 mpf Exp $ */ +/* $OpenBSD: if_trunk.c,v 1.11 2005/11/27 09:27:14 mcbride Exp $ */ /* * Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net> @@ -61,6 +61,7 @@ void trunk_port_lladdr(struct trunk_port *, u_int8_t *); int trunk_port_create(struct trunk_softc *, struct ifnet *); int trunk_port_destroy(struct trunk_port *); void trunk_port_watchdog(struct ifnet *); +void trunk_port_state(void *); int trunk_port_ioctl(struct ifnet *, u_long, caddr_t); struct trunk_port *trunk_port_get(struct trunk_softc *, struct ifnet *); int trunk_port_checkstacking(struct trunk_softc *); @@ -347,6 +348,10 @@ trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp) /* Add multicast addresses to this port */ trunk_ether_cmdmulti(tp, SIOCADDMULTI); + /* Register callback for physical link state changes */ + tp->lh_cookie = hook_establish(ifp->if_linkstatehooks, 1, + trunk_port_state, tp); + if (tr->tr_port_create != NULL) error = (*tr->tr_port_create)(tp); @@ -395,6 +400,8 @@ trunk_port_destroy(struct trunk_port *tp) ifp->if_ioctl = tp->tp_ioctl; ifp->if_tp = NULL; + hook_disestablish(ifp->if_linkstatehooks, tp->lh_cookie); + /* Finally, remove the port from the trunk */ SLIST_REMOVE(&tr->tr_ports, tp, trunk_port, tp_entries); tr->tr_count--; @@ -960,10 +967,26 @@ trunk_media_status(struct ifnet *ifp, struct ifmediareq *imr) imr->ifm_status |= IFM_ACTIVE; } +void +trunk_port_state(void *v) +{ + struct trunk_port *tp = v; + struct trunk_softc *tr; + + if (v) + tr = (struct trunk_softc *)tp->tp_trunk; + + if (!tr) + return; + + trunk_link_active(tr, tp); +} + struct trunk_port * trunk_link_active(struct trunk_softc *tr, struct trunk_port *tp) { - struct trunk_port *tp_next; + struct trunk_port *tp_next, *rval = NULL; + int new_link = LINK_STATE_UP; /* * Search a port which reports an active link state. @@ -975,19 +998,34 @@ trunk_link_active(struct trunk_softc *tr, struct trunk_port *tp) if (tp == NULL) goto search; - if (tp->tp_link_state != LINK_STATE_DOWN) - return (tp); + if (tp->tp_link_state != LINK_STATE_DOWN) { + rval = tp; + goto found; + } if ((tp_next = SLIST_NEXT(tp, tp_entries)) != NULL && - tp_next->tp_link_state != LINK_STATE_DOWN) - return (tp_next); + tp_next->tp_link_state != LINK_STATE_DOWN) { + rval = tp_next; + goto found; + } search: SLIST_FOREACH(tp_next, &tr->tr_ports, tp_entries) { - if (tp_next->tp_link_state != LINK_STATE_DOWN) - return (tp_next); + if (tp_next->tp_link_state != LINK_STATE_DOWN) { + rval = tp_next; + goto found; + } } - return (NULL); + found: + if (rval == NULL) + new_link = LINK_STATE_DOWN; + + if (tr->tr_ac.ac_if.if_link_state != new_link) { + tr->tr_ac.ac_if.if_link_state = new_link; + if_link_state_change(&tr->tr_ac.ac_if); + } + + return (rval); } /* diff --git a/sys/net/if_trunk.h b/sys/net/if_trunk.h index 1de55a7b0fd..aff18863601 100644 --- a/sys/net/if_trunk.h +++ b/sys/net/if_trunk.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_trunk.h,v 1.4 2005/10/03 01:46:47 reyk Exp $ */ +/* $OpenBSD: if_trunk.h,v 1.5 2005/11/27 09:27:14 mcbride Exp $ */ /* * Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net> @@ -98,6 +98,7 @@ struct trunk_port { u_char tp_iftype; /* interface type */ u_int32_t tp_prio; /* port priority */ u_int32_t tp_flags; /* port flags */ + void *lh_cookie; /* if state hook */ /* Redirected callbacks */ void (*tp_watchdog)(struct ifnet *); |