Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2012 10:44:09 +0000 (UTC)
From:      Randall Stewart <rrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r236951 - head/sys/net
Message-ID:  <201206121044.q5CAi9vq048816@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rrs
Date: Tue Jun 12 10:44:09 2012
New Revision: 236951
URL: http://svn.freebsd.org/changeset/base/236951

Log:
  Allow a gif tunnel to be used with ALTq.
  
  Reviewed by:	gnn

Modified:
  head/sys/net/if_gif.c

Modified: head/sys/net/if_gif.c
==============================================================================
--- head/sys/net/if_gif.c	Tue Jun 12 10:25:11 2012	(r236950)
+++ head/sys/net/if_gif.c	Tue Jun 12 10:44:09 2012	(r236951)
@@ -342,26 +342,98 @@ gif_encapcheck(m, off, proto, arg)
 		return 0;
 	}
 }
+#ifdef INET
+#define GIF_HDR_LEN (ETHER_HDR_LEN + sizeof (struct ip))
+#endif
+#ifdef INET6
+#define GIF_HDR_LEN6 (ETHER_HDR_LEN + sizeof (struct ip6_hdr))
+#endif
 
 static void
 gif_start(struct ifnet *ifp)
 {
 	struct gif_softc *sc;
 	struct mbuf *m;
+	uint32_t af;
+	int error = 0;
 
 	sc = ifp->if_softc;
-
+	GIF_LOCK(sc);
+	if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
+		/* Already active */
+		ifp->if_drv_flags |= IFF_GIF_WANTED;
+		GIF_UNLOCK(sc);
+		return;
+	}
 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-	for (;;) {
-		IFQ_DEQUEUE(&ifp->if_snd, m);
+	GIF_UNLOCK(sc);
+keep_going:
+	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
 		if (m == 0)
 			break;
 
-		gif_output(ifp, m, sc->gif_pdst, NULL);
+#ifdef ALTQ
+		/* Take out those altq bytes we add in gif_output  */
+#ifdef INET
+		if (sc->gif_psrc->sa_family == AF_INET) 
+			m->m_pkthdr.len -= GIF_HDR_LEN;
+#endif
+#ifdef INET6
+		if (sc->gif_psrc->sa_family == AF_INET6) 
+		    m->m_pkthdr.len -= GIF_HDR_LEN6;
+#endif
+#endif
+		/* Now pull back the af in packet that
+		 * was saved in the address location.
+		 */
+		bcopy(m->m_pkthdr.src_mac_addr, &af, sizeof(af));
+		if (ifp->if_bridge)
+			af = AF_LINK;
+
+		BPF_MTAP2(ifp, &af, sizeof(af), m);
+		ifp->if_opackets++;	
+
+/*              Done by IFQ_HANDOFF */
+/* 		ifp->if_obytes += m->m_pkthdr.len;*/
+		/* override to IPPROTO_ETHERIP for bridged traffic */
+
+		M_SETFIB(m, sc->gif_fibnum);
+		/* inner AF-specific encapsulation */
+		/* XXX should we check if our outer source is legal? */
+		/* dispatch to output logic based on outer AF */
+		switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+		case AF_INET:
+			error = in_gif_output(ifp, af, m);
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			error = in6_gif_output(ifp, af, m);
+			break;
+#endif
+		default:
+			m_freem(m);		
+			error = ENETDOWN;
+		}
+		if (error)
+			ifp->if_oerrors++;
 
 	}
+	GIF_LOCK(sc);
+	if (ifp->if_drv_flags & IFF_GIF_WANTED) {
+		/* Someone did a start while
+		 * we were unlocked and processing
+		 * lets clear the flag and try again.
+		 */
+		ifp->if_drv_flags &= ~IFF_GIF_WANTED;
+		GIF_UNLOCK(sc);
+		goto keep_going;
+	}
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
+	GIF_UNLOCK(sc);
 	return;
 }
 
@@ -376,8 +448,7 @@ gif_output(ifp, m, dst, ro)
 	struct m_tag *mtag;
 	int error = 0;
 	int gif_called;
-	u_int32_t af;
-
+	uint32_t af;
 #ifdef MAC
 	error = mac_ifnet_check_transmit(ifp, m);
 	if (error) {
@@ -426,55 +497,40 @@ gif_output(ifp, m, dst, ro)
 	m_tag_prepend(m, mtag);
 
 	m->m_flags &= ~(M_BCAST|M_MCAST);
-
-	GIF_LOCK(sc);
-
-	if (!(ifp->if_flags & IFF_UP) ||
-	    sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
-		GIF_UNLOCK(sc);
-		m_freem(m);
-		error = ENETDOWN;
-		goto end;
-	}
-
 	/* BPF writes need to be handled specially. */
 	if (dst->sa_family == AF_UNSPEC) {
 		bcopy(dst->sa_data, &af, sizeof(af));
 		dst->sa_family = af;
 	}
-
 	af = dst->sa_family;
-	BPF_MTAP2(ifp, &af, sizeof(af), m);
-	ifp->if_opackets++;	
-	ifp->if_obytes += m->m_pkthdr.len;
-
-	/* override to IPPROTO_ETHERIP for bridged traffic */
-	if (ifp->if_bridge)
-		af = AF_LINK;
-
-	M_SETFIB(m, sc->gif_fibnum);
-	/* inner AF-specific encapsulation */
-
-	/* XXX should we check if our outer source is legal? */
-
-	/* dispatch to output logic based on outer AF */
-	switch (sc->gif_psrc->sa_family) {
+	/* Now save the af in the inbound pkt mac
+	 * address location.
+	 */
+	bcopy(&af, m->m_pkthdr.src_mac_addr, sizeof(af));
+	if (!(ifp->if_flags & IFF_UP) ||
+	    sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+		m_freem(m);
+		error = ENETDOWN;
+		goto end;
+	}
+#ifdef ALTQ
+	/* Make altq aware of the bytes we will add 
+	 * when we actually send it.
+	 */
 #ifdef INET
-	case AF_INET:
-		error = in_gif_output(ifp, af, m);
-		break;
+	if (sc->gif_psrc->sa_family == AF_INET) 
+		m->m_pkthdr.len += GIF_HDR_LEN;
 #endif
 #ifdef INET6
-	case AF_INET6:
-		error = in6_gif_output(ifp, af, m);
-		break;
+	if (sc->gif_psrc->sa_family == AF_INET6) 
+		m->m_pkthdr.len += GIF_HDR_LEN6;
 #endif
-	default:
-		m_freem(m);		
-		error = ENETDOWN;
-	}
-
-	GIF_UNLOCK(sc);
+#endif
+	/*
+	 * Queue message on interface, update output statistics if
+	 * successful, and start output if interface not yet active.
+	 */
+	IFQ_HANDOFF(ifp, m, error);
   end:
 	if (error)
 		ifp->if_oerrors++;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206121044.q5CAi9vq048816>