summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/inet.426
-rw-r--r--sys/net/if_arcsubr.c4
-rw-r--r--sys/net/if_ef.c2
-rw-r--r--sys/net/if_ethersubr.c2
-rw-r--r--sys/net/if_fddisubr.c2
-rw-r--r--sys/net/if_fwsubr.c2
-rw-r--r--sys/net/if_iso88025subr.c2
-rw-r--r--sys/netinet/in_var.h2
-rw-r--r--sys/netinet/ip_fastfwd.c117
-rw-r--r--sys/netinet/ip_input.c12
10 files changed, 151 insertions, 20 deletions
diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4
index 6fe4e61..09cb0bc 100644
--- a/share/man/man4/inet.4
+++ b/share/man/man4/inet.4
@@ -32,7 +32,7 @@
.\" From: @(#)inet.4 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd Feb 4, 2016
+.Dd January 26, 2012
.Dt INET 4
.Os
.Sh NAME
@@ -169,11 +169,33 @@ MIB.
In addition to the variables supported by the transport protocols
(for which the respective manual pages may be consulted),
the following general variables are defined:
-.Bl -tag -width IPCTL_ACCEPTSOURCEROUTE
+.Bl -tag -width IPCTL_FASTFORWARDING
.It Dv IPCTL_FORWARDING
.Pq ip.forwarding
Boolean: enable/disable forwarding of IP packets.
Defaults to off.
+.It Dv IPCTL_FASTFORWARDING
+.Pq ip.fastforwarding
+Boolean: enable/disable the use of
+.Tn fast IP forwarding
+code.
+Defaults to off.
+When
+.Tn fast IP forwarding
+is enabled, IP packets are forwarded directly to the appropriate network
+interface with direct processing to completion, which greatly improves
+the throughput.
+All packets for local IP addresses, non-unicast, or with IP options are
+handled by the normal IP input processing path.
+All features of the normal (slow) IP forwarding path are supported
+including firewall (through
+.Xr pfil 9
+hooks) checking, except
+.Xr ipsec 4
+tunnel brokering.
+The
+.Tn IP fastforwarding
+path does not generate ICMP redirect or source quench messages.
.It Dv IPCTL_SENDREDIRECTS
.Pq ip.redirect
Boolean: enable/disable sending of ICMP redirects in response to
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index 1091ae4..2f94785 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -557,11 +557,15 @@ arc_input(struct ifnet *ifp, struct mbuf *m)
#ifdef INET
case ARCTYPE_IP:
m_adj(m, ARC_HDRNEWLEN);
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
case ARCTYPE_IP_OLD:
m_adj(m, ARC_HDRLEN);
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index 478dfb4..fc6402c 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -240,6 +240,8 @@ ef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type)
#endif
#ifdef INET
case ETHERTYPE_IP:
+ if ((m = ip_fastforward(m)) == NULL)
+ return (0);
isr = NETISR_IP;
break;
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 90ebb56..ea22d33 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -784,6 +784,8 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
switch (ether_type) {
#ifdef INET
case ETHERTYPE_IP:
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index 271f72c..4f54dcb 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -501,6 +501,8 @@ fddi_input(ifp, m)
switch (type) {
#ifdef INET
case ETHERTYPE_IP:
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index acac423..31fc2a9 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -595,6 +595,8 @@ firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src)
switch (type) {
#ifdef INET
case ETHERTYPE_IP:
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index f96df4e..5975b28 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -579,6 +579,8 @@ iso88025_input(ifp, m)
#ifdef INET
case ETHERTYPE_IP:
th->iso88025_shost[0] &= ~(TR_RII);
+ if ((m = ip_fastforward(m)) == NULL)
+ return;
isr = NETISR_IP;
break;
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 511ba26..8657dbb 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -452,7 +452,7 @@ int in_scrubprefix(struct in_ifaddr *, u_int);
void ip_input(struct mbuf *);
int in_ifadown(struct ifaddr *ifa, int);
void in_ifscrub(struct ifnet *, struct in_ifaddr *, u_int);
-struct mbuf *ip_tryforward(struct mbuf *);
+struct mbuf *ip_fastforward(struct mbuf *);
void *in_domifattach(struct ifnet *);
void in_domifdetach(struct ifnet *, void *);
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 13c5785..0772cf0 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -109,6 +109,12 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
+static VNET_DEFINE(int, ipfastforward_active);
+#define V_ipfastforward_active VNET(ipfastforward_active)
+
+SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW,
+ &VNET_NAME(ipfastforward_active), 0, "Enable fast IP forwarding");
+
static struct sockaddr_in *
ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
{
@@ -153,7 +159,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
* to ip_input for full processing.
*/
struct mbuf *
-ip_tryforward(struct mbuf *m)
+ip_fastforward(struct mbuf *m)
{
struct ip *ip;
struct mbuf *m0 = NULL;
@@ -161,20 +167,119 @@ ip_tryforward(struct mbuf *m)
struct sockaddr_in *dst = NULL;
struct ifnet *ifp;
struct in_addr odest, dest;
- uint16_t ip_len, ip_off;
+ uint16_t sum, ip_len, ip_off;
int error = 0;
- int mtu;
+ int hlen, mtu;
struct m_tag *fwd_tag = NULL;
/*
* Are we active and forwarding packets?
*/
+ if (!V_ipfastforward_active || !V_ipforwarding)
+ return m;
M_ASSERTVALID(m);
M_ASSERTPKTHDR(m);
bzero(&ro, sizeof(ro));
+ /*
+ * Step 1: check for packet drop conditions (and sanity checks)
+ */
+
+ /*
+ * Is entire packet big enough?
+ */
+ if (m->m_pkthdr.len < sizeof(struct ip)) {
+ IPSTAT_INC(ips_tooshort);
+ goto drop;
+ }
+
+ /*
+ * Is first mbuf large enough for ip header and is header present?
+ */
+ if (m->m_len < sizeof (struct ip) &&
+ (m = m_pullup(m, sizeof (struct ip))) == NULL) {
+ IPSTAT_INC(ips_toosmall);
+ return NULL; /* mbuf already free'd */
+ }
+
+ ip = mtod(m, struct ip *);
+
+ /*
+ * Is it IPv4?
+ */
+ if (ip->ip_v != IPVERSION) {
+ IPSTAT_INC(ips_badvers);
+ goto drop;
+ }
+
+ /*
+ * Is IP header length correct and is it in first mbuf?
+ */
+ hlen = ip->ip_hl << 2;
+ if (hlen < sizeof(struct ip)) { /* minimum header length */
+ IPSTAT_INC(ips_badhlen);
+ goto drop;
+ }
+ if (hlen > m->m_len) {
+ if ((m = m_pullup(m, hlen)) == NULL) {
+ IPSTAT_INC(ips_badhlen);
+ return NULL; /* mbuf already free'd */
+ }
+ ip = mtod(m, struct ip *);
+ }
+
+ /*
+ * Checksum correct?
+ */
+ if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
+ sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
+ else {
+ if (hlen == sizeof(struct ip))
+ sum = in_cksum_hdr(ip);
+ else
+ sum = in_cksum(m, hlen);
+ }
+ if (sum) {
+ IPSTAT_INC(ips_badsum);
+ goto drop;
+ }
+
+ /*
+ * Remember that we have checked the IP header and found it valid.
+ */
+ m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID);
+
+ ip_len = ntohs(ip->ip_len);
+
+ /*
+ * Is IP length longer than packet we have got?
+ */
+ if (m->m_pkthdr.len < ip_len) {
+ IPSTAT_INC(ips_tooshort);
+ goto drop;
+ }
+
+ /*
+ * Is packet longer than IP header tells us? If yes, truncate packet.
+ */
+ if (m->m_pkthdr.len > ip_len) {
+ if (m->m_len == m->m_pkthdr.len) {
+ m->m_len = ip_len;
+ m->m_pkthdr.len = ip_len;
+ } else
+ m_adj(m, ip_len - m->m_pkthdr.len);
+ }
+
+ /*
+ * Is packet from or to 127/8?
+ */
+ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
+ (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
+ IPSTAT_INC(ips_badaddr);
+ goto drop;
+ }
#ifdef ALTQ
/*
@@ -185,10 +290,12 @@ ip_tryforward(struct mbuf *m)
#endif
/*
- * Only IP packets without options
+ * Step 2: fallback conditions to normal ip_input path processing
*/
- ip = mtod(m, struct ip *);
+ /*
+ * Only IP packets without options
+ */
if (ip->ip_hl != (sizeof(struct ip) >> 2)) {
if (V_ip_doopts == 1)
return m;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 0b29d49..2dc080f 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -77,8 +77,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_carp.h>
#ifdef IPSEC
#include <netinet/ip_ipsec.h>
-#include <netipsec/ipsec.h>
-#include <netipsec/key.h>
#endif /* IPSEC */
#include <sys/socketvar.h>
@@ -466,22 +464,12 @@ tooshort:
} else
m_adj(m, ip_len - m->m_pkthdr.len);
}
- /* Try to forward the packet, but if we fail continue */
#ifdef IPSEC
- /* For now we do not handle IPSEC in tryforward. */
- if (!key_havesp(IPSEC_DIR_INBOUND) && !key_havesp(IPSEC_DIR_OUTBOUND) &&
- (V_ipforwarding == 1))
- if (ip_tryforward(m) == NULL)
- return;
/*
* Bypass packet filtering for packets previously handled by IPsec.
*/
if (ip_ipsec_filtertunnel(m))
goto passin;
-#else
- if (V_ipforwarding == 1)
- if (ip_tryforward(m) == NULL)
- return;
#endif /* IPSEC */
/*
OpenPOWER on IntegriCloud