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.
signature.asc
Description: This is a digitally signed message part.

