[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Fri Mar 2 15:39:26 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/73bf3c4ab253
changeset: 386:73bf3c4ab253
user:      ray at terran.dlink.ua
date:      Fri Mar 02 17:11:48 2012 +0200
description:
Update to FreeBSD-HEAD @232391

diffstat:

 head/sys/netinet/in.c                 |   35 +++---
 head/sys/netinet/ip_carp.c            |   75 ++++++++++-----
 head/sys/netinet/ipfw/ip_fw2.c        |   32 +++++-
 head/sys/netinet/ipfw/ip_fw_dynamic.c |  156 +++++++++++++++++----------------
 head/sys/netinet/ipfw/ip_fw_nat.c     |    4 +-
 head/sys/netinet/ipfw/ip_fw_sockopt.c |    4 +-
 head/sys/netinet/sctp_os_bsd.h        |    8 +-
 head/sys/netinet/sctp_output.c        |   91 +++++++++++++-----
 head/sys/netinet/sctp_structs.h       |    4 +-
 head/sys/netinet/sctp_usrreq.c        |    4 +-
 head/sys/netinet/tcp.h                |    6 +-
 head/sys/netinet/tcp_input.c          |   50 +++++-----
 head/sys/netinet/tcp_output.c         |    6 +-
 head/sys/netinet/tcp_seq.h            |   33 ++++++-
 head/sys/netinet/tcp_subr.c           |    4 +-
 head/sys/netinet/tcp_syncache.c       |   20 +++-
 head/sys/netinet/tcp_timer.c          |   23 ++--
 head/sys/netinet/tcp_timer.h          |   10 +-
 head/sys/netinet/tcp_timewait.c       |    4 +-
 head/sys/netinet/tcp_usrreq.c         |   63 ++++++++++++-
 head/sys/netinet/tcp_var.h            |    9 +-
 21 files changed, 419 insertions(+), 222 deletions(-)

diffs (1442 lines):

diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/in.c
--- a/head/sys/netinet/in.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/in.c	Fri Mar 02 17:11:48 2012 +0200
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/in.c 230207 2012-01-16 09:53:24Z glebius $");
+__FBSDID("$FreeBSD: head/sys/netinet/in.c 232054 2012-02-23 18:21:37Z kmacy $");
 
 #include "opt_mpath.h"
 
@@ -879,7 +879,7 @@
 
 		bzero(&ia_ro, sizeof(ia_ro));
 		*((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
-		rtalloc_ign_fib(&ia_ro, 0, 0);
+		rtalloc_ign_fib(&ia_ro, 0, RT_DEFAULT_FIB);
 		if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
 		    (ia_ro.ro_rt->rt_ifp == V_loif)) {
 			RT_LOCK(ia_ro.ro_rt);
@@ -1260,6 +1260,20 @@
 	struct sockaddr_in	l3_addr4;
 };
 
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+static void
+in_lltable_free(struct lltable *llt, struct llentry *lle)
+{
+	LLE_WUNLOCK(lle);
+	LLE_LOCK_DESTROY(lle);
+	free(lle, M_LLTABLE);
+}
+
 static struct llentry *
 in_lltable_new(const struct sockaddr *l3addr, u_int flags)
 {
@@ -1277,25 +1291,11 @@
 	lle->base.la_expire = time_uptime; /* mark expired */
 	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
 	lle->base.lle_refcnt = 1;
+	lle->base.lle_free = in_lltable_free;
 	LLE_LOCK_INIT(&lle->base);
 	return &lle->base;
 }
 
-/*
- * Deletes an address from the address table.
- * This function is called by the timer functions
- * such as arptimer() and nd6_llinfo_timer(), and
- * the caller does the locking.
- */
-static void
-in_lltable_free(struct lltable *llt, struct llentry *lle)
-{
-	LLE_WUNLOCK(lle);
-	LLE_LOCK_DESTROY(lle);
-	free(lle, M_LLTABLE);
-}
-
-
 #define IN_ARE_MASKED_ADDR_EQUAL(d, a, m)	(			\
 	    (((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
 
@@ -1577,7 +1577,6 @@
 
 	llt = lltable_init(ifp, AF_INET);
 	if (llt != NULL) {
-		llt->llt_free = in_lltable_free;
 		llt->llt_prefix_free = in_lltable_prefix_free;
 		llt->llt_lookup = in_lltable_lookup;
 		llt->llt_dump = in_lltable_dump;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/ip_carp.c
--- a/head/sys/netinet/ip_carp.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/ip_carp.c	Fri Mar 02 17:11:48 2012 +0200
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/ip_carp.c 229621 2012-01-05 19:00:36Z jhb $");
+__FBSDID("$FreeBSD: head/sys/netinet/ip_carp.c 231201 2012-02-08 13:39:38Z glebius $");
 
 #include "opt_bpf.h"
 #include "opt_inet.h"
@@ -269,7 +269,9 @@
 static void	carp_send_ad(void *);
 static void	carp_send_ad_locked(struct carp_softc *);
 static void	carp_addroute(struct carp_softc *);
+static void	carp_ifa_addroute(struct ifaddr *);
 static void	carp_delroute(struct carp_softc *);
+static void	carp_ifa_delroute(struct ifaddr *);
 static void	carp_send_ad_all(void *, int);
 static void	carp_demote_adj(int, char *);
 
@@ -705,19 +707,24 @@
 	LIST_FOREACH(sc, &carp_list, sc_next)
 		if (sc->sc_state == MASTER) {
 			CARP_LOCK(sc);
+			CURVNET_SET(sc->sc_carpdev->if_vnet);
 			carp_send_ad_locked(sc);
+			CURVNET_RESTORE();
 			CARP_UNLOCK(sc);
 		}
 	mtx_unlock(&carp_mtx);
 }
 
+/* Send a periodic advertisement, executed in callout context. */
 static void
 carp_send_ad(void *v)
 {
 	struct carp_softc *sc = v;
 
 	CARP_LOCK_ASSERT(sc);
+	CURVNET_SET(sc->sc_carpdev->if_vnet);
 	carp_send_ad_locked(sc);
+	CURVNET_RESTORE();
 	CARP_UNLOCK(sc);
 }
 
@@ -907,22 +914,29 @@
 	struct ifaddr *ifa;
 
 	CARP_FOREACH_IFA(sc, ifa)
-		switch (ifa->ifa_addr->sa_family) {
+		carp_ifa_addroute(ifa);
+}
+
+static void
+carp_ifa_addroute(struct ifaddr *ifa)
+{
+
+	switch (ifa->ifa_addr->sa_family) {
 #ifdef INET
-		case AF_INET:
-			in_addprefix(ifatoia(ifa), RTF_UP);
-			ifa_add_loopback_route(ifa,
-			    (struct sockaddr *)&ifatoia(ifa)->ia_addr);
-			break;
+	case AF_INET:
+		in_addprefix(ifatoia(ifa), RTF_UP);
+		ifa_add_loopback_route(ifa,
+		    (struct sockaddr *)&ifatoia(ifa)->ia_addr);
+		break;
 #endif
 #ifdef INET6
-		case AF_INET6:
-			ifa_add_loopback_route(ifa,
-			    (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
-			in6_ifaddloop(ifa);
-			break;
+	case AF_INET6:
+		ifa_add_loopback_route(ifa,
+		    (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
+		in6_ifaddloop(ifa);
+		break;
 #endif
-		}
+	}
 }
 
 static void
@@ -931,22 +945,29 @@
 	struct ifaddr *ifa;
 
 	CARP_FOREACH_IFA(sc, ifa)
-		switch (ifa->ifa_addr->sa_family) {
+		carp_ifa_delroute(ifa);
+}
+
+static void
+carp_ifa_delroute(struct ifaddr *ifa)
+{
+
+	switch (ifa->ifa_addr->sa_family) {
 #ifdef INET
-		case AF_INET:
-			ifa_del_loopback_route(ifa,
-			    (struct sockaddr *)&ifatoia(ifa)->ia_addr);
-			in_scrubprefix(ifatoia(ifa), LLE_STATIC);
-			break;
+	case AF_INET:
+		ifa_del_loopback_route(ifa,
+		    (struct sockaddr *)&ifatoia(ifa)->ia_addr);
+		in_scrubprefix(ifatoia(ifa), LLE_STATIC);
+		break;
 #endif
 #ifdef INET6
-		case AF_INET6:
-			ifa_del_loopback_route(ifa,
-			    (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
-			in6_ifremloop(ifa);
-			break;
+	case AF_INET6:
+		ifa_del_loopback_route(ifa,
+		    (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
+		in6_ifremloop(ifa);
+		break;
 #endif
-		}
+	}
 }
 
 #ifdef INET
@@ -1074,6 +1095,7 @@
 	return (0);
 }
 
+/* Master down timeout event, executed in callout context. */
 static void
 carp_master_down(void *v)
 {
@@ -1081,12 +1103,14 @@
 
 	CARP_LOCK_ASSERT(sc);
 
+	CURVNET_SET(sc->sc_carpdev->if_vnet);
 	if (sc->sc_state == BACKUP) {
 		CARP_LOG("VHID %u@%s: BACKUP -> MASTER (master down)\n",
 		    sc->sc_vhid,
 		    sc->sc_carpdev->if_xname);
 		carp_master_down_locked(sc);
 	}
+	CURVNET_RESTORE();
 
 	CARP_UNLOCK(sc);
 }
@@ -1856,6 +1880,7 @@
 #endif
 	}
 
+	carp_ifa_delroute(ifa);
 	carp_multicast_cleanup(sc, ifa->ifa_addr->sa_family);
 
 	ifa->ifa_carp = NULL;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/ipfw/ip_fw2.c
--- a/head/sys/netinet/ipfw/ip_fw2.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/ipfw/ip_fw2.c	Fri Mar 02 17:11:48 2012 +0200
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 230452 2012-01-22 10:41:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 231852 2012-02-17 02:39:58Z bz $");
 
 /*
  * The FreeBSD IP packet firewall, main file
@@ -496,7 +496,7 @@
 }
 
 static int
-verify_path6(struct in6_addr *src, struct ifnet *ifp)
+verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
 {
 	struct route_in6 ro;
 	struct sockaddr_in6 *dst;
@@ -507,9 +507,8 @@
 	dst->sin6_family = AF_INET6;
 	dst->sin6_len = sizeof(*dst);
 	dst->sin6_addr = *src;
-	/* XXX MRT 0 for ipv6 at this time */
-	rtalloc_ign((struct route *)&ro, 0);
 
+	in6_rtalloc_ign(&ro, 0, fib);
 	if (ro.ro_rt == NULL)
 		return 0;
 
@@ -1650,8 +1649,22 @@
 				break;
 
 			case O_TCPWIN:
-				match = (proto == IPPROTO_TCP && offset == 0 &&
-				    cmd->arg1 == TCP(ulp)->th_win);
+				if (proto == IPPROTO_TCP && offset == 0) {
+				    uint16_t x;
+				    uint16_t *p;
+				    int i;
+
+				    x = ntohs(TCP(ulp)->th_win);
+				    if (cmdlen == 1) {
+					match = (cmd->arg1 == x);
+					break;
+				    }
+				    /* Otherwise we have ranges. */
+				    p = ((ipfw_insn_u16 *)cmd)->ports;
+				    i = cmdlen - 1;
+				    for (; !match && i > 0; i--, p += 2)
+					match = (x >= p[0] && x <= p[1]);
+				}
 				break;
 
 			case O_ESTAB:
@@ -1701,7 +1714,7 @@
 #ifdef INET6
 				    is_ipv6 ?
 					verify_path6(&(args->f_id.src_ip6),
-					    m->m_pkthdr.rcvif) :
+					    m->m_pkthdr.rcvif, args->f_id.fib) :
 #endif
 				    verify_path(src_ip, m->m_pkthdr.rcvif,
 				        args->f_id.fib)));
@@ -1713,7 +1726,7 @@
 #ifdef INET6
 				    is_ipv6 ?
 				        verify_path6(&(args->f_id.src_ip6),
-				            NULL) :
+				            NULL, args->f_id.fib) :
 #endif
 				    verify_path(src_ip, NULL, args->f_id.fib)));
 				break;
@@ -1731,7 +1744,8 @@
 #ifdef INET6
 					    is_ipv6 ? verify_path6(
 					        &(args->f_id.src_ip6),
-					        m->m_pkthdr.rcvif) :
+					        m->m_pkthdr.rcvif,
+						args->f_id.fib) :
 #endif
 					    verify_path(src_ip,
 					    	m->m_pkthdr.rcvif,
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/ipfw/ip_fw_dynamic.c
--- a/head/sys/netinet/ipfw/ip_fw_dynamic.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/ipfw/ip_fw_dynamic.c	Fri Mar 02 17:11:48 2012 +0200
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_dynamic.c 227085 2011-11-04 16:24:19Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_dynamic.c 232273 2012-02-28 22:00:41Z oleg $");
 
 #define        DEB(x)
 #define        DDB(x) x
@@ -390,72 +390,68 @@
 	IPFW_DYN_UNLOCK();
 }
 
-/**
- * lookup a dynamic rule, locked version
+/*
+ * Lookup a dynamic rule, locked version.
  */
 static ipfw_dyn_rule *
 lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int *match_direction,
     struct tcphdr *tcp)
 {
 	/*
-	 * stateful ipfw extensions.
-	 * Lookup into dynamic session queue
+	 * Stateful ipfw extensions.
+	 * Lookup into dynamic session queue.
 	 */
 #define MATCH_REVERSE	0
 #define MATCH_FORWARD	1
 #define MATCH_NONE	2
 #define MATCH_UNKNOWN	3
 	int i, dir = MATCH_NONE;
-	ipfw_dyn_rule *prev, *q=NULL;
+	ipfw_dyn_rule *prev, *q = NULL;
 
 	IPFW_DYN_LOCK_ASSERT();
 
 	if (V_ipfw_dyn_v == NULL)
-		goto done;	/* not found */
-	i = hash_packet( pkt );
-	for (prev=NULL, q = V_ipfw_dyn_v[i] ; q != NULL ; ) {
+		goto done;				/* not found */
+	i = hash_packet(pkt);
+	for (prev = NULL, q = V_ipfw_dyn_v[i]; q != NULL;) {
 		if (q->dyn_type == O_LIMIT_PARENT && q->count)
 			goto next;
-		if (TIME_LEQ( q->expire, time_uptime)) { /* expire entry */
+		if (TIME_LEQ(q->expire, time_uptime)) {	/* expire entry */
 			UNLINK_DYN_RULE(prev, V_ipfw_dyn_v[i], q);
 			continue;
 		}
-		if (pkt->proto == q->id.proto &&
-		    q->dyn_type != O_LIMIT_PARENT) {
-			if (IS_IP6_FLOW_ID(pkt)) {
-			    if (IN6_ARE_ADDR_EQUAL(&(pkt->src_ip6),
-				&(q->id.src_ip6)) &&
-			    IN6_ARE_ADDR_EQUAL(&(pkt->dst_ip6),
-				&(q->id.dst_ip6)) &&
+		if (pkt->proto != q->id.proto || q->dyn_type == O_LIMIT_PARENT)
+			goto next;
+
+		if (IS_IP6_FLOW_ID(pkt)) {
+			if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.src_ip6) &&
+			    IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.dst_ip6) &&
 			    pkt->src_port == q->id.src_port &&
-			    pkt->dst_port == q->id.dst_port ) {
+			    pkt->dst_port == q->id.dst_port) {
 				dir = MATCH_FORWARD;
 				break;
-			    }
-			    if (IN6_ARE_ADDR_EQUAL(&(pkt->src_ip6),
-				    &(q->id.dst_ip6)) &&
-				IN6_ARE_ADDR_EQUAL(&(pkt->dst_ip6),
-				    &(q->id.src_ip6)) &&
-				pkt->src_port == q->id.dst_port &&
-				pkt->dst_port == q->id.src_port ) {
-				    dir = MATCH_REVERSE;
-				    break;
-			    }
-			} else {
-			    if (pkt->src_ip == q->id.src_ip &&
-				pkt->dst_ip == q->id.dst_ip &&
-				pkt->src_port == q->id.src_port &&
-				pkt->dst_port == q->id.dst_port ) {
-				    dir = MATCH_FORWARD;
-				    break;
-			    }
-			    if (pkt->src_ip == q->id.dst_ip &&
-				pkt->dst_ip == q->id.src_ip &&
-				pkt->src_port == q->id.dst_port &&
-				pkt->dst_port == q->id.src_port ) {
-				    dir = MATCH_REVERSE;
-				    break;
-			    }
+			}
+			if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.dst_ip6) &&
+			    IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.src_ip6) &&
+			    pkt->src_port == q->id.dst_port &&
+			    pkt->dst_port == q->id.src_port) {
+				dir = MATCH_REVERSE;
+				break;
+			}
+		} else {
+			if (pkt->src_ip == q->id.src_ip &&
+			    pkt->dst_ip == q->id.dst_ip &&
+			    pkt->src_port == q->id.src_port &&
+			    pkt->dst_port == q->id.dst_port) {
+				dir = MATCH_FORWARD;
+				break;
+			}
+			if (pkt->src_ip == q->id.dst_ip &&
+			    pkt->dst_ip == q->id.src_ip &&
+			    pkt->src_port == q->id.dst_port &&
+			    pkt->dst_port == q->id.src_port) {
+				dir = MATCH_REVERSE;
+				break;
 			}
 		}
 next:
@@ -463,45 +459,55 @@
 		q = q->next;
 	}
 	if (q == NULL)
