svn commit: r184961 - user/kmacy/HEAD_fast_multi_xmit/sys/netinet

Kip Macy kmacy at FreeBSD.org
Fri Nov 14 00:27:23 PST 2008


Author: kmacy
Date: Fri Nov 14 08:27:23 2008
New Revision: 184961
URL: http://svn.freebsd.org/changeset/base/184961

Log:
  allow reversion to legacy ip_output behavior at runtime

Modified:
  user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_input.c
  user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_output.c
  user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_var.h

Modified: user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_input.c
==============================================================================
--- user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_input.c	Fri Nov 14 08:26:45 2008	(r184960)
+++ user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_input.c	Fri Nov 14 08:27:23 2008	(r184961)
@@ -216,6 +216,7 @@ int fw_one_pass = 1;
 struct flowtable *ipv4_ft;
 struct flowtable *ipv4_forward_ft;
 
+
 static void	ip_freef(struct ipqhead *, struct ipq *);
 
 /*
@@ -1407,7 +1408,7 @@ ip_forward(struct mbuf *m, int srcrt)
 	 * Try to cache the route MTU from ip_output so we can consider it for
 	 * the ICMP_UNREACH_NEEDFRAG "Next-Hop MTU" field described in RFC1191.
 	 */
-	error = ip_output(m, NULL, (struct route *)&ri, IP_FORWARDING|IP_RTINFO,
+	error = ip_output_fast(m, NULL, (struct route *)&ri, IP_FORWARDING|IP_RTINFO,
 	    NULL, NULL);
 
 	if (error == EMSGSIZE)

Modified: user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_output.c
==============================================================================
--- user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_output.c	Fri Nov 14 08:26:45 2008	(r184960)
+++ user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_output.c	Fri Nov 14 08:27:23 2008	(r184961)
@@ -97,10 +97,528 @@ static void	ip_mloopback
 
 
 extern	struct protosw inetsw[];
-
 extern struct flowtable *ipv4_ft;
+extern int flowtable_enable;
+
+
+/*
+ * IP output.  The packet in mbuf chain m contains a skeletal IP
+ * header (with len, off, ttl, proto, tos, src, dst).
+ * The mbuf chain containing the packet will be freed.
+ * The mbuf opt, if present, will not be freed.
+ * In the IP forwarding case, the packet will arrive with options already
+ * inserted, so must have a NULL opt pointer.
+ */
+static int
+ip_output_legacy(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
+    struct ip_moptions *imo, struct inpcb *inp)
+{
+	INIT_VNET_NET(curvnet);
+	INIT_VNET_INET(curvnet);
+	struct ip *ip;
+	struct ifnet *ifp = NULL;	/* keep compiler happy */
+	struct mbuf *m0;
+	int hlen = sizeof (struct ip);
+	int mtu;
+	int len, error = 0;
+	struct sockaddr_in *dst = NULL;	/* keep compiler happy */
+	struct in_ifaddr *ia = NULL;
+	int isbroadcast, sw_csum;
+	struct route iproute;
+	struct in_addr odst;
+#ifdef IPFIREWALL_FORWARD
+	struct m_tag *fwd_tag = NULL;
+#endif
+	M_ASSERTPKTHDR(m);
+
+	if (ro == NULL) {
+		ro = &iproute;
+		bzero(ro, sizeof (*ro));
+	}
+
+	if (inp != NULL)
+		INP_LOCK_ASSERT(inp);
+
+	if (opt) {
+		len = 0;
+		m = ip_insertoptions(m, opt, &len);
+		if (len != 0)
+			hlen = len;
+	}
+	ip = mtod(m, struct ip *);
+
+	/*
+	 * Fill in IP header.  If we are not allowing fragmentation,
+	 * then the ip_id field is meaningless, but we don't set it
+	 * to zero.  Doing so causes various problems when devices along
+	 * the path (routers, load balancers, firewalls, etc.) illegally
+	 * disable DF on our packet.  Note that a 16-bit counter
+	 * will wrap around in less than 10 seconds at 100 Mbit/s on a
+	 * medium with MTU 1500.  See Steven M. Bellovin, "A Technique
+	 * for Counting NATted Hosts", Proc. IMW'02, available at
+	 * <http://www.cs.columbia.edu/~smb/papers/fnat.pdf>.
+	 */
+	if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
+		ip->ip_v = IPVERSION;
+		ip->ip_hl = hlen >> 2;
+		ip->ip_id = ip_newid();
+		V_ipstat.ips_localout++;
+	} else {
+		hlen = ip->ip_hl << 2;
+	}
+
+	dst = (struct sockaddr_in *)&ro->ro_dst;
+again:
+	/*
+	 * If there is a cached route,
+	 * check that it is to the same destination
+	 * and is still up.  If not, free it and try again.
+	 * The address family should also be checked in case of sharing the
+	 * cache with IPv6.
+	 */
+	if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+			  dst->sin_family != AF_INET ||
+			  dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+		RTFREE(ro->ro_rt);
+		ro->ro_rt = (struct rtentry *)NULL;
+	}
+#ifdef IPFIREWALL_FORWARD
+	if (ro->ro_rt == NULL && fwd_tag == NULL) {
+#else
+	if (ro->ro_rt == NULL) {
+#endif
+		bzero(dst, sizeof(*dst));
+		dst->sin_family = AF_INET;
+		dst->sin_len = sizeof(*dst);
+		dst->sin_addr = ip->ip_dst;
+	}
+	/*
+	 * If routing to interface only, short circuit routing lookup.
+	 * The use of an all-ones broadcast address implies this; an
+	 * interface is specified by the broadcast address of an interface,
+	 * or the destination address of a ptp interface.
+	 */
+	if (flags & IP_SENDONES) {
+		if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL &&
+		    (ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL) {
+			V_ipstat.ips_noroute++;
+			error = ENETUNREACH;
+			goto bad;
+		}
+		ip->ip_dst.s_addr = INADDR_BROADCAST;
+		dst->sin_addr = ip->ip_dst;
+		ifp = ia->ia_ifp;
+		ip->ip_ttl = 1;
+		isbroadcast = 1;
+	} else if (flags & IP_ROUTETOIF) {
+		if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
+		    (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {
+			V_ipstat.ips_noroute++;
+			error = ENETUNREACH;
+			goto bad;
+		}
+		ifp = ia->ia_ifp;
+		ip->ip_ttl = 1;
+		isbroadcast = in_broadcast(dst->sin_addr, ifp);
+	} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
+	    imo != NULL && imo->imo_multicast_ifp != NULL) {
+		/*
+		 * Bypass the normal routing lookup for multicast
+		 * packets if the interface is specified.
+		 */
+		ifp = imo->imo_multicast_ifp;
+		IFP_TO_IA(ifp, ia);
+		isbroadcast = 0;	/* fool gcc */
+	} else {
+		/*
+		 * We want to do any cloning requested by the link layer,
+		 * as this is probably required in all cases for correct
+		 * operation (as it is for ARP).
+		 */
+		if (ro->ro_rt == NULL)
+#ifdef RADIX_MPATH
+			rtalloc_mpath_fib(ro,
+			    ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr),
+			    inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
+#else
+			in_rtalloc_ign(ro, 0,
+			    inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
+#endif
+		if (ro->ro_rt == NULL) {
+			V_ipstat.ips_noroute++;
+			error = EHOSTUNREACH;
+			goto bad;
+		}
+		ia = ifatoia(ro->ro_rt->rt_ifa);
+		ifp = ro->ro_rt->rt_ifp;
+		ro->ro_rt->rt_rmx.rmx_pksent++;
+		if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+			dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
+		if (ro->ro_rt->rt_flags & RTF_HOST)
+			isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
+		else
+			isbroadcast = in_broadcast(dst->sin_addr, ifp);
+	}
+	/*
+	 * Calculate MTU.  If we have a route that is up, use that,
+	 * otherwise use the interface's MTU.
+	 */
+	if (ro->ro_rt != NULL && (ro->ro_rt->rt_flags & (RTF_UP|RTF_HOST))) {
+		/*
+		 * This case can happen if the user changed the MTU
+		 * of an interface after enabling IP on it.  Because
+		 * most netifs don't keep track of routes pointing to
+		 * them, there is no way for one to update all its
+		 * routes when the MTU is changed.
+		 */
+		if (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)
+			ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+		mtu = ro->ro_rt->rt_rmx.rmx_mtu;
+	} else {
+		mtu = ifp->if_mtu;
+	}
+	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+		struct in_multi *inm;
+
+		m->m_flags |= M_MCAST;
+		/*
+		 * IP destination address is multicast.  Make sure "dst"
+		 * still points to the address in "ro".  (It may have been
+		 * changed to point to a gateway address, above.)
+		 */
+		dst = (struct sockaddr_in *)&ro->ro_dst;
+		/*
+		 * See if the caller provided any multicast options
+		 */
+		if (imo != NULL) {
+			ip->ip_ttl = imo->imo_multicast_ttl;
+			if (imo->imo_multicast_vif != -1)
+				ip->ip_src.s_addr =
+				    ip_mcast_src ?
+				    ip_mcast_src(imo->imo_multicast_vif) :
+				    INADDR_ANY;
+		} else
+			ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
+		/*
+		 * Confirm that the outgoing interface supports multicast.
+		 */
+		if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
+			if ((ifp->if_flags & IFF_MULTICAST) == 0) {
+				V_ipstat.ips_noroute++;
+				error = ENETUNREACH;
+				goto bad;
+			}
+		}
+		/*
+		 * If source address not specified yet, use address
+		 * of outgoing interface.
+		 */
+		if (ip->ip_src.s_addr == INADDR_ANY) {
+			/* Interface may have no addresses. */
+			if (ia != NULL)
+				ip->ip_src = IA_SIN(ia)->sin_addr;
+		}
+
+		IN_MULTI_LOCK();
+		IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
+		if (inm != NULL &&
+		   (imo == NULL || imo->imo_multicast_loop)) {
+			IN_MULTI_UNLOCK();
+			/*
+			 * If we belong to the destination multicast group
+			 * on the outgoing interface, and the caller did not
+			 * forbid loopback, loop back a copy.
+			 */
+			ip_mloopback(ifp, m, dst, hlen);
+		}
+		else {
+			IN_MULTI_UNLOCK();
+			/*
+			 * If we are acting as a multicast router, perform
+			 * multicast forwarding as if the packet had just
+			 * arrived on the interface to which we are about
+			 * to send.  The multicast forwarding function
+			 * recursively calls this function, using the
+			 * IP_FORWARDING flag to prevent infinite recursion.
+			 *
+			 * Multicasts that are looped back by ip_mloopback(),
+			 * above, will be forwarded by the ip_input() routine,
+			 * if necessary.
+			 */
+			if (V_ip_mrouter && (flags & IP_FORWARDING) == 0) {
+				/*
+				 * If rsvp daemon is not running, do not
+				 * set ip_moptions. This ensures that the packet
+				 * is multicast and not just sent down one link
+				 * as prescribed by rsvpd.
+				 */
+				if (!V_rsvp_on)
+					imo = NULL;
+				if (ip_mforward &&
+				    ip_mforward(ip, ifp, m, imo) != 0) {
+					m_freem(m);
+					goto done;
+				}
+			}
+		}
+
+		/*
+		 * Multicasts with a time-to-live of zero may be looped-
+		 * back, above, but must not be transmitted on a network.
+		 * Also, multicasts addressed to the loopback interface
+		 * are not sent -- the above call to ip_mloopback() will
+		 * loop back a copy if this host actually belongs to the
+		 * destination group on the loopback interface.
+		 */
+		if (ip->ip_ttl == 0 || ifp->if_flags & IFF_LOOPBACK) {
+			m_freem(m);
+			goto done;
+		}
+
+		goto sendit;
+	}
+
+	/*
+	 * If the source address is not specified yet, use the address
+	 * of the outoing interface.
+	 */
+	if (ip->ip_src.s_addr == INADDR_ANY) {
+		/* Interface may have no addresses. */
+		if (ia != NULL) {
+			ip->ip_src = IA_SIN(ia)->sin_addr;
+		}
+	}
 
