diff --git a/bsd/sys/netinet/tcp.h b/bsd/sys/netinet/tcp.h
index c714360c164460cae1083d44260b1c342a5261f0..31f6eb25c9c90913a339c9dba0ddffb369c65a9b 100644
--- a/bsd/sys/netinet/tcp.h
+++ b/bsd/sys/netinet/tcp.h
@@ -35,10 +35,40 @@
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
+#include <bsd/sys/sys/param.h>
 
 #if __BSD_VISIBLE
 
-typedef	u_int32_t tcp_seq;
+class tcp_seq {
+public:
+	tcp_seq() {}
+	explicit tcp_seq(u_int32_t raw) : _raw(raw) {}
+	tcp_seq& operator=(const tcp_seq&) = default;
+	u_int32_t raw() const { return _raw; }
+	void to_host() { _raw = ntohl(_raw); }
+	void to_net() { _raw = htonl(_raw); }
+	tcp_seq& operator+=(uint32_t delta) { _raw += delta; return *this; }
+	tcp_seq& operator-=(uint32_t delta) { _raw -= delta; return *this; }
+	tcp_seq operator++(int) { return tcp_seq(_raw++); }
+	tcp_seq operator--(int) { return tcp_seq(_raw--); }
+	friend inline bool operator==(tcp_seq a, tcp_seq b) { return a._raw == b._raw; }
+	friend inline bool operator!=(tcp_seq a, tcp_seq b) { return a._raw != b._raw; }
+	friend inline u_int32_t operator-(tcp_seq a, tcp_seq b) { return a._raw - b._raw; }
+	friend inline tcp_seq operator+(tcp_seq a, u_int32_t delta) { return a += delta; }
+	friend inline tcp_seq operator-(tcp_seq a, u_int32_t delta) { return a -= delta; }
+private:
+	u_int32_t _raw;
+};
+
+inline tcp_seq __ntohl(tcp_seq s)
+{
+	return tcp_seq(ntohl(s.raw()));
+}
+
+inline tcp_seq __htonl(tcp_seq s)
+{
+	return tcp_seq(htonl(s.raw()));
+}
 
 #define tcp6_seq	tcp_seq	/* for KAME src sync over BSD*'s */
 #define tcp6hdr		tcphdr	/* for KAME src sync over BSD*'s */
diff --git a/bsd/sys/netinet/tcp_input.cc b/bsd/sys/netinet/tcp_input.cc
index 289c7dc244043ea6759ee8adba7c6c54623a2f08..6b9b52de563fa5c57f7a5799aea6af6f063f38aa 100644
--- a/bsd/sys/netinet/tcp_input.cc
+++ b/bsd/sys/netinet/tcp_input.cc
@@ -1429,7 +1429,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 	short ostate = 0;
 #endif
 	thflags = th->th_flags;
-	tp->sackhint.last_sack_ack = 0;
+	tp->sackhint.last_sack_ack = tcp_seq(0);
 
 	/*
 	 * If this is either a state-changing packet or current state isn't
diff --git a/bsd/sys/netinet/tcp_lro.h b/bsd/sys/netinet/tcp_lro.h
index f38ceb376316c12cc0ce3bb8e00a742b34e33d6b..ca81237b124079c4be7a58441360b438bf36d02c 100644
--- a/bsd/sys/netinet/tcp_lro.h
+++ b/bsd/sys/netinet/tcp_lro.h
@@ -58,8 +58,8 @@ struct lro_entry
 	uint16_t		append_cnt;
 	uint32_t		p_len;		/* IP header payload length. */
 	uint32_t		ulp_csum;	/* TCP, etc. checksum. */
-	uint32_t		next_seq;	/* tcp_seq */
-	uint32_t		ack_seq;	/* tcp_seq */
+	tcp_seq			next_seq;	/* tcp_seq */
+	tcp_seq			ack_seq;	/* tcp_seq */
 	uint32_t		tsval;
 	uint32_t		tsecr;
 	uint16_t		window;
