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.