+	/*
+	 * Verify that we have any chance at all of being able to queue the
+	 * packet or packet fragments, unless ALTQ is enabled on the given
+	 * interface in which case packetdrop should be done by queueing.
+	 */
+#ifdef ALTQ
+	if ((!ALTQ_IS_ENABLED(&ifp->if_snd)) &&
+	    ((ifp->if_snd.ifq_len + ip->ip_len / mtu + 1) >=
+	    ifp->if_snd.ifq_maxlen))
+#else
+	if ((ifp->if_snd.ifq_len + ip->ip_len / mtu + 1) >=
+	    ifp->if_snd.ifq_maxlen)
+#endif /* ALTQ */
+	{
+		error = ENOBUFS;
+		V_ipstat.ips_odropped++;
+		ifp->if_snd.ifq_drops += (ip->ip_len / ifp->if_mtu + 1);
+		goto bad;
+	}
 
+	/*
+	 * Look for broadcast address and
+	 * verify user is allowed to send
+	 * such a packet.
+	 */
+	if (isbroadcast) {
+		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
+			error = EADDRNOTAVAIL;
+			goto bad;
+		}
+		if ((flags & IP_ALLOWBROADCAST) == 0) {
+			error = EACCES;
+			goto bad;
+		}
+		/* don't allow broadcast messages to be fragmented */
+		if (ip->ip_len > mtu) {
+			error = EMSGSIZE;
+			goto bad;
+		}
+		m->m_flags |= M_BCAST;
+	} else {
+		m->m_flags &= ~M_BCAST;
+	}
+
+sendit:
+#ifdef IPSEC
+	switch(ip_ipsec_output(&m, inp, &flags, &error, &ro, &iproute, &dst, &ia, &ifp)) {
+	case 1:
+		goto bad;
+	case -1:
+		goto done;
+	case 0:
+	default:
+		break;	/* Continue with packet processing. */
+	}
+	/* Update variables that are affected by ipsec4_output(). */
+	ip = mtod(m, struct ip *);
+	hlen = ip->ip_hl << 2;
+#endif /* IPSEC */
+
+	/* Jump over all PFIL processing if hooks are not active. */
+	if (!PFIL_HOOKED(&inet_pfil_hook))
+		goto passout;
+
+	/* Run through list of hooks for output packets. */
+	odst.s_addr = ip->ip_dst.s_addr;
+	error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
+	if (error != 0 || m == NULL)
+		goto done;
+
+	ip = mtod(m, struct ip *);
+
+	/* See if destination IP address was changed by packet filter. */
+	if (odst.s_addr != ip->ip_dst.s_addr) {
+		m->m_flags |= M_SKIP_FIREWALL;
+		/* If destination is now ourself drop to ip_input(). */
+		if (in_localip(ip->ip_dst)) {
+			m->m_flags |= M_FASTFWD_OURS;
+			if (m->m_pkthdr.rcvif == NULL)
+				m->m_pkthdr.rcvif = V_loif;
+			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+				m->m_pkthdr.csum_flags |=
+				    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+				m->m_pkthdr.csum_data = 0xffff;
+			}
+			m->m_pkthdr.csum_flags |=
+			    CSUM_IP_CHECKED | CSUM_IP_VALID;
+
+			error = netisr_queue(NETISR_IP, m);
+			goto done;
+		} else
+			goto again;	/* Redo the routing table lookup. */
+	}
+
+#ifdef IPFIREWALL_FORWARD
+	/* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
+	if (m->m_flags & M_FASTFWD_OURS) {
+		if (m->m_pkthdr.rcvif == NULL)
+			m->m_pkthdr.rcvif = V_loif;
+		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+			m->m_pkthdr.csum_flags |=
+			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+			m->m_pkthdr.csum_data = 0xffff;
+		}
+		m->m_pkthdr.csum_flags |=
+			    CSUM_IP_CHECKED | CSUM_IP_VALID;
+
+		error = netisr_queue(NETISR_IP, m);
+		goto done;
+	}
+	/* Or forward to some other address? */
+	fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+	if (fwd_tag) {
+		dst = (struct sockaddr_in *)&ro->ro_dst;
+		bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
+		m->m_flags |= M_SKIP_FIREWALL;
+		m_tag_delete(m, fwd_tag);
+		goto again;
+	}
+#endif /* IPFIREWALL_FORWARD */
+
+passout:
+	/* 127/8 must not appear on wire - RFC1122. */
+	if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
+	    (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
+		if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
+			V_ipstat.ips_badaddr++;
+			error = EADDRNOTAVAIL;
+			goto bad;
+		}
+	}
+
+	m->m_pkthdr.csum_flags |= CSUM_IP;
+	sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist;
+	if (sw_csum & CSUM_DELAY_DATA) {
+		in_delayed_cksum(m);
+		sw_csum &= ~CSUM_DELAY_DATA;
+	}
+	m->m_pkthdr.csum_flags &= ifp->if_hwassist;
+
+	/*
+	 * If small enough for interface, or the interface will take
+	 * care of the fragmentation for us, we can just send directly.
+	 */
+	if (ip->ip_len <= mtu ||
+	    (m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
+	    ((ip->ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) {
+		ip->ip_len = htons(ip->ip_len);
+		ip->ip_off = htons(ip->ip_off);
+		ip->ip_sum = 0;
+		if (sw_csum & CSUM_DELAY_IP)
+			ip->ip_sum = in_cksum(m, hlen);
+
+		/*
+		 * Record statistics for this interface address.
+		 * With CSUM_TSO the byte/packet count will be slightly
+		 * incorrect because we count the IP+TCP headers only
+		 * once instead of for every generated packet.
+		 */
+		if (!(flags & IP_FORWARDING) && ia) {
+			if (m->m_pkthdr.csum_flags & CSUM_TSO)
+				ia->ia_ifa.if_opackets +=
+				    m->m_pkthdr.len / m->m_pkthdr.tso_segsz;
+			else
+				ia->ia_ifa.if_opackets++;
+			ia->ia_ifa.if_obytes += m->m_pkthdr.len;
+		}
+#ifdef MBUF_STRESS_TEST
+		if (mbuf_frag_size && m->m_pkthdr.len > mbuf_frag_size)
+			m = m_fragment(m, M_DONTWAIT, mbuf_frag_size);
+#endif
+		/*
+		 * Reset layer specific mbuf flags
+		 * to avoid confusing lower layers.
+		 */
+		m->m_flags &= ~(M_PROTOFLAGS);
+
+		error = (*ifp->if_output)(ifp, m,
+				(struct sockaddr *)dst, ro->ro_rt);
+		goto done;
+	}
+
+	/* Balk when DF bit is set or the interface didn't support TSO. */
+	if ((ip->ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) {
+		error = EMSGSIZE;
+		V_ipstat.ips_cantfrag++;
+		goto bad;
+	}
+
+	/*
+	 * Too large for interface; fragment if possible. If successful,
+	 * on return, m will point to a list of packets to be sent.
+	 */
+	error = ip_fragment(ip, &m, mtu, ifp->if_hwassist, sw_csum);
+	if (error)
+		goto bad;
+	for (; m; m = m0) {
+		m0 = m->m_nextpkt;
+		m->m_nextpkt = 0;
+		if (error == 0) {
+			/* Record statistics for this interface address. */
+			if (ia != NULL) {
+				ia->ia_ifa.if_opackets++;
+				ia->ia_ifa.if_obytes += m->m_pkthdr.len;
+			}
+			/*
+			 * Reset layer specific mbuf flags
+			 * to avoid confusing upper layers.
+			 */
+			m->m_flags &= ~(M_PROTOFLAGS);
+
+			error = (*ifp->if_output)(ifp, m,
+			    (struct sockaddr *)dst, ro->ro_rt);
+		} else
+			m_freem(m);
+	}
+
+	if (error == 0)
+		V_ipstat.ips_fragmented++;
+
+done:
+	if (ro == &iproute && ro->ro_rt) {
+		RTFREE(ro->ro_rt);
+	}
+	return (error);
+bad:
+	m_freem(m);
+	goto done;
+}
+	
 /*
  * IP output.  The packet in mbuf chain m contains a skeletal IP
  * header (with len, off, ttl, proto, tos, src, dst).
@@ -110,7 +628,7 @@ extern struct flowtable *ipv4_ft;
  * inserted, so must have a NULL opt pointer.
  */
 int
-ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
+ip_output_fast(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
     struct ip_moptions *imo, struct inpcb *inp)
 {
 	INIT_VNET_NET(curvnet);
@@ -628,6 +1146,17 @@ bad:
 	goto done;
 }
 
+
+int
+ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
+    struct ip_moptions *imo, struct inpcb *inp)
+{
+	if (flowtable_enable)
+		return (ip_output_fast(m, opt, ro, flags, imo, inp));
+	else
+		return (ip_output_legacy(m, opt, ro, flags, imo, inp));
+}
+
 /*
  * Create a chain of fragments which fit the given mtu. m_frag points to the
  * mbuf to be fragmented; on return it points to the chain with the fragments.

Modified: user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_var.h
==============================================================================
--- user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_var.h	Fri Nov 14 08:26:45 2008	(r184960)
+++ user/kmacy/HEAD_fast_multi_xmit/sys/netinet/ip_var.h	Fri Nov 14 08:27:23 2008	(r184961)
@@ -208,6 +208,9 @@ extern int
 int	ip_output(struct mbuf *,
 	    struct mbuf *, struct route *, int, struct ip_moptions *,
 	    struct inpcb *);
+int	ip_output_fast(struct mbuf *,
+	    struct mbuf *, struct route *, int, struct ip_moptions *,
+	    struct inpcb *);
 int	ipproto_register(u_char);
 int	ipproto_unregister(u_char);
 struct mbuf *


More information about the svn-src-user mailing list