diff --git a/bsd/sys/netinet/tcp_sack.cc b/bsd/sys/netinet/tcp_sack.cc
index d01ef3b1e55a20d14ee392b1cd086a122943bec7..d31c81c189f81e65592f34fa5a2e10305ca0a63d 100644
--- a/bsd/sys/netinet/tcp_sack.cc
+++ b/bsd/sys/netinet/tcp_sack.cc
@@ -247,7 +247,7 @@ tcp_clean_sackreport(struct tcpcb *tp)
 	INP_WLOCK_ASSERT(tp->t_inpcb);
 	tp->rcv_numsacks = 0;
 	for (i = 0; i < MAX_SACK_BLKS; i++)
-		tp->sackblks[i].start = tp->sackblks[i].end=0;
+		tp->sackblks[i].start = tp->sackblks[i].end = tcp_seq(0);
 }
 
 /*
diff --git a/bsd/sys/netinet/tcp_seq.h b/bsd/sys/netinet/tcp_seq.h
index 51d971f22bee43cb9721ec0c550ff4c7bbe47070..0c5cc726c3957acf61a97027884c8e9fbc362cd5 100644
--- a/bsd/sys/netinet/tcp_seq.h
+++ b/bsd/sys/netinet/tcp_seq.h
@@ -37,10 +37,10 @@
  * on with modular arithmetic.  These macros can be
  * used to compare such integers.
  */
-#define	SEQ_LT(a,b)	((int)((a)-(b)) < 0)
-#define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
-#define	SEQ_GT(a,b)	((int)((a)-(b)) > 0)
-#define	SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
+#define	SEQ_LT(a,b)	((int)((a).raw()-(b).raw()) < 0)
+#define	SEQ_LEQ(a,b)	((int)((a).raw()-(b).raw()) <= 0)
+#define	SEQ_GT(a,b)	((int)((a).raw()-(b).raw()) > 0)
+#define	SEQ_GEQ(a,b)	((int)((a).raw()-(b).raw()) >= 0)
 
 #define	SEQ_MIN(a, b)	((SEQ_LT(a, b)) ? (a) : (b))
 #define	SEQ_MAX(a, b)	((SEQ_GT(a, b)) ? (a) : (b))
diff --git a/bsd/sys/netinet/tcp_subr.cc b/bsd/sys/netinet/tcp_subr.cc
index 2f5d7aef4904b69556ab33e3a14f56737dbf6c1c..82f806d2501ce521a9b7f3110222d648a2e664c1 100644
--- a/bsd/sys/netinet/tcp_subr.cc
+++ b/bsd/sys/netinet/tcp_subr.cc
@@ -416,8 +416,8 @@ tcpip_fillheaders(struct inpcb *inp, void *ip_ptr, void *tcp_ptr)
 #endif /* INET */
 	th->th_sport = inp->inp_lport;
 	th->th_dport = inp->inp_fport;
-	th->th_seq = 0;
-	th->th_ack = 0;
+	th->th_seq = tcp_seq(0);
+	th->th_ack = tcp_seq(0);
 	th->th_x2 = 0;
 	th->th_off = 5;
 	th->th_flags = 0;
