summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-05-24 07:51:54 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-05-24 07:51:54 +0000
commitc96e00f42bd82fc6ae8e02141aac174d6ff5dccc (patch)
tree911edbc066003167bcdfc42c5bcfa279543a3960
parentfd2f9a0f7f8d879591264cbd1781b81e6a4f0157 (diff)
support trunk stacking (trunks as trunk ports) and some fixes
ok brad@
-rw-r--r--sbin/ifconfig/ifconfig.c27
-rw-r--r--sys/net/if_ethersubr.c13
-rw-r--r--sys/net/if_trunk.c54
-rw-r--r--sys/net/if_trunk.h6
4 files changed, 73 insertions, 27 deletions
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index fc068ee98fe..ccc1ef1e70e 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifconfig.c,v 1.138 2005/05/24 02:45:18 reyk Exp $ */
+/* $OpenBSD: ifconfig.c,v 1.139 2005/05/24 07:51:53 reyk Exp $ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
@@ -3202,9 +3202,17 @@ trunk_status(void)
struct trunk_reqport rp, rpbuf[TRUNK_MAX_PORTS];
struct trunk_reqall ra;
const char *proto = "<unknown>";
- int i;
+ int i, isport = 0;
+ bzero(&rp, sizeof(rp));
bzero(&ra, sizeof(ra));
+
+ strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
+
+ if (ioctl(s, SIOCGTRUNKPORT, &rp) == 0)
+ isport = 1;
+
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
ra.ra_size = sizeof(rpbuf);
ra.ra_port = rpbuf;
@@ -3217,7 +3225,11 @@ trunk_status(void)
}
}
- printf("\ttrunk: trunkproto %s\n", proto);
+ printf("\ttrunk: trunkproto %s", proto);
+ if (isport)
+ printf(" trunkdev %s", rp.rp_ifname);
+ putchar('\n');
+
for (i = 0; i < ra.ra_ports; i++) {
printf("\t\ttrunkport %s", rpbuf[i].rp_portname);
if (rpbuf[i].rp_flags & TRUNK_PORT_MASTER)
@@ -3230,15 +3242,8 @@ trunk_status(void)
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++)
printf("\t\ttrunkproto %s\n", tpr[i].tpr_name);
}
- } else {
- strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
- strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
-
- if (ioctl(s, SIOCGTRUNKPORT, &rp) != 0)
- return;
-
+ } else if (isport)
printf("\ttrunk: trunkdev %s\n", rp.rp_ifname);
- }
}
#endif /* SMALL */
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 4b440cb2dd1..08f93d7425e 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.90 2005/05/24 02:45:17 reyk Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.91 2005/05/24 07:51:53 reyk Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -612,7 +612,7 @@ ether_input(ifp, eh, m)
{
struct ifqueue *inq;
u_int16_t etype;
- int s, llcfound = 0;
+ int s, llcfound = 0, i = 0;
struct llc *l;
struct arpcom *ac;
#if NPPPOE > 0
@@ -621,9 +621,14 @@ ether_input(ifp, eh, m)
#if NTRUNK > 0
/* Handle input from a trunk port */
- if (ifp->if_type == IFT_IEEE8023ADLAG) {
- if (trunk_input(ifp, eh, m) != 0)
+ while (ifp->if_type == IFT_IEEE8023ADLAG) {
+ if (++i > TRUNK_MAX_STACKING ||
+ trunk_input(ifp, eh, m) != 0) {
+ if (m)
+ m_freem(m);
return;
+ }
+
/* Has been set to the trunk interface */
ifp = m->m_pkthdr.rcvif;
}
diff --git a/sys/net/if_trunk.c b/sys/net/if_trunk.c
index e0c7290b63f..c7b8d42a4c5 100644
--- a/sys/net/if_trunk.c
+++ b/sys/net/if_trunk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_trunk.c,v 1.1 2005/05/24 02:45:17 reyk Exp $ */
+/* $OpenBSD: if_trunk.c,v 1.2 2005/05/24 07:51:53 reyk Exp $ */
/*
* Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net>
@@ -61,6 +61,7 @@ int trunk_port_destroy(struct trunk_port *);
void trunk_port_watchdog(struct ifnet *);
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 *);
void trunk_port2req(struct trunk_port *, struct trunk_reqport *);
int trunk_ioctl(struct ifnet *, u_long, caddr_t);
void trunk_start(struct ifnet *);
@@ -162,12 +163,17 @@ trunk_clone_destroy(struct ifnet *ifp)
{
struct trunk_softc *tr = (struct trunk_softc *)ifp->if_softc;
struct trunk_port *tp;
- int error;
+ int error, s;
+
+ s = splnet();
/* Shutdown and remove trunk ports, return on error */
- while ((tp = SLIST_FIRST(&tr->tr_ports)) != NULL)
- if ((error = trunk_port_destroy(tp)) != 0)
+ while ((tp = SLIST_FIRST(&tr->tr_ports)) != NULL) {
+ if ((error = trunk_port_destroy(tp)) != 0) {
+ splx(s);
return (error);
+ }
+ }
ifmedia_delete_instance(&tr->tr_media, IFM_INST_ANY);
#if NBPFILTER > 0
@@ -179,6 +185,8 @@ trunk_clone_destroy(struct ifnet *ifp)
SLIST_REMOVE(&trunk_list, tr, trunk_softc, tr_entries);
free(tr, M_DEVBUF);
+ splx(s);
+
return (0);
}
@@ -200,6 +208,7 @@ trunk_lladdr(struct trunk_softc *tr, u_int8_t *lladdr)
int
trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
{
+ struct trunk_softc *tr_ptr;
struct trunk_port *tp;
int error = 0;
@@ -228,6 +237,18 @@ trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
bzero(tp, sizeof(struct trunk_port));
+ /* Check if port is a stacked trunk */
+ SLIST_FOREACH(tr_ptr, &trunk_list, tr_entries) {
+ if (ifp == &tr_ptr->tr_ac.ac_if) {
+ tp->tp_flags |= TRUNK_PORT_STACK;
+ if (trunk_port_checkstacking(tr_ptr) >=
+ TRUNK_MAX_STACKING) {
+ free(tp, M_DEVBUF);
+ return (E2BIG);
+ }
+ }
+ }
+
/* Change the interface type */
tp->tp_iftype = ifp->if_type;
ifp->if_type = IFT_IEEE8023ADLAG;
@@ -242,7 +263,7 @@ trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
if (SLIST_EMPTY(&tr->tr_ports)) {
tr->tr_primary = tp;
- tp->tp_flags = TRUNK_PORT_MASTER;
+ tp->tp_flags |= TRUNK_PORT_MASTER;
trunk_lladdr(tr, ((struct arpcom *)ifp)->ac_enaddr);
}
@@ -254,6 +275,23 @@ trunk_port_create(struct trunk_softc *tr, struct ifnet *ifp)
}
int
+trunk_port_checkstacking(struct trunk_softc *tr)
+{
+ struct trunk_softc *tr_ptr;
+ struct trunk_port *tp;
+ int m = 0;
+
+ SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) {
+ if (tp->tp_flags & TRUNK_PORT_STACK) {
+ tr_ptr = (struct trunk_softc *)tp->tp_if->if_softc;
+ m = MAX(m, trunk_port_checkstacking(tr_ptr));
+ }
+ }
+
+ return (m + 1);
+}
+
+int
trunk_port_destroy(struct trunk_port *tp)
{
struct trunk_softc *tr = (struct trunk_softc *)tp->tp_trunk;
@@ -366,9 +404,7 @@ trunk_port_ifdetach(struct ifnet *ifp)
{
struct trunk_port *tp;
- if (SLIST_FIRST(&trunk_list) == NULL)
- return;
- if ((tp = trunk_port_get(NULL, ifp)) == NULL)
+ if ((tp = (struct trunk_port *)ifp->if_tp) == NULL)
return;
trunk_port_destroy(tp);
@@ -652,8 +688,6 @@ trunk_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
bad:
trifp->if_ierrors++;
- if (m)
- m_free(m);
return (error);
}
diff --git a/sys/net/if_trunk.h b/sys/net/if_trunk.h
index 42c6d5fa264..d41497e5d1e 100644
--- a/sys/net/if_trunk.h
+++ b/sys/net/if_trunk.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_trunk.h,v 1.1 2005/05/24 02:45:17 reyk Exp $ */
+/* $OpenBSD: if_trunk.h,v 1.2 2005/05/24 07:51:53 reyk Exp $ */
/*
* Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net>
@@ -25,12 +25,14 @@
#define TRUNK_MAX_PORTS 32 /* logically */
#define TRUNK_MAX_NAMESIZE 32 /* name of a protocol */
+#define TRUNK_MAX_STACKING 4 /* maximum number of stacked trunks */
/* Port flags */
#define TRUNK_PORT_SLAVE 0x00000000 /* normal enslaved port */
#define TRUNK_PORT_MASTER 0x00000001 /* primary port */
+#define TRUNK_PORT_STACK 0x00000002 /* stacked trunk port */
#define TRUNK_PORT_GLOBAL 0x80000000 /* IOCTL: global flag */
-#define TRUNK_PORT_BITS "\20\01MASTER"
+#define TRUNK_PORT_BITS "\20\01MASTER\02STACK"
/* Supported trunk PROTOs */
enum trunk_proto {