summaryrefslogtreecommitdiff
path: root/sys/net/if_trunk.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-10-03 01:46:48 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-10-03 01:46:48 +0000
commitf2e709e247aad62c71e9107297739e4fdb223379 (patch)
treeccacbcaf2c781a525b32ab27ad6f0987d1478f0f /sys/net/if_trunk.c
parent84269b03d0035bb44926b61b424d74e47ff04c57 (diff)
add a simple active "failover" trunk mode. port priorities will be
added later, currently the master port will always be the default (active) port and the the next active port will be used as the failover port. ok brad@
Diffstat (limited to 'sys/net/if_trunk.c')
-rw-r--r--sys/net/if_trunk.c142
1 files changed, 123 insertions, 19 deletions
diff --git a/sys/net/if_trunk.c b/sys/net/if_trunk.c
index 77ed66c1ecf..41b1ab96c4f 100644
--- a/sys/net/if_trunk.c
+++ b/sys/net/if_trunk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_trunk.c,v 1.7 2005/09/14 08:07:24 reyk Exp $ */
+/* $OpenBSD: if_trunk.c,v 1.8 2005/10/03 01:46:47 reyk Exp $ */
/*
* Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net>
@@ -55,8 +55,9 @@ extern int ifqmaxlen;
void trunkattach(int);
int trunk_clone_create(struct if_clone *, int);
int trunk_clone_destroy(struct ifnet *);
-void trunk_lladdr(struct trunk_softc *, u_int8_t *);
+void trunk_lladdr(struct arpcom *, u_int8_t *);
int trunk_capabilities(struct trunk_softc *);
+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 *);
@@ -85,16 +86,23 @@ int trunk_rr_attach(struct trunk_softc *);
int trunk_rr_detach(struct trunk_softc *);
void trunk_rr_port_destroy(struct trunk_port *);
int trunk_rr_start(struct trunk_softc *, struct mbuf *);
-int trunk_rr_watchdog(struct trunk_softc *);
int trunk_rr_input(struct trunk_softc *, struct trunk_port *,
struct ether_header *, struct mbuf *);
+/* Active failover */
+int trunk_fail_attach(struct trunk_softc *);
+int trunk_fail_detach(struct trunk_softc *);
+int trunk_fail_start(struct trunk_softc *, struct mbuf *);
+int trunk_fail_input(struct trunk_softc *, struct trunk_port *,
+ struct ether_header *, struct mbuf *);
+
/* Trunk protocol table */
static const struct {
enum trunk_proto ti_proto;
int (*ti_attach)(struct trunk_softc *);
} trunk_protos[] = {
{ TRUNK_PROTO_ROUNDROBIN, trunk_rr_attach },
+ { TRUNK_PROTO_FAILOVER, trunk_fail_attach },
{ TRUNK_PROTO_NONE, }
};
@@ -204,9 +212,9 @@ trunk_clone_destroy(struct ifnet *ifp)
}
void
-trunk_lladdr(struct trunk_softc *tr, u_int8_t *lladdr)
+trunk_lladdr(struct arpcom *ac, u_int8_t *lladdr)
{
- struct ifnet *ifp = &tr->tr_ac.ac_if;
+ struct ifnet *ifp = &ac->ac_if;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
@@ -215,7 +223,7 @@ trunk_lladdr(struct trunk_softc *tr, u_int8_t *lladdr)
sdl->sdl_type = IFT_ETHER;
sdl->sdl_alen = ETHER_ADDR_LEN;
bcopy(lladdr, LLADDR(sdl), ETHER_ADDR_LEN);
- bcopy(lladdr, tr->tr_ac.ac_enaddr, ETHER_ADDR_LEN);
+ bcopy(lladdr, ac->ac_enaddr, ETHER_ADDR_LEN);
}
int
@@ -235,6 +243,32 @@ trunk_capabilities(struct trunk_softc *tr)
return (cap == ~0 ? 0 : cap);
}
+void
+trunk_port_lladdr(struct trunk_port *tp, u_int8_t *lladdr)
+{
+ struct ifnet *ifp = tp->tp_if;
+ struct ifaddr *ifa;
+ struct ifreq ifr;
+
+ /* Set the link layer address */
+ trunk_lladdr((struct arpcom *)ifp, lladdr);
+
+ /* Reset the port to update the lladdr */
+ if (ifp->if_flags & IFF_UP) {
+ int s = splimp();
+ ifp->if_flags &= ~IFF_UP;
+ (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+ ifp->if_flags |= IFF_UP;
+ (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+ splx(s);
+ TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+ if (ifa->ifa_addr != NULL &&
+ ifa->ifa_addr->sa_family == AF_INET)
+ arp_ifinit((struct arpcom *)ifp, ifa);
+ }
+ }
+}
+
int
trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
{
@@ -291,13 +325,19 @@ trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
tp->tp_if = ifp;
tp->tp_trunk = (caddr_t)tr;
+ /* Save port link layer address */
+ bcopy(((struct arpcom *)ifp)->ac_enaddr, tp->tp_lladdr, ETHER_ADDR_LEN);
+
if (SLIST_EMPTY(&tr->tr_ports)) {
tr->tr_primary = tp;
tp->tp_flags |= TRUNK_PORT_MASTER;
- trunk_lladdr(tr, ((struct arpcom *)ifp)->ac_enaddr);
+ trunk_lladdr(&tr->tr_ac, tp->tp_lladdr);
}
- /* Insert into the global list of trunks */
+ /* Update link layer address for this port */
+ trunk_port_lladdr(tp, tr->tr_primary->tp_lladdr);
+
+ /* Insert into the list of ports */
SLIST_INSERT_HEAD(&tr->tr_ports, tp, tp_entries);
tr->tr_count++;
@@ -361,18 +401,26 @@ trunk_port_destroy(struct trunk_port *tp)
/* Update the primary interface */
if (tp == tr->tr_primary) {
+ u_int8_t lladdr[ETHER_ADDR_LEN];
+
if ((tp_ptr = SLIST_FIRST(&tr->tr_ports)) == NULL) {
- u_int8_t lladdr[ETHER_ADDR_LEN];
bzero(&lladdr, ETHER_ADDR_LEN);
- trunk_lladdr(tr, lladdr);
} else {
- trunk_lladdr(tr,
- ((struct arpcom *)tp_ptr->tp_if)->ac_enaddr);
+ bcopy(((struct arpcom *)tp_ptr->tp_if)->ac_enaddr,
+ lladdr, ETHER_ADDR_LEN);
tp_ptr->tp_flags = TRUNK_PORT_MASTER;
}
+ trunk_lladdr(&tr->tr_ac, lladdr);
tr->tr_primary = tp_ptr;
+
+ /* Update link layer address for each port */
+ SLIST_FOREACH(tp_ptr, &tr->tr_ports, tp_entries)
+ trunk_port_lladdr(tp_ptr, lladdr);
}
+ /* Reset the port lladdr */
+ trunk_port_lladdr(tp, tp->tp_lladdr);
+
free(tp, M_DEVBUF);
/* Update trunk capabilities */
@@ -394,9 +442,6 @@ trunk_port_watchdog(struct ifnet *ifp)
(tr = (struct trunk_softc *)tp->tp_trunk) == NULL)
return;
- if (tr->tr_ifflags & IFF_DEBUG)
- printf("%s\n", __func__);
-
if (tp->tp_watchdog != NULL)
(*tp->tp_watchdog)(ifp);
}
@@ -489,7 +534,10 @@ trunk_port2req(struct trunk_port *tp, struct trunk_reqport *rp)
struct trunk_softc *tr = (struct trunk_softc *)tp->tp_trunk;
strlcpy(rp->rp_ifname, tr->tr_ifname, sizeof(rp->rp_ifname));
strlcpy(rp->rp_portname, tp->tp_if->if_xname, sizeof(rp->rp_portname));
+ rp->rp_prio = tp->tp_prio;
rp->rp_flags = tp->tp_flags;
+ if (tp->tp_link_state != LINK_STATE_DOWN)
+ rp->rp_flags |= TRUNK_PORT_ACTIVE;
}
int
@@ -636,6 +684,11 @@ trunk_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &tr->tr_media, cmd);
break;
+ case SIOCSIFLLADDR:
+ /* Update the port lladdrs as well */
+ SLIST_FOREACH(tp, &tr->tr_ports, tp_entries)
+ trunk_port_lladdr(tp, ifr->ifr_addr.sa_data);
+ break;
default:
error = EINVAL;
break;
@@ -1002,16 +1055,67 @@ trunk_rr_start(struct trunk_softc *tr, struct mbuf *m)
}
int
-trunk_rr_watchdog(struct trunk_softc *tr)
+trunk_rr_input(struct trunk_softc *tr, struct trunk_port *tp,
+ struct ether_header *eh, struct mbuf *m)
{
- if (tr->tr_ifflags & IFF_DEBUG)
- printf("%s\n", __func__);
+ struct ifnet *ifp = &tr->tr_ac.ac_if;
+
+ /* Just pass in the packet to our trunk device */
+ m->m_pkthdr.rcvif = ifp;
return (0);
}
+/*
+ * Active failover
+ */
+
int
-trunk_rr_input(struct trunk_softc *tr, struct trunk_port *tp,
+trunk_fail_attach(struct trunk_softc *tr)
+{
+ tr->tr_detach = trunk_fail_detach;
+ tr->tr_start = trunk_fail_start;
+ tr->tr_input = trunk_fail_input;
+ tr->tr_port_create = NULL;
+ tr->tr_port_destroy = NULL;
+
+ return (0);
+}
+
+int
+trunk_fail_detach(struct trunk_softc *tr)
+{
+ return (0);
+}
+
+int
+trunk_fail_start(struct trunk_softc *tr, struct mbuf *m)
+{
+ struct trunk_port *tp;
+ struct ifnet *ifp;
+ int error = 0;
+
+ /* Use the master port if active or the next available port */
+ if ((tp = trunk_link_active(tr, tr->tr_primary)) == NULL)
+ return (ENOENT);
+
+ /* Send mbuf */
+ ifp = tp->tp_if;
+ IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+ if (error)
+ return (error);
+ if ((ifp->if_flags & IFF_OACTIVE) == 0)
+ (*ifp->if_start)(ifp);
+
+ ifp->if_obytes += m->m_pkthdr.len;
+ if (m->m_flags & M_MCAST)
+ ifp->if_omcasts++;
+
+ return (error);
+}
+
+int
+trunk_fail_input(struct trunk_softc *tr, struct trunk_port *tp,
struct ether_header *eh, struct mbuf *m)
{
struct ifnet *ifp = &tr->tr_ac.ac_if;