@@ -1588,7 +1588,7 @@ tcp_new_isn(struct tcpcb *tp)
 	if (bsd_ticks != V_isn_last) {
 		projected_offset = V_isn_offset_old +
 		    ISN_BYTES_PER_SECOND / hz * (bsd_ticks - V_isn_last);
-		if (SEQ_GT(projected_offset, V_isn_offset))
+		if (SEQ_GT(tcp_seq(projected_offset), tcp_seq(V_isn_offset)))
 			V_isn_offset = projected_offset;
 		V_isn_offset_old = V_isn_offset;
 		V_isn_last = bsd_ticks;
diff --git a/bsd/sys/netinet/tcp_syncache.cc b/bsd/sys/netinet/tcp_syncache.cc
index e8c0d299755070c9da76c1237acceecc9bf621ff..8fb8bb09dbdf5246384ca95a93d1d23cb0e0cc2e 100644
--- a/bsd/sys/netinet/tcp_syncache.cc
+++ b/bsd/sys/netinet/tcp_syncache.cc
@@ -1158,7 +1158,7 @@ static void _syncache_add(struct in_conninfo *inc, struct tcpopt *to,
 	sc->sc_toepcb = toepcb;
 #endif
 	sc->sc_irs = th->th_seq;
-	sc->sc_iss = arc4random();
+	sc->sc_iss = tcp_seq(arc4random());
 	sc->sc_flags = 0;
 	sc->sc_flowlabel = 0;
 
@@ -1572,7 +1572,7 @@ static void syncookie_generate(struct syncache_head *sch, struct syncache *sc,
 	}
 
 	/* Secret rotation offset. */
-	off = sc->sc_iss & 0x7; /* iss was randomized before */
+	off = sc->sc_iss.raw() & 0x7; /* iss was randomized before */
 
 	/* Maximum segment size calculation. */
 	pmss = bsd_max(bsd_min(sc->sc_peer_mss, tcp_mssopt(&sc->sc_inc)), V_tcp_minmss);
@@ -1595,7 +1595,7 @@ static void syncookie_generate(struct syncache_head *sch, struct syncache *sc,
 	MD5Final((u_int8_t *)&md5_buffer, &ctx);
 
 	data |= (md5_buffer[0] << 7);
-	sc->sc_iss = data;
+	sc->sc_iss = tcp_seq(data);
 
 #ifdef INET6
 	*flowlabel = md5_buffer[1] & IPV6_FLOWLABEL_MASK;
@@ -1625,7 +1625,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
 	u_int32_t md5_buffer[MD5_DIGEST_LENGTH / sizeof(u_int32_t)];
 	u_int32_t data = 0;
 	u_int32_t *secbits;
-	tcp_seq ack, seq;
+	u_int32_t ack, seq;
 	int off, mss, wnd, flags;
 
 	SCH_LOCK_ASSERT(sch);
@@ -1634,8 +1634,8 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
 	 * Pull information out of SYN-ACK/ACK and
 	 * revert sequence number advances.
 	 */
-	ack = th->th_ack - 1;
-	seq = th->th_seq - 1;
+	ack = th->th_ack.raw() - 1;
+	seq = th->th_seq.raw() - 1;
 	off = (ack >> 1) & 0x7;
 	mss = (ack >> 4) & 0x7;
 	flags = ack & 0x7f;
@@ -1676,8 +1676,8 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
 	bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo));
 	sc->sc_ipopts = NULL;
 
-	sc->sc_irs = seq;
-	sc->sc_iss = ack;
+	sc->sc_irs = tcp_seq(seq);
+	sc->sc_iss = tcp_seq(ack);
 
 #ifdef INET6
 	if (inc->inc_flags & INC_ISIPV6) {
diff --git a/bsd/sys/netinet/tcp_usrreq.cc b/bsd/sys/netinet/tcp_usrreq.cc
index 151a6caf876402add01a3ce9e76dcb60905ef671..8954e19a5fc6b7b1c023c58a731dd131c43d9b82 100644
--- a/bsd/sys/netinet/tcp_usrreq.cc
+++ b/bsd/sys/netinet/tcp_usrreq.cc
@@ -1233,10 +1233,10 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
 	 * FreeBSD-specific extension fields for tcp_info.
 	 */
 	ti->tcpi_rcv_space = tp->rcv_wnd;
-	ti->tcpi_rcv_nxt = tp->rcv_nxt;
+	ti->tcpi_rcv_nxt = tp->rcv_nxt.raw();
 	ti->tcpi_snd_wnd = tp->snd_wnd;
 	ti->tcpi_snd_bwnd = 0;		/* Unused, kept for compat. */
-	ti->tcpi_snd_nxt = tp->snd_nxt;
+	ti->tcpi_snd_nxt = tp->snd_nxt.raw();
 	ti->tcpi_snd_mss = tp->t_maxseg;
 	ti->tcpi_rcv_mss = tp->t_maxseg;
 	if (tp->t_flags & TF_TOE)