summaryrefslogtreecommitdiffstats
path: root/sys/net/if_vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_vlan.c')
-rw-r--r--sys/net/if_vlan.c104
1 files changed, 50 insertions, 54 deletions
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index ed88536..355dc12 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -304,12 +304,11 @@ static void trunk_destroy(struct ifvlantrunk *trunk);
static void vlan_init(void *foo);
static void vlan_input(struct ifnet *ifp, struct mbuf *m);
static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
-static void vlan_qflush(struct ifnet *ifp);
static int vlan_setflag(struct ifnet *ifp, int flag, int status,
int (*func)(struct ifnet *, int));
static int vlan_setflags(struct ifnet *ifp, int status);
static int vlan_setmulti(struct ifnet *ifp);
-static int vlan_transmit(struct ifnet *ifp, struct mbuf *m);
+static void vlan_start(struct ifnet *ifp);
static void vlan_unconfig(struct ifnet *ifp);
static void vlan_unconfig_locked(struct ifnet *ifp, int departing);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
@@ -1073,10 +1072,12 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
/* NB: mtu is not set here */
ifp->if_init = vlan_init;
- ifp->if_transmit = vlan_transmit;
- ifp->if_qflush = vlan_qflush;
+ ifp->if_start = vlan_start;
ifp->if_ioctl = vlan_ioctl;
ifp->if_flags = VLAN_IFFLAGS;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = 0;
+ IFQ_SET_READY(&ifp->if_snd);
ether_ifattach(ifp, eaddr);
/* Now undo some of the damage... */
ifp->if_baudrate = 0;
@@ -1114,6 +1115,7 @@ vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
struct ifvlan *ifv = ifp->if_softc;
int unit = ifp->if_dunit;
+ IFQ_PURGE(&ifp->if_snd);
ether_ifdetach(ifp); /* first, remove it from system-wide lists */
vlan_unconfig(ifp); /* now it can be unconfigured and freed */
/*
@@ -1138,67 +1140,61 @@ vlan_init(void *foo __unused)
}
/*
- * The if_transmit method for vlan(4) interface.
+ * The if_start method for vlan(4) interface.
*/
-static int
-vlan_transmit(struct ifnet *ifp, struct mbuf *m)
+static void
+vlan_start(struct ifnet *ifp)
{
struct ifvlan *ifv;
struct ifnet *p;
+ struct mbuf *m;
int error, len, mcast;
VLAN_LOCK_READER;
- VLAN_RLOCK();
- ifv = ifp->if_softc;
- if (TRUNK(ifv) == NULL) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- VLAN_RUNLOCK();
- m_freem(m);
- return (ENETDOWN);
- }
- p = PARENT(ifv);
- len = m->m_pkthdr.len;
- mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
+ for (;;) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+
+ VLAN_RLOCK();
+ ifv = ifp->if_softc;
+ if (TRUNK(ifv) == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
+ return;
+ }
+ p = PARENT(ifv);
+ len = m->m_pkthdr.len;
+ mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
- BPF_MTAP(ifp, m);
+ BPF_MTAP(ifp, m);
- /*
- * Do not run parent's if_transmit() if the parent is not up,
- * or parent's driver will cause a system crash.
- */
- if (!UP_AND_RUNNING(p)) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- VLAN_RUNLOCK();
- m_freem(m);
- return (ENETDOWN);
- }
+ /*
+ * Do not run parent's if_transmit() if the parent is not up,
+ * or parent's driver will cause a system crash.
+ */
+ if (!UP_AND_RUNNING(p)) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
+ return;
+ }
+ if (!ether_8021q_frame(&m, ifp, p, ifv->ifv_vid, ifv->ifv_pcp)) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
+ return;
+ }
- if (!ether_8021q_frame(&m, ifp, p, ifv->ifv_vid, ifv->ifv_pcp)) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ /*
+ * Send it, precisely as ether_output() would have.
+ */
+ error = (p->if_transmit)(p, m);
+ if_inc_counter(ifp,
+ (error == 0) ? IFCOUNTER_OPACKETS : IFCOUNTER_OERRORS, 1);
VLAN_RUNLOCK();
- return (0);
}
-
- /*
- * Send it, precisely as ether_output() would have.
- */
- error = (p->if_transmit)(p, m);
- if (error == 0) {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
- if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
- } else
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- VLAN_RUNLOCK();
- return (error);
-}
-
-/*
- * The ifp->if_qflush entry point for vlan(4) is a no-op.
- */
-static void
-vlan_qflush(struct ifnet *ifp __unused)
-{
}
static void
@@ -1333,7 +1329,7 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
* We can handle non-ethernet hardware types as long as
* they handle the tagging and headers themselves.
*/
- if (p->if_type != IFT_ETHER &&
+ if (p->if_type != IFT_ETHER && p->if_type != IFT_BRIDGE &&
(p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
return (EPROTONOSUPPORT);
if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS)
OpenPOWER on IntegriCloud