-		goto done; /* q = NULL, not found */
+		goto done;	/* q = NULL, not found */
 
-	if ( prev != NULL) { /* found and not in front */
+	if (prev != NULL) {	/* found and not in front */
 		prev->next = q->next;
 		q->next = V_ipfw_dyn_v[i];
 		V_ipfw_dyn_v[i] = q;
 	}
 	if (pkt->proto == IPPROTO_TCP) { /* update state according to flags */
-		u_char flags = pkt->_flags & (TH_FIN|TH_SYN|TH_RST);
+		uint32_t ack;
+		u_char flags = pkt->_flags & (TH_FIN | TH_SYN | TH_RST);
 
 #define BOTH_SYN	(TH_SYN | (TH_SYN << 8))
 #define BOTH_FIN	(TH_FIN | (TH_FIN << 8))
-		q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
-		switch (q->state) {
-		case TH_SYN:				/* opening */
+#define	TCP_FLAGS	(TH_FLAGS | (TH_FLAGS << 8))
+#define	ACK_FWD		0x10000			/* fwd ack seen */
+#define	ACK_REV		0x20000			/* rev ack seen */
+
+		q->state |= (dir == MATCH_FORWARD) ? flags : (flags << 8);
+		switch (q->state & TCP_FLAGS) {
+		case TH_SYN:			/* opening */
 			q->expire = time_uptime + V_dyn_syn_lifetime;
 			break;
 
 		case BOTH_SYN:			/* move to established */
-		case BOTH_SYN | TH_FIN :	/* one side tries to close */
-		case BOTH_SYN | (TH_FIN << 8) :
- 			if (tcp) {
+		case BOTH_SYN | TH_FIN:		/* one side tries to close */
+		case BOTH_SYN | (TH_FIN << 8):
 #define _SEQ_GE(a,b) ((int)(a) - (int)(b) >= 0)
-			    u_int32_t ack = ntohl(tcp->th_ack);
-			    if (dir == MATCH_FORWARD) {
-				if (q->ack_fwd == 0 || _SEQ_GE(ack, q->ack_fwd))
-				    q->ack_fwd = ack;
-				else { /* ignore out-of-sequence */
-				    break;
+			if (tcp == NULL)
+				break;
+
+			ack = ntohl(tcp->th_ack);
+			if (dir == MATCH_FORWARD) {
+				if (q->ack_fwd == 0 ||
+				    _SEQ_GE(ack, q->ack_fwd)) {
+					q->ack_fwd = ack;
+					q->state |= ACK_FWD;
 				}
-			    } else {
-				if (q->ack_rev == 0 || _SEQ_GE(ack, q->ack_rev))
-				    q->ack_rev = ack;
-				else { /* ignore out-of-sequence */
-				    break;
+			} else {
+				if (q->ack_rev == 0 ||
+				    _SEQ_GE(ack, q->ack_rev)) {
+					q->ack_rev = ack;
+					q->state |= ACK_REV;
 				}
-			    }
 			}
-			q->expire = time_uptime + V_dyn_ack_lifetime;
+			if ((q->state & (ACK_FWD | ACK_REV)) ==
+			    (ACK_FWD | ACK_REV)) {
+				q->expire = time_uptime + V_dyn_ack_lifetime;
+				q->state &= ~(ACK_FWD | ACK_REV);
+			}
 			break;
 
 		case BOTH_SYN | BOTH_FIN:	/* both sides closed */
@@ -531,9 +537,9 @@
 		q->expire = time_uptime + V_dyn_short_lifetime;
 	}
 done:
-	if (match_direction)
+	if (match_direction != NULL)
 		*match_direction = dir;
-	return q;
+	return (q);
 }
 
 ipfw_dyn_rule *
@@ -1076,10 +1082,12 @@
 			if (TIME_LEQ(q->expire, time_uptime))
 				continue;	/* too late, rule expired */
 
-			m = ipfw_send_pkt(NULL, &(q->id), q->ack_rev - 1,
-				q->ack_fwd, TH_SYN);
-			mnext = ipfw_send_pkt(NULL, &(q->id), q->ack_fwd - 1,
-				q->ack_rev, 0);
+			m = (q->state & ACK_REV) ? NULL :
+			    ipfw_send_pkt(NULL, &(q->id), q->ack_rev - 1,
+			    q->ack_fwd, TH_SYN);
+			mnext = (q->state & ACK_FWD) ? NULL :
+			    ipfw_send_pkt(NULL, &(q->id), q->ack_fwd - 1,
+			    q->ack_rev, 0);
 
 			switch (q->id.addr_type) {
 			case 4:
@@ -1105,18 +1113,16 @@
 				break;
 #endif
 			}
-
-			m = mnext = NULL;
 		}
 	}
 	IPFW_DYN_UNLOCK();
-	for (m = mnext = m0; m != NULL; m = mnext) {
+	for (m = m0; m != NULL; m = mnext) {
 		mnext = m->m_nextpkt;
 		m->m_nextpkt = NULL;
 		ip_output(m, NULL, NULL, 0, NULL, NULL);
 	}
 #ifdef INET6
-	for (m = mnext = m6; m != NULL; m = mnext) {
+	for (m = m6; m != NULL; m = mnext) {
 		mnext = m->m_nextpkt;
 		m->m_nextpkt = NULL;
 		ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/ipfw/ip_fw_nat.c
--- a/head/sys/netinet/ipfw/ip_fw_nat.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/ipfw/ip_fw_nat.c	Fri Mar 02 17:11:48 2012 +0200
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_nat.c 223080 2011-06-14 13:35:24Z ae $");
+__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_nat.c 231991 2012-02-22 04:19:33Z ae $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -315,7 +315,7 @@
 	}
 
 	if (retval == PKT_ALIAS_RESPOND)
-		m->m_flags |= M_SKIP_FIREWALL;
+		mcl->m_flags |= M_SKIP_FIREWALL;
 	mcl->m_pkthdr.len = mcl->m_len = ntohs(ip->ip_len);
 
 	/*
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/ipfw/ip_fw_sockopt.c
--- a/head/sys/netinet/ipfw/ip_fw_sockopt.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/ipfw/ip_fw_sockopt.c	Fri Mar 02 17:11:48 2012 +0200
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_sockopt.c 227085 2011-11-04 16:24:19Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_sockopt.c 231076 2012-02-06 11:35:29Z glebius $");
 
 /*
  * Sockopt support for ipfw. The routines here implement
@@ -569,7 +569,6 @@
 		case O_IPPRECEDENCE:
 		case O_IPVER:
 		case O_SOCKARG:
-		case O_TCPWIN:
 		case O_TCPFLAGS:
 		case O_TCPOPTS:
 		case O_ESTAB:
@@ -679,6 +678,7 @@
 		case O_IPTTL:
 		case O_IPLEN:
 		case O_TCPDATALEN:
+		case O_TCPWIN:
 		case O_TAGGED:
 			if (cmdlen < 1 || cmdlen > 31)
 				goto bad_size;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/sctp_os_bsd.h
--- a/head/sys/netinet/sctp_os_bsd.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/sctp_os_bsd.h	Fri Mar 02 17:11:48 2012 +0200
@@ -30,7 +30,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_os_bsd.h 221251 2011-04-30 11:22:30Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_os_bsd.h 231852 2012-02-17 02:39:58Z bz $");
 #ifndef __sctp_os_bsd_h__
 #define __sctp_os_bsd_h__
 /*
@@ -424,6 +424,12 @@
 typedef struct route sctp_route_t;
 typedef struct rtentry sctp_rtentry_t;
 
+/*
+ * XXX multi-FIB support was backed out in r179783 and it seems clear that the
+ * VRF support as currently in FreeBSD is not ready to support multi-FIB.
+ * It might be best to implement multi-FIB support for both v4 and v6 indepedent
+ * of VRFs and leave those to a real MPLS stack.
+ */
 #define SCTP_RTALLOC(ro, vrf_id) rtalloc_ign((struct route *)ro, 0UL)
 
 /* Future zero copy wakeup/send  function */
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/sctp_output.c
--- a/head/sys/netinet/sctp_output.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/sctp_output.c	Fri Mar 02 17:11:48 2012 +0200
@@ -33,7 +33,7 @@
 /* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $	 */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 230136 2012-01-15 13:35:55Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 231672 2012-02-14 12:00:34Z tuexen $");
 
 #include <netinet/sctp_os.h>
 #include <sys/proc.h>
@@ -7612,16 +7612,22 @@
 
 	SCTP_TCB_LOCK_ASSERT(stcb);
 	asoc = &stcb->asoc;
+	switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+	case AF_INET:
+		goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+		break;
+#endif
 #ifdef INET6
-	if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
+	case AF_INET6:
 		goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
-	} else {
-		/* ?? not sure what else to do */
-		goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
-	}
-#else
-	goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
-#endif
+		break;
+#endif
+	default:
+		/* TSNH */
+		goal_mtu = net->mtu;
+		break;
+	}
 	/* Need an allowance for the data chunk header too */
 	goal_mtu -= sizeof(struct sctp_data_chunk);
 
@@ -8180,10 +8186,21 @@
 					if (!no_out_cnt)
 						*num_out += ctl_cnt;
 					/* recalc a clean slate and setup */
-					if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
-						mtu = (net->mtu - SCTP_MIN_OVERHEAD);
-					} else {
-						mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+					switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+					case AF_INET:
+						mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+						break;
+#endif
+#ifdef INET6
+					case AF_INET6:
+						mtu = net->mtu - SCTP_MIN_OVERHEAD;
+						break;
+#endif
+					default:
+						/* TSNH */
+						mtu = net->mtu;
+						break;
 					}
 					to_out = 0;
 					no_fragmentflg = 1;
@@ -8446,10 +8463,21 @@
 					if (!no_out_cnt)
 						*num_out += ctl_cnt;
 					/* recalc a clean slate and setup */
-					if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
-						mtu = (net->mtu - SCTP_MIN_OVERHEAD);
-					} else {
-						mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+					switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+					case AF_INET:
+						mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+						break;
+#endif
+#ifdef INET6
+					case AF_INET6:
+						mtu = net->mtu - SCTP_MIN_OVERHEAD;
+						break;
+#endif
+					default:
+						/* TSNH */
+						mtu = net->mtu;
+						break;
 					}
 					to_out = 0;
 					no_fragmentflg = 1;
@@ -9492,10 +9520,21 @@
 		}
 		/* pick up the net */
 		net = chk->whoTo;
