From owner-freebsd-ipfw@FreeBSD.ORG Tue Nov 25 14:22:09 2008 Return-Path: Delivered-To: ipfw@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 69ABE1065692 for ; Tue, 25 Nov 2008 14:22:08 +0000 (UTC) (envelope-from eugen@kuzbass.ru) Received: from www.svzserv.kemerovo.su (www.svzserv.kemerovo.su [213.184.65.80]) by mx1.freebsd.org (Postfix) with ESMTP id 48B828FC08 for ; Tue, 25 Nov 2008 14:22:05 +0000 (UTC) (envelope-from eugen@kuzbass.ru) Received: from www.svzserv.kemerovo.su (eugen@localhost [127.0.0.1]) by www.svzserv.kemerovo.su (8.13.8/8.13.8) with ESMTP id mAPDgd2w018301; Tue, 25 Nov 2008 20:42:39 +0700 (KRAT) (envelope-from eugen@www.svzserv.kemerovo.su) Received: (from eugen@localhost) by www.svzserv.kemerovo.su (8.13.8/8.13.8/Submit) id mAPDgdY1018299; Tue, 25 Nov 2008 20:42:39 +0700 (KRAT) (envelope-from eugen) Date: Tue, 25 Nov 2008 20:42:39 +0700 From: Eugene Grosbein To: net@freebsd.org Message-ID: <20081125134239.GA17138@svzserv.kemerovo.su> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.3i Cc: ipfw@freebsd.org Subject: m_tag_find() overhead X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Nov 2008 14:22:20 -0000 Hi! I wonder if one more call to m_tag_find() for every outgoing packet would be expensive. For many years conventional way to implement PBR was: use 'ipfw fwd'. Currently 'ipfw add fwd ... in' marks a packet with PACKET_TAG_IPFORWARD. Such forwarding changes packet's outgoing interface generally but none in the kernel reflect this in packet's metadata and packets are passed by ip_output() to PFIL hooks with wrong outgoing interface name ( details and How-To-Repeat may be found here: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/129036 ) I've patched src/sys/netinet/ip_output.c to fix this problem by extra check for PACKET_TAG_IPFORWARD and update of route if necessary. This adds a call to m_tag_find() for every outgoing packet if packet filtering is enabled and kernel has options IPFIREWALL_FORWARD. Please review. It works for my test lab but I'm not sure if that's correct: should a call to rtalloc_ign() be accomplished with some resource freeing call? And what's the meaning of RTF_CLONING second argument of rtalloc_ign? --- ip_output.c.orig 2008-11-25 14:21:26.000000000 +0700 +++ ip_output.c 2008-11-25 18:29:32.000000000 +0700 @@ -195,6 +195,20 @@ ro->ro_rt = (struct rtentry *)0; } #ifdef IPFIREWALL_FORWARD + /* + * Check if packet has changed next-hop in ip_input() + * If so, update route so pfil hooks get it right + */ + if ((inet_pfil_hook.ph_busy_count != -1) && + (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL))) { + bzero(&iproute, sizeof(iproute)); + ro = &iproute; + bcopy((fwd_tag+1), &ro->ro_dst, sizeof(struct sockaddr_in)); + m_tag_delete(m, fwd_tag); + rtalloc_ign(ro, RTF_CLONING); + dst = (struct sockaddr_in *)&ro->ro_dst; + } + if (ro->ro_rt == NULL && fwd_tag == NULL) { #else if (ro->ro_rt == NULL) { Eugene Grosbein