summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2005-11-27 09:27:15 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2005-11-27 09:27:15 +0000
commit18a1691e9e1699c22823ccb665712ee9a7c6f83f (patch)
treec2e44d8b287197747edbd85e16d164a32307333d
parent24d821b4bdeaecda24d55cf921d4b6c31c1160a2 (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.c56
-rw-r--r--sys/net/if_trunk.h3
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 *);