-		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
-			mtu = (net->mtu - SCTP_MIN_OVERHEAD);
-		} else {
+		switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+		case AF_INET:
 			mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			mtu = net->mtu - SCTP_MIN_OVERHEAD;
+			break;
+#endif
+		default:
+			/* TSNH */
+			mtu = net->mtu;
+			break;
 		}
 
 		if ((asoc->peers_rwnd < mtu) && (asoc->total_flight > 0)) {
@@ -9816,12 +9855,10 @@
 	return (0);
 }
 
-
-static int
+static void
 sctp_timer_validation(struct sctp_inpcb *inp,
     struct sctp_tcb *stcb,
-    struct sctp_association *asoc,
-    int ret)
+    struct sctp_association *asoc)
 {
 	struct sctp_nets *net;
 
@@ -9829,7 +9866,7 @@
 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
 		if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
 			/* Here is a timer */
-			return (ret);
+			return;
 		}
 	}
 	SCTP_TCB_LOCK_ASSERT(stcb);
@@ -9840,7 +9877,7 @@
 	} else {
 		sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
 	}
-	return (ret);
+	return;
 }
 
 void
@@ -9950,7 +9987,7 @@
 #ifdef SCTP_AUDITING_ENABLED
 			sctp_auditing(8, inp, stcb, NULL);
 #endif
-			(void)sctp_timer_validation(inp, stcb, asoc, ret);
+			sctp_timer_validation(inp, stcb, asoc);
 			return;
 		}
 		if (ret < 0) {
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/sctp_structs.h
--- a/head/sys/netinet/sctp_structs.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/sctp_structs.h	Fri Mar 02 17:11:48 2012 +0200
@@ -33,7 +33,7 @@
 /* $KAME: sctp_structs.h,v 1.13 2005/03/06 16:04:18 itojun Exp $	 */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 228653 2011-12-17 19:21:40Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 231074 2012-02-06 10:47:12Z tuexen $");
 
 #ifndef __sctp_structs_h__
 #define __sctp_structs_h__
@@ -416,7 +416,7 @@
 #define CHUNK_FLAGS_PR_SCTP_BUF	        SCTP_PR_SCTP_BUF
 #define CHUNK_FLAGS_PR_SCTP_RTX         SCTP_PR_SCTP_RTX
 
-/* The upper byte is used a a bit mask */
+/* The upper byte is used as a bit mask */
 #define CHUNK_FLAGS_FRAGMENT_OK	        0x0100
 
 struct chk_id {
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/sctp_usrreq.c
--- a/head/sys/netinet/sctp_usrreq.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/sctp_usrreq.c	Fri Mar 02 17:11:48 2012 +0200
@@ -33,7 +33,7 @@
 /* $KAME: sctp_usrreq.c,v 1.48 2005/03/07 23:26:08 itojun Exp $	 */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 230104 2012-01-14 09:10:20Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 231895 2012-02-18 16:06:15Z tuexen $");
 #include <netinet/sctp_os.h>
 #include <sys/proc.h>
 #include <netinet/sctp_pcb.h>
@@ -6357,7 +6357,7 @@
 int
 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
 {
-	struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
+	struct sockaddr_in *sin;
 	int fnd;
 	struct sockaddr_in *sin_a;
 	struct sctp_inpcb *inp;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp.h
--- a/head/sys/netinet/tcp.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp.h	Fri Mar 02 17:11:48 2012 +0200
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tcp.h	8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/netinet/tcp.h 226610 2011-10-21 12:58:34Z ed $
+ * $FreeBSD: head/sys/netinet/tcp.h 231025 2012-02-05 16:53:02Z glebius $
  */
 
 #ifndef _NETINET_TCP_H_
@@ -159,6 +159,10 @@
 #define TCP_MD5SIG	0x10	/* use MD5 digests (RFC2385) */
 #define	TCP_INFO	0x20	/* retrieve tcp_info structure */
 #define	TCP_CONGESTION	0x40	/* get/set congestion control algorithm */
+#define	TCP_KEEPINIT	0x80	/* N, time to establish connection */
+#define	TCP_KEEPIDLE	0x100	/* L,N,X start keeplives after this period */
+#define	TCP_KEEPINTVL	0x200	/* L,N interval between keepalives */
+#define	TCP_KEEPCNT	0x400	/* L,N number of keepalives before close */
 
 #define	TCP_CA_NAME_MAX	16	/* max congestion control name length */
 
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_input.c
--- a/head/sys/netinet/tcp_input.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_input.c	Fri Mar 02 17:11:48 2012 +0200
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_input.c 229665 2012-01-05 22:29:11Z jhb $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_input.c 231767 2012-02-15 16:09:56Z bz $");
 
 #include "opt_ipfw.h"		/* for ipfw_fwd	*/
 #include "opt_inet.h"
@@ -1446,7 +1446,7 @@
 	 */
 	tp->t_rcvtime = ticks;
 	if (TCPS_HAVEESTABLISHED(tp->t_state))
-		tcp_timer_activate(tp, TT_KEEP, tcp_keepidle);
+		tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
 
 	/*
 	 * Unscale the window into a 32-bit value.
@@ -1493,7 +1493,7 @@
 	 */
 	if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
 		to.to_tsecr -= tp->ts_offset;
-		if (TSTMP_GT(to.to_tsecr, ticks))
+		if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
 			to.to_tsecr = 0;
 	}
 
@@ -1518,7 +1518,7 @@
 		if (to.to_flags & TOF_TS) {
 			tp->t_flags |= TF_RCVD_TSTMP;
 			tp->ts_recent = to.to_tsval;
-			tp->ts_recent_age = ticks;
+			tp->ts_recent_age = tcp_ts_getticks();
 		}
 		if (to.to_flags & TOF_MSS)
 			tcp_mss(tp, to.to_mss);
@@ -1562,7 +1562,7 @@
 		 */
 		if ((to.to_flags & TOF_TS) != 0 &&
 		    SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
-			tp->ts_recent_age = ticks;
+			tp->ts_recent_age = tcp_ts_getticks();
 			tp->ts_recent = to.to_tsval;
 		}
 
@@ -1600,11 +1600,13 @@
 				 */
 				if ((to.to_flags & TOF_TS) != 0 &&
 				    to.to_tsecr) {
-					if (!tp->t_rttlow ||
-					    tp->t_rttlow > ticks - to.to_tsecr)
-						tp->t_rttlow = ticks - to.to_tsecr;
+					u_int t;
+
+					t = tcp_ts_getticks() - to.to_tsecr;
+					if (!tp->t_rttlow || tp->t_rttlow > t)
+						tp->t_rttlow = t;
 					tcp_xmit_timer(tp,
-					    ticks - to.to_tsecr + 1);
+					    TCP_TS_TO_TICKS(t) + 1);
 				} else if (tp->t_rtttime &&
 				    SEQ_GT(th->th_ack, tp->t_rtseq)) {
 					if (!tp->t_rttlow ||
@@ -1889,7 +1891,8 @@
 			} else {
 				tp->t_state = TCPS_ESTABLISHED;
 				cc_conn_init(tp);
-				tcp_timer_activate(tp, TT_KEEP, tcp_keepidle);
+				tcp_timer_activate(tp, TT_KEEP,
+				    TP_KEEPIDLE(tp));
 			}
 		} else {
 			/*
@@ -2069,7 +2072,7 @@
 	    TSTMP_LT(to.to_tsval, tp->ts_recent)) {
 
 		/* Check to see if ts_recent is over 24 days old.  */
-		if (ticks - tp->ts_recent_age > TCP_PAWS_IDLE) {
+		if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) {
 			/*
 			 * Invalidate ts_recent.  If this segment updates
 			 * ts_recent, the age will be reset later and ts_recent
@@ -2228,7 +2231,7 @@
 	    SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
 	    SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
 		((thflags & (TH_SYN|TH_FIN)) != 0))) {
-		tp->ts_recent_age = ticks;
+		tp->ts_recent_age = tcp_ts_getticks();
 		tp->ts_recent = to.to_tsval;
 	}
 
@@ -2293,7 +2296,7 @@
 		} else {
 			tp->t_state = TCPS_ESTABLISHED;
 			cc_conn_init(tp);
-			tcp_timer_activate(tp, TT_KEEP, tcp_keepidle);
+			tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
 		}
 		/*
 		 * If segment contains data or ACK, will call tcp_reass()
@@ -2542,11 +2545,13 @@
 		 * timestamps of 0 or we could calculate a
 		 * huge RTT and blow up the retransmit timer.
 		 */
-		if ((to.to_flags & TOF_TS) != 0 &&
-		    to.to_tsecr) {
-			if (!tp->t_rttlow || tp->t_rttlow > ticks - to.to_tsecr)
-				tp->t_rttlow = ticks - to.to_tsecr;
-			tcp_xmit_timer(tp, ticks - to.to_tsecr + 1);
+		if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) {
+			u_int t;
+
+			t = tcp_ts_getticks() - to.to_tsecr;
+			if (!tp->t_rttlow || tp->t_rttlow > t)
+				tp->t_rttlow = t;
+			tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1);
 		} else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) {
 			if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime)
 				tp->t_rttlow = ticks - tp->t_rtttime;
@@ -2630,12 +2635,11 @@
 				 * compressed state.
 				 */
 				if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
-					int timeout;
-
 					soisdisconnected(so);
-					timeout = (tcp_fast_finwait2_recycle) ? 
-						tcp_finwait2_timeout : tcp_maxidle;
-					tcp_timer_activate(tp, TT_2MSL, timeout);
+					tcp_timer_activate(tp, TT_2MSL,
+					    (tcp_fast_finwait2_recycle ?
+					    tcp_finwait2_timeout :
+					    TP_MAXIDLE(tp)));
 				}
 				tp->t_state = TCPS_FIN_WAIT_2;
 			}
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_output.c
--- a/head/sys/netinet/tcp_output.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_output.c	Fri Mar 02 17:11:48 2012 +0200
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_output.c 227034 2011-11-02 20:58:47Z pluknet $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_output.c 231767 2012-02-15 16:09:56Z bz $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -680,13 +680,13 @@
 		/* Timestamps. */
 		if ((tp->t_flags & TF_RCVD_TSTMP) ||
 		    ((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) {
-			to.to_tsval = ticks + tp->ts_offset;
+			to.to_tsval = tcp_ts_getticks() + tp->ts_offset;
 			to.to_tsecr = tp->ts_recent;
 			to.to_flags |= TOF_TS;
 			/* Set receive buffer autosizing timestamp. */
 			if (tp->rfbuf_ts == 0 &&
 			    (so->so_rcv.sb_flags & SB_AUTOSIZE))
-				tp->rfbuf_ts = ticks;
+				tp->rfbuf_ts = tcp_ts_getticks();
 		}
 		/* Selective ACK's. */
 		if (tp->t_flags & TF_SACK_PERMIT) {
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_seq.h
--- a/head/sys/netinet/tcp_seq.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_seq.h	Fri Mar 02 17:11:48 2012 +0200
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tcp_seq.h	8.3 (Berkeley) 6/21/95
- * $FreeBSD$
+ * $FreeBSD: head/sys/netinet/tcp_seq.h 231767 2012-02-15 16:09:56Z bz $
  */
 
 #ifndef _NETINET_TCP_SEQ_H_
@@ -62,7 +62,34 @@
 	(tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \
 	    (tp)->snd_recover = (tp)->iss
 
-#define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * hz)
-					/* timestamp wrap-around time */
+#ifdef _KERNEL
+/*
+ * Clock macros for RFC 1323 timestamps.
+ */
+#define	TCP_TS_TO_TICKS(_t)	((_t) * hz / 1000)
+
+/* Timestamp wrap-around time, 24 days. */
+#define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * 1000)
+
+/*
+ * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323.
+ * We always use 1ms granularity independent of hz.
+ */
+static __inline u_int
+tcp_ts_getticks(void)
+{
+	struct timeval tv;
+	u_long ms;
+
+	/*
+	 * getmicrouptime() should be good enough for any 1-1000ms granularity.
+	 * Do not use getmicrotime() here as it might break nfsroot/tcp.
+	 */
+	getmicrouptime(&tv);
+	ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+
+	return (ms);
+}
+#endif /* _KERNEL */
 
 #endif /* _NETINET_TCP_SEQ_H_ */
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_subr.c
--- a/head/sys/netinet/tcp_subr.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_subr.c	Fri Mar 02 17:11:48 2012 +0200
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_subr.c 224010 2011-07-14 13:44:48Z bz $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_subr.c 231852 2012-02-17 02:39:58Z bz $");
 
 #include "opt_compat.h"
 #include "opt_inet.h"
@@ -1750,7 +1750,7 @@
 		sro6.ro_dst.sin6_family = AF_INET6;
 		sro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
 		sro6.ro_dst.sin6_addr = inc->inc6_faddr;
-		rtalloc_ign((struct route *)&sro6, 0);
+		in6_rtalloc_ign(&sro6, 0, inc->inc_fibnum);
 	}
 	if (sro6.ro_rt != NULL) {
 		ifp = sro6.ro_rt->rt_ifp;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_syncache.c
--- a/head/sys/netinet/tcp_syncache.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_syncache.c	Fri Mar 02 17:11:48 2012 +0200
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_syncache.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_syncache.c 231767 2012-02-15 16:09:56Z bz $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -819,7 +819,7 @@
 		if (sc->sc_flags & SCF_TIMESTAMP) {
 			tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP;
 			tp->ts_recent = sc->sc_tsreflect;
-			tp->ts_recent_age = ticks;
+			tp->ts_recent_age = tcp_ts_getticks();
 			tp->ts_offset = sc->sc_tsoff;
 		}
 #ifdef TCP_SIGNATURE
@@ -845,7 +845,15 @@
 	 */
 	if (sc->sc_rxmits > 1)
 		tp->snd_cwnd = tp->t_maxseg;
-	tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
+
+	/*
+	 * Copy and activate timers.
+	 */
+	tp->t_keepinit = sototcpcb(lso)->t_keepinit;
+	tp->t_keepidle = sototcpcb(lso)->t_keepidle;
+	tp->t_keepintvl = sototcpcb(lso)->t_keepintvl;
+	tp->t_keepcnt = sototcpcb(lso)->t_keepcnt;
+	tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
 
 	INP_WUNLOCK(inp);
 
@@ -1218,7 +1226,7 @@
 		 */
 		if (to->to_flags & TOF_TS) {
 			sc->sc_tsreflect = to->to_tsval;
-			sc->sc_ts = ticks;
+			sc->sc_ts = tcp_ts_getticks();
 			sc->sc_flags |= SCF_TIMESTAMP;
 		}
 		if (to->to_flags & TOF_SCALE) {
@@ -1659,7 +1667,7 @@
 		data |= md5_buffer[2] << 10;		/* more digest bits */
 		data ^= md5_buffer[3];
 		sc->sc_ts = data;
-		sc->sc_tsoff = data - ticks;		/* after XOR */
+		sc->sc_tsoff = data - tcp_ts_getticks();	/* after XOR */
 	}
 
 	TCPSTAT_INC(tcps_sc_sendcookie);
@@ -1744,7 +1752,7 @@
 		sc->sc_flags |= SCF_TIMESTAMP;
 		sc->sc_tsreflect = to->to_tsval;
 		sc->sc_ts = to->to_tsecr;
-		sc->sc_tsoff = to->to_tsecr - ticks;
+		sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks();
 		sc->sc_flags |= (data & 0x1) ? SCF_SIGNATURE : 0;
 		sc->sc_flags |= ((data >> 1) & 0x1) ? SCF_SACK : 0;
 		sc->sc_requested_s_scale = min((data >> 2) & 0xf,
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_timer.c
--- a/head/sys/netinet/tcp_timer.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_timer.c	Fri Mar 02 17:11:48 2012 +0200
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_timer.c 226318 2011-10-12 19:52:23Z np $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_timer.c 231025 2012-02-05 16:53:02Z glebius $");
 
 #include "opt_inet6.h"
 #include "opt_tcpdebug.h"
@@ -111,12 +111,12 @@
 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW,
     &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", "FIN-WAIT2 timeout");
 
+int	tcp_keepcnt = TCPTV_KEEPCNT;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
+    "Number of keepalive probes to send");
 
-static int	tcp_keepcnt = TCPTV_KEEPCNT;
 	/* max idle probes */
 int	tcp_maxpersistidle;
-	/* max idle time in persist */
-int	tcp_maxidle;
 
 static int	per_cpu_timers = 0;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
@@ -138,7 +138,6 @@
 	VNET_LIST_RLOCK_NOSLEEP();
 	VNET_FOREACH(vnet_iter) {
 		CURVNET_SET(vnet_iter);
-		tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
 		INP_INFO_WLOCK(&V_tcbinfo);
 		(void) tcp_tw_2msl_scan(0);
 		INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -255,9 +254,9 @@
 		tp = tcp_close(tp);             
 	} else {
 		if (tp->t_state != TCPS_TIME_WAIT &&
-		   ticks - tp->t_rcvtime <= tcp_maxidle)
-		       callout_reset_on(&tp->t_timers->tt_2msl, tcp_keepintvl,
-			   tcp_timer_2msl, tp, INP_CPU(inp));
+		   ticks - tp->t_rcvtime <= TP_MAXIDLE(tp))
+		       callout_reset_on(&tp->t_timers->tt_2msl,
+			   TP_KEEPINTVL(tp), tcp_timer_2msl, tp, INP_CPU(inp));
 	       else
 		       tp = tcp_close(tp);
        }
@@ -318,7 +317,7 @@
 		goto dropit;
 	if ((always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) &&
 	    tp->t_state <= TCPS_CLOSING) {
-		if (ticks - tp->t_rcvtime >= tcp_keepidle + tcp_maxidle)
+		if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
 			goto dropit;
 		/*
 		 * Send a packet designed to force a response
@@ -340,9 +339,11 @@
 				    tp->rcv_nxt, tp->snd_una - 1, 0);
 			free(t_template, M_TEMP);
 		}
-		callout_reset_on(&tp->t_timers->tt_keep, tcp_keepintvl, tcp_timer_keep, tp, INP_CPU(inp));
+		callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp),
+		    tcp_timer_keep, tp, INP_CPU(inp));
 	} else
-		callout_reset_on(&tp->t_timers->tt_keep, tcp_keepidle, tcp_timer_keep, tp, INP_CPU(inp));
+		callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp),
+		    tcp_timer_keep, tp, INP_CPU(inp));
 
 #ifdef TCPDEBUG
 	if (inp->inp_socket->so_options & SO_DEBUG)
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_timer.h
--- a/head/sys/netinet/tcp_timer.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_timer.h	Fri Mar 02 17:11:48 2012 +0200
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tcp_timer.h	8.1 (Berkeley) 6/10/93
- * $FreeBSD$
+ * $FreeBSD: head/sys/netinet/tcp_timer.h 231025 2012-02-05 16:53:02Z glebius $
  */
 
 #ifndef _NETINET_TCP_TIMER_H_
@@ -153,10 +153,16 @@
 #define TT_KEEP		0x08
 #define TT_2MSL		0x10
 
+#define	TP_KEEPINIT(tp)	((tp)->t_keepinit ? (tp)->t_keepinit : tcp_keepinit)
+#define	TP_KEEPIDLE(tp)	((tp)->t_keepidle ? (tp)->t_keepidle : tcp_keepidle)
+#define	TP_KEEPINTVL(tp) ((tp)->t_keepintvl ? (tp)->t_keepintvl : tcp_keepintvl)
+#define	TP_KEEPCNT(tp)	((tp)->t_keepcnt ? (tp)->t_keepcnt : tcp_keepcnt)
+#define	TP_MAXIDLE(tp)	(TP_KEEPCNT(tp) * TP_KEEPINTVL(tp))
+
 extern int tcp_keepinit;		/* time to establish connection */
 extern int tcp_keepidle;		/* time before keepalive probes begin */
 extern int tcp_keepintvl;		/* time between keepalive probes */
-extern int tcp_maxidle;			/* time to drop after starting probes */
+extern int tcp_keepcnt;			/* number of keepalives */
 extern int tcp_delacktime;		/* time before sending a delayed ACK */
 extern int tcp_maxpersistidle;
 extern int tcp_rexmit_min;
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_timewait.c
--- a/head/sys/netinet/tcp_timewait.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_timewait.c	Fri Mar 02 17:11:48 2012 +0200
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_timewait.c 229700 2012-01-06 12:49:01Z jhb $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_timewait.c 231767 2012-02-15 16:09:56Z bz $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -558,7 +558,7 @@
 	 */
 	if (tw->t_recent && flags == TH_ACK) {
 		to.to_flags |= TOF_TS;
-		to.to_tsval = ticks + tw->ts_offset;
+		to.to_tsval = tcp_ts_getticks() + tw->ts_offset;
 		to.to_tsecr = tw->t_recent;
 	}
 	optlen = tcp_addoptions(&to, (u_char *)(th + 1));
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_usrreq.c
--- a/head/sys/netinet/tcp_usrreq.c	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_usrreq.c	Fri Mar 02 17:11:48 2012 +0200
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/tcp_usrreq.c 229714 2012-01-06 18:29:40Z np $");
+__FBSDID("$FreeBSD: head/sys/netinet/tcp_usrreq.c 231025 2012-02-05 16:53:02Z glebius $");
 
 #include "opt_ddb.h"
 #include "opt_inet.h"
@@ -45,6 +45,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/limits.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
@@ -1118,7 +1119,7 @@
 	soisconnecting(so);
 	TCPSTAT_INC(tcps_connattempt);
 	tp->t_state = TCPS_SYN_SENT;
-	tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
+	tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
 	tp->iss = tcp_new_isn(tp);
 	tcp_sendseqinit(tp);
 
@@ -1191,7 +1192,7 @@
 	soisconnecting(so);
 	TCPSTAT_INC(tcps_connattempt);
 	tp->t_state = TCPS_SYN_SENT;
-	tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
+	tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
 	tp->iss = tcp_new_isn(tp);
 	tcp_sendseqinit(tp);
 
@@ -1272,6 +1273,7 @@
 tcp_ctloutput(struct socket *so, struct sockopt *sopt)
 {
 	int	error, opt, optval;
+	u_int	ui;
 	struct	inpcb *inp;
 	struct	tcpcb *tp;
 	struct	tcp_info ti;
@@ -1439,6 +1441,59 @@
 			INP_WUNLOCK(inp);
 			break;
 
+		case TCP_KEEPIDLE:
+		case TCP_KEEPINTVL:
+		case TCP_KEEPCNT:
+		case TCP_KEEPINIT:
+			INP_WUNLOCK(inp);
+			error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui));
+			if (error)
+				return (error);
+
+			if (ui > (UINT_MAX / hz)) {
+				error = EINVAL;
+				break;
+			}
+			ui *= hz;
+
+			INP_WLOCK_RECHECK(inp);
+			switch (sopt->sopt_name) {
+			case TCP_KEEPIDLE:
+				tp->t_keepidle = ui;
+				/*
+				 * XXX: better check current remaining
+				 * timeout and "merge" it with new value.
+				 */
+				if ((tp->t_state > TCPS_LISTEN) &&
+				    (tp->t_state <= TCPS_CLOSING))
+					tcp_timer_activate(tp, TT_KEEP,
+					    TP_KEEPIDLE(tp));
+				break;
+			case TCP_KEEPINTVL:
+				tp->t_keepintvl = ui;
+				if ((tp->t_state == TCPS_FIN_WAIT_2) &&
+				    (TP_MAXIDLE(tp) > 0))
+					tcp_timer_activate(tp, TT_2MSL,
+					    TP_MAXIDLE(tp));
+				break;
+			case TCP_KEEPCNT:
+				tp->t_keepcnt = ui;
+				if ((tp->t_state == TCPS_FIN_WAIT_2) &&
+				    (TP_MAXIDLE(tp) > 0))
+					tcp_timer_activate(tp, TT_2MSL,
+					    TP_MAXIDLE(tp));
+				break;
+			case TCP_KEEPINIT:
+				tp->t_keepinit = ui;
+				if (tp->t_state == TCPS_SYN_RECEIVED ||
+				    tp->t_state == TCPS_SYN_SENT)
+					tcp_timer_activate(tp, TT_KEEP,
+					    TP_KEEPINIT(tp));
+				break;
+			}
+			INP_WUNLOCK(inp);
+			break;
+
 		default:
 			INP_WUNLOCK(inp);
 			error = ENOPROTOOPT;
@@ -1636,7 +1691,7 @@
 			int timeout;
 
 			timeout = (tcp_fast_finwait2_recycle) ? 
-			    tcp_finwait2_timeout : tcp_maxidle;
+			    tcp_finwait2_timeout : TP_MAXIDLE(tp);
 			tcp_timer_activate(tp, TT_2MSL, timeout);
 		}
 	}
diff -r 9de13f80a66c -r 73bf3c4ab253 head/sys/netinet/tcp_var.h
--- a/head/sys/netinet/tcp_var.h	Fri Mar 02 17:11:25 2012 +0200
+++ b/head/sys/netinet/tcp_var.h	Fri Mar 02 17:11:48 2012 +0200
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tcp_var.h	8.4 (Berkeley) 5/24/95
- * $FreeBSD: head/sys/netinet/tcp_var.h 226447 2011-10-16 20:06:44Z andre $
+ * $FreeBSD: head/sys/netinet/tcp_var.h 231025 2012-02-05 16:53:02Z glebius $
  */
 
 #ifndef _NETINET_TCP_VAR_H_
@@ -203,7 +203,12 @@
 	struct cc_var	*ccv;		/* congestion control specific vars */
 	struct osd	*osd;		/* storage for Khelp module data */
 
-	uint32_t t_ispare[12];		/* 4 keep timers, 5 UTO, 3 TBD */
+	u_int	t_keepinit;		/* time to establish connection */
+	u_int	t_keepidle;		/* time before keepalive probes begin */
+	u_int	t_keepintvl;		/* interval between keepalives */
+	u_int	t_keepcnt;		/* number of keepalives before close */
+
+	uint32_t t_ispare[8];		/* 5 UTO, 3 TBD */
 	void	*t_pspare2[4];		/* 4 TBD */
 	uint64_t _pad[6];		/* 6 TBD (1-2 CC/RTT?) */
 };


More information about the Zrouter-src-freebsd mailing list