On Monday 29 August 2005 16:10, Gleb Smirnoff wrote:
> D> (I'll try it later but a definitive answer would be nice :)
>
>   If you have put smth into ng_iface_start(), then you should do this
> stuff via ng_send_fn().

OK.

> Sorry, that I haven't yet feedbacked on your patches. I'll probably look
> at them after 6.0-RELEASE.

No problem :)
I have attached an updated (untested - but it compiles! version)

-- 
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
  -- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C
Index: sys/netgraph/ng_iface.c
===================================================================
RCS file: /usr/CVS-Repository/src/sys/netgraph/ng_iface.c,v
retrieving revision 1.44
diff -u -p -r1.44 ng_iface.c
--- sys/netgraph/ng_iface.c	9 Aug 2005 10:19:59 -0000	1.44
+++ sys/netgraph/ng_iface.c	29 Aug 2005 06:05:19 -0000
@@ -107,6 +107,14 @@ const static struct iffam gFamilies[] = 
 };
 #define NUM_FAMILIES		(sizeof(gFamilies) / sizeof(*gFamilies))
 
+#define NGM_MTAG_ID_IFFAM	29
+
+/* Tag for mbufs to tell ng_iface_start where to send them */
+struct iffamtag {
+    struct m_tag	tag;
+    iffam_p		iffam_p;
+};
+
 /* Node private data */
 struct ng_iface_private {
 	struct	ifnet *ifp;		/* Our interface */
@@ -118,6 +126,7 @@ typedef struct ng_iface_private *priv_p;
 
 /* Interface methods */
 static void	ng_iface_start(struct ifnet *ifp);
+static void	ng_iface_start2(node_p node, hook_p hook, void *arg1, int arg2);
 static int	ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
 static int	ng_iface_output(struct ifnet *ifp, struct mbuf *m0,
 			struct sockaddr *dst, struct rtentry *rt0);
@@ -351,11 +360,11 @@ static int
 ng_iface_output(struct ifnet *ifp, struct mbuf *m,
 		struct sockaddr *dst, struct rtentry *rt0)
 {
-	const priv_p priv = (priv_p) ifp->if_softc;
 	const iffam_p iffam = get_iffam_from_af(dst->sa_family);
-	int len, error = 0;
+	int error = 0;
 	u_int32_t af;
-
+	struct iffamtag *mtag;
+	
 	/* Check interface flags */
 	if (!((ifp->if_flags & IFF_UP) &&
 	    (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
@@ -380,28 +389,71 @@ ng_iface_output(struct ifnet *ifp, struc
 		return (EAFNOSUPPORT);
 	}
 
-	/* Copy length before the mbuf gets invalidated */
-	len = m->m_pkthdr.len;
+	/* Tag mbuf with hook information */
+	/* XXX: kind of dumb that the alloc routine adds the size of
+	 * struct mtag adds to our length, this make it hard to
+	 * allocate the correct size.. */
+	mtag = (struct iffamtag *)m_tag_alloc(NGM_MTAG_ID_IFFAM, NGM_MTAG_ID_IFFAM, 
+					      sizeof(struct iffamtag) - sizeof(struct m_tag), M_NOWAIT);
+	if (mtag == NULL)
+	    return (ENOBUFS);
+	mtag->iffam_p = iffam;
+	m_tag_prepend(m, (struct m_tag *)mtag);
+	
+	IFQ_HANDOFF(ifp, m, error);
+	
+	return (error);
 
-	/* Send packet; if hook is not connected, mbuf will get freed. */
-	NG_SEND_DATA_ONLY(error, *get_hook_from_iffam(priv, iffam), m);
 
-	/* Update stats */
-	if (error == 0) {
-		ifp->if_obytes += len;
-		ifp->if_opackets++;
-	}
-	return (error);
 }
 
 /*
- * This routine should never be called
+ * Called to move queued packets off the interface.
+ *
+ * We wait for netgraph to call us back when we can really move the
+ * data
  */
-
 static void
 ng_iface_start(struct ifnet *ifp)
 {
-	if_printf(ifp, "%s called?", __func__);
+	const priv_p priv = (priv_p)ifp->if_softc;
+
+	ng_send_fn(priv->node, NULL, &ng_iface_start2, ifp, 0);
+}
+
+static void
+ng_iface_start2(node_p node, hook_p hook, void *arg1, int arg2)
+{
+	struct ifnet *ifp = arg1;
+	const priv_p priv = (priv_p) ifp->if_softc;
+	struct iffamtag *mtag;
+	struct mbuf *m;
+	int error = 0, len;
+	
+	if_printf(ifp, "%s called\n", __func__);
+	while (1) {
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+		if (m == NULL)
+			break;
+	    
+		mtag = (struct iffamtag *)m_tag_locate(m, NGM_MTAG_ID_IFFAM, NGM_MTAG_ID_IFFAM, NULL);
+		if (mtag == NULL) { /* mbuf with no tag? shouldn't be possible */
+			if_printf(ifp, "mbuf found without a tag, discarding\n");
+			m_freem(m); /* XXX: does this free tags too? */
+		}
+		
+		/* Copy length before the mbuf gets invalidated */
+		len = m->m_pkthdr.len;
+
+		/* Send packet; if hook is not connected, mbuf will get freed. */
+		NG_SEND_DATA_ONLY(error, *get_hook_from_iffam(priv, mtag->iffam_p), m);
+
+		/* Update stats */
+		if (error == 0) {
+			ifp->if_obytes += len;
+			ifp->if_opackets++;
+		}
+	}
 }
 
 /*
@@ -493,13 +545,15 @@ ng_iface_constructor(node_p node)
 	ifp->if_start = ng_iface_start;
 	ifp->if_ioctl = ng_iface_ioctl;
 	ifp->if_watchdog = NULL;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
 	ifp->if_mtu = NG_IFACE_MTU_DEFAULT;
 	ifp->if_flags = (IFF_SIMPLEX|IFF_POINTOPOINT|IFF_NOARP|IFF_MULTICAST);
 	ifp->if_type = IFT_PROPVIRTUAL;		/* XXX */
 	ifp->if_addrlen = 0;			/* XXX */
 	ifp->if_hdrlen = 0;			/* XXX */
 	ifp->if_baudrate = 64000;		/* XXX */
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/* Give this node the same name as the interface (if possible) */
 	if (ng_name_node(node, ifp->if_xname) != 0)

Attachment: pgpTjI65mh4pS.pgp
Description: PGP signature

Reply via email to