Hi,

attached is a small diff to allow pfil(9) consumers to force a sticky 
position on the head/tail of the processing queue.  This can be used to 
do traffic conditioning kind of tasks w/o disturbing the other filters.  
I will need this to implement carp(4) ip based load balancing.  While 
here I also removed a few paragraphs in BUGS which are no longer true 
(since we are using rmlocks for pfil(9)).

I'd appreciate review of the logic in pfil_list_add - just to make sure I 
didn't botch it.  Thanks.

-- 
/"\  Best regards,                      | [EMAIL PROTECTED]
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | [EMAIL PROTECTED]
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News
Index: sys/net/pfil.c
===================================================================
RCS file: /home/ncvs/src/sys/net/pfil.c,v
retrieving revision 1.15
diff -u -r1.15 pfil.c
--- sys/net/pfil.c	25 Nov 2007 12:41:47 -0000	1.15
+++ sys/net/pfil.c	15 Mar 2008 22:35:50 -0000
@@ -182,6 +182,9 @@
 	struct packet_filter_hook *pfh2 = NULL;
 	int err;
 
+	if ((flags & (PFIL_FIRST|PFIL_LAST)) == (PFIL_FIRST|PFIL_LAST))
+		return (EDOOFUS);
+
 	/* Get memory */
 	if (flags & PFIL_IN) {
 		pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), 
@@ -267,23 +270,50 @@
 static int
 pfil_list_add(pfil_list_t *list, struct packet_filter_hook *pfh1, int flags)
 {
-	struct packet_filter_hook *pfh;
+	struct packet_filter_hook *pfh, *fh, *lh;
 
 	/*
 	 * First make sure the hook is not already there.
 	 */
-	TAILQ_FOREACH(pfh, list, pfil_link)
+	fh = TAILQ_FIRST(list);
+	lh = NULL;
+	TAILQ_FOREACH(pfh, list, pfil_link) {
+		/* fh is the first hook not marked PFIL_FIRST */
+		if (pfh->pfil_flags & PFIL_FIRST)
+			fh = TAILQ_NEXT(pfh, pfil_link);
+		/* lh ist the last hook not marked PFIL_LAST */
+		if (!(pfh->pfil_flags & PFIL_LAST))
+			lh = pfh;
 		if (pfh->pfil_func == pfh1->pfil_func &&
 		    pfh->pfil_arg == pfh1->pfil_arg)
 			return EEXIST;
+	}
+
 	/*
 	 * insert the input list in reverse order of the output list
 	 * so that the same path is followed in or out of the kernel.
 	 */
-	if (flags & PFIL_IN)
+	if (flags & PFIL_FIRST) {
 		TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
-	else
+	} else if (flags & PFIL_LAST) {
 		TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
+	} else {
+		if (flags & PFIL_IN) {
+			if (fh)
+				TAILQ_INSERT_BEFORE(fh, pfh1, pfil_link);
+			else if (!TAILQ_EMPTY(list))
+				TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
+			else
+				TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
+		} else {
+			if (lh)
+				TAILQ_INSERT_AFTER(list, lh, pfh1, pfil_link);
+			else if (!TAILQ_EMPTY(list))
+				TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
+			else
+				TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
+		}
+	}
 
 	return 0;
 }
Index: sys/net/pfil.h
===================================================================
RCS file: /home/ncvs/src/sys/net/pfil.h,v
retrieving revision 1.17
diff -u -r1.17 pfil.h
--- sys/net/pfil.h	25 Nov 2007 12:41:47 -0000	1.17
+++ sys/net/pfil.h	15 Mar 2008 22:34:44 -0000
@@ -54,10 +54,12 @@
 	int	pfil_flags;
 };
 
-#define PFIL_IN		0x00000001
-#define PFIL_OUT	0x00000002
-#define PFIL_WAITOK	0x00000004
-#define PFIL_ALL	(PFIL_IN|PFIL_OUT)
+#define	PFIL_IN		(1<<0)
+#define	PFIL_OUT	(1<<2)
+#define	PFIL_WAITOK	(1<<3)
+#define	PFIL_ALL	(PFIL_IN|PFIL_OUT)
+#define	PFIL_FIRST	(1<<4)
+#define	PFIL_LAST	(1<<5)
 
 typedef	TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t;
 
Index: share/man/man9/pfil.9
===================================================================
RCS file: /home/ncvs/src/share/man/man9/pfil.9,v
retrieving revision 1.22
diff -u -r1.22 pfil.9
--- share/man/man9/pfil.9	18 Sep 2006 15:24:20 -0000	1.22
+++ share/man/man9/pfil.9	15 Mar 2008 22:50:48 -0000
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man9/pfil.9,v 1.22 2006/09/18 15:24:20 ru Exp $
 .\"
-.Dd September 29, 2004
+.Dd March 15, 2008
 .Dt PFIL 9
 .Os
 .Sh NAME
@@ -115,6 +115,11 @@
 or
 .Dv PFIL_OUT )
 that the packet is traveling.
+.Dv PFIL_FIRST
+and
+.Dv PFIL_LAST
+can be used to force a sticky positioning of the hook in the front or the
+tail of the processing queue respectively.
 The filter may change which mbuf the
 .Vt "mbuf\ **"
 argument references.
@@ -134,15 +139,6 @@
 .Fn pfil_remove_hook
 functions
 return 0 if successful.
-If called with flag
-.Dv PFIL_WAITOK ,
-.Fn pfil_remove_hook
-is expected to always succeed.
-.Pp
-The
-.Fn pfil_head_unregister
-function
-might sleep!
 .Sh SEE ALSO
 .Xr bpf 4 ,
 .Xr if_bridge 4
@@ -203,14 +199,3 @@
 .Dv AF_INET6
 traffic according to its sysctl settings, but contrary to the above
 statements, the data is provided in host byte order.
-.Pp
-When a
-.Vt pfil_head
-is being modified, no traffic is diverted
-(to avoid deadlock).
-This means that traffic may be dropped unconditionally for a short period
-of time.
-.Fn pfil_run_hooks
-will return
-.Er ENOBUFS
-to indicate this.

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to