summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-09 13:04:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commite4a8065910cd6b2e7e0448cc6431ca2906322389 (patch)
tree73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/netinet
parentUpdate to FreeBSD head 2017-08-01 (diff)
downloadrtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1. Update #3472.
Diffstat (limited to 'freebsd/sys/netinet')
-rw-r--r--freebsd/sys/netinet/if_ether.c2
-rw-r--r--freebsd/sys/netinet/in_pcb.c32
-rw-r--r--freebsd/sys/netinet/in_pcb.h1
-rw-r--r--freebsd/sys/netinet/ip_icmp.c65
-rw-r--r--freebsd/sys/netinet/sctp.h1
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c33
-rw-r--r--freebsd/sys/netinet/sctp_asconf.h3
-rw-r--r--freebsd/sys/netinet/sctp_constants.h9
-rw-r--r--freebsd/sys/netinet/sctp_indata.c26
-rw-r--r--freebsd/sys/netinet/sctp_input.c43
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h5
-rw-r--r--freebsd/sys/netinet/sctp_output.c36
-rw-r--r--freebsd/sys/netinet/sctp_output.h2
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c12
-rw-r--r--freebsd/sys/netinet/sctp_pcb.h4
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c8
-rw-r--r--freebsd/sys/netinet/sctp_uio.h4
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c21
-rw-r--r--freebsd/sys/netinet/sctputil.c94
-rw-r--r--freebsd/sys/netinet/tcp_input.c38
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c10
-rw-r--r--freebsd/sys/netinet/tcp_timer.c49
-rw-r--r--freebsd/sys/netinet/tcp_usrreq.c2
-rw-r--r--freebsd/sys/netinet/tcp_var.h7
24 files changed, 243 insertions, 264 deletions
diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index 802fedbb..bdb3b054 100644
--- a/freebsd/sys/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
@@ -1281,7 +1281,7 @@ arp_mark_lle_reachable(struct llentry *la)
}
/*
- * Add pernament link-layer record for given interface address.
+ * Add permanent link-layer record for given interface address.
*/
static __noinline void
arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst)
diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index 3d43ed92..44890e3f 100644
--- a/freebsd/sys/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
@@ -2809,6 +2809,35 @@ in_pcbquery_txrtlmt(struct inpcb *inp, uint32_t *p_max_pacing_rate)
}
/*
+ * Query existing TX queue level based on the existing
+ * "inp->inp_snd_tag", if any.
+ */
+int
+in_pcbquery_txrlevel(struct inpcb *inp, uint32_t *p_txqueue_level)
+{
+ union if_snd_tag_query_params params = { };
+ struct m_snd_tag *mst;
+ struct ifnet *ifp;
+ int error;
+
+ mst = inp->inp_snd_tag;
+ if (mst == NULL)
+ return (EINVAL);
+
+ ifp = mst->ifp;
+ if (ifp == NULL)
+ return (EINVAL);
+
+ if (ifp->if_snd_tag_query == NULL)
+ return (EOPNOTSUPP);
+
+ error = ifp->if_snd_tag_query(mst, &params);
+ if (error == 0 && p_txqueue_level != NULL)
+ *p_txqueue_level = params.rate_limit.queue_level;
+ return (error);
+}
+
+/*
* Allocate a new TX rate limit send tag from the network interface
* given by the "ifp" argument and save it in "inp->inp_snd_tag":
*/
@@ -2817,7 +2846,8 @@ in_pcbattach_txrtlmt(struct inpcb *inp, struct ifnet *ifp,
uint32_t flowtype, uint32_t flowid, uint32_t max_pacing_rate)
{
union if_snd_tag_alloc_params params = {
- .rate_limit.hdr.type = IF_SND_TAG_TYPE_RATE_LIMIT,
+ .rate_limit.hdr.type = (max_pacing_rate == -1U) ?
+ IF_SND_TAG_TYPE_UNLIMITED : IF_SND_TAG_TYPE_RATE_LIMIT,
.rate_limit.hdr.flowid = flowid,
.rate_limit.hdr.flowtype = flowtype,
.rate_limit.max_rate = max_pacing_rate,
diff --git a/freebsd/sys/netinet/in_pcb.h b/freebsd/sys/netinet/in_pcb.h
index 42fd23d0..059ea90c 100644
--- a/freebsd/sys/netinet/in_pcb.h
+++ b/freebsd/sys/netinet/in_pcb.h
@@ -761,6 +761,7 @@ int in_pcbattach_txrtlmt(struct inpcb *, struct ifnet *, uint32_t, uint32_t, uin
void in_pcbdetach_txrtlmt(struct inpcb *);
int in_pcbmodify_txrtlmt(struct inpcb *, uint32_t);
int in_pcbquery_txrtlmt(struct inpcb *, uint32_t *);
+int in_pcbquery_txrlevel(struct inpcb *, uint32_t *);
void in_pcboutput_txrtlmt(struct inpcb *, struct ifnet *, struct mbuf *);
void in_pcboutput_eagain(struct inpcb *);
#endif
diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index acc2e6b6..4843efcd 100644
--- a/freebsd/sys/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
@@ -187,17 +187,14 @@ kmod_icmpstat_inc(int statnum)
void
icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
{
- struct ip *oip = mtod(n, struct ip *), *nip;
- unsigned oiphlen = oip->ip_hl << 2;
+ struct ip *oip, *nip;
struct icmp *icp;
struct mbuf *m;
- unsigned icmplen, icmpelen, nlen;
+ unsigned icmplen, icmpelen, nlen, oiphlen;
+
+ KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type",
+ __func__));
- KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__));
-#ifdef ICMPPRINTFS
- if (icmpprintfs)
- printf("icmp_error(%p, %x, %d)\n", oip, type, code);
-#endif
if (type != ICMP_REDIRECT)
ICMPSTAT_INC(icps_error);
/*
@@ -209,19 +206,28 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
*/
if (n->m_flags & M_DECRYPTED)
goto freeit;
- if (oip->ip_off & htons(~(IP_MF|IP_DF)))
- goto freeit;
if (n->m_flags & (M_BCAST|M_MCAST))
goto freeit;
+
+ /* Drop if IP header plus 8 bytes is not contiguous in first mbuf. */
+ if (n->m_len < sizeof(struct ip) + ICMP_MINLEN)
+ goto freeit;
+ oip = mtod(n, struct ip *);
+ oiphlen = oip->ip_hl << 2;
+ if (n->m_len < oiphlen + ICMP_MINLEN)
+ goto freeit;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("icmp_error(%p, %x, %d)\n", oip, type, code);
+#endif
+ if (oip->ip_off & htons(~(IP_MF|IP_DF)))
+ goto freeit;
if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
- n->m_len >= oiphlen + ICMP_MINLEN &&
- !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) {
+ !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip +
+ oiphlen))->icmp_type)) {
ICMPSTAT_INC(icps_oldicmp);
goto freeit;
}
- /* Drop if IP header plus 8 bytes is not contignous in first mbuf. */
- if (oiphlen + 8 > n->m_len)
- goto freeit;
/*
* Calculate length to quote from original packet and
* prevent the ICMP mbuf from overflowing.
@@ -237,9 +243,10 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
n->m_next == NULL)
goto stdreply;
if (n->m_len < oiphlen + sizeof(struct tcphdr) &&
- ((n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL))
+ (n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL)
goto freeit;
- th = (struct tcphdr *)((caddr_t)oip + oiphlen);
+ oip = mtod(n, struct ip *);
+ th = mtodo(n, oiphlen);
tcphlen = th->th_off << 2;
if (tcphlen < sizeof(struct tcphdr))
goto freeit;
@@ -247,8 +254,8 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
goto freeit;
if (oiphlen + tcphlen > n->m_len && n->m_next == NULL)
goto stdreply;
- if (n->m_len < oiphlen + tcphlen &&
- ((n = m_pullup(n, oiphlen + tcphlen)) == NULL))
+ if (n->m_len < oiphlen + tcphlen &&
+ (n = m_pullup(n, oiphlen + tcphlen)) == NULL)
goto freeit;
icmpelen = max(tcphlen, min(V_icmp_quotelen,
ntohs(oip->ip_len) - oiphlen));
@@ -264,24 +271,31 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
if (n->m_len < oiphlen + sizeof(struct sctphdr) &&
(n = m_pullup(n, oiphlen + sizeof(struct sctphdr))) == NULL)
goto freeit;
+ oip = mtod(n, struct ip *);
icmpelen = max(sizeof(struct sctphdr),
min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
- sh = (struct sctphdr *)((caddr_t)oip + oiphlen);
+ sh = mtodo(n, oiphlen);
if (ntohl(sh->v_tag) == 0 &&
- ntohs(oip->ip_len) >= oiphlen + sizeof(struct sctphdr) + 8 &&
+ ntohs(oip->ip_len) >= oiphlen +
+ sizeof(struct sctphdr) + 8 &&
(n->m_len >= oiphlen + sizeof(struct sctphdr) + 8 ||
n->m_next != NULL)) {
if (n->m_len < oiphlen + sizeof(struct sctphdr) + 8 &&
- (n = m_pullup(n, oiphlen + sizeof(struct sctphdr) + 8)) == NULL)
+ (n = m_pullup(n, oiphlen +
+ sizeof(struct sctphdr) + 8)) == NULL)
goto freeit;
+ oip = mtod(n, struct ip *);
+ sh = mtodo(n, oiphlen);
ch = (struct sctp_chunkhdr *)(sh + 1);
if (ch->chunk_type == SCTP_INITIATION) {
icmpelen = max(sizeof(struct sctphdr) + 8,
- min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
+ min(V_icmp_quotelen, ntohs(oip->ip_len) -
+ oiphlen));
}
}
} else
-stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
+stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) -
+ oiphlen));
icmplen = min(oiphlen + icmpelen, nlen);
if (icmplen < sizeof(struct ip))
@@ -296,7 +310,8 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
#ifdef MAC
mac_netinet_icmp_reply(n, m);
#endif
- icmplen = min(icmplen, M_TRAILINGSPACE(m) - sizeof(struct ip) - ICMP_MINLEN);
+ icmplen = min(icmplen, M_TRAILINGSPACE(m) -
+ sizeof(struct ip) - ICMP_MINLEN);
m_align(m, ICMP_MINLEN + icmplen);
m->m_len = ICMP_MINLEN + icmplen;
diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index ec42cffa..578be4f6 100644
--- a/freebsd/sys/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
@@ -545,7 +545,6 @@ struct sctp_error_auth_invalid_hmac {
#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010
#define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020
#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040
-#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080
/* socket options */
#define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100
#define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index aa31e488..5f1c4e8f 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -2307,39 +2307,6 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
return (0);
}
-void
-sctp_set_primary_ip_address(struct sctp_ifa *ifa)
-{
- struct sctp_inpcb *inp;
-
- /* go through all our PCB's */
- LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
- struct sctp_tcb *stcb;
-
- /* process for all associations for this endpoint */
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- /* queue an ASCONF:SET_PRIM_ADDR to be sent */
- if (!sctp_asconf_queue_add(stcb, ifa,
- SCTP_SET_PRIM_ADDR)) {
- /* set primary queuing succeeded */
- SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
- (void *)stcb);
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
-#ifdef SCTP_TIMER_BASED_ASCONF
- sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
- stcb->sctp_ep, stcb,
- stcb->asoc.primary_destination);
-#else
- sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
-#endif
- }
- }
- } /* for each stcb */
- } /* for each inp */
-}
-
int
sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
{
diff --git a/freebsd/sys/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h
index c8d670e5..ed9160e1 100644
--- a/freebsd/sys/netinet/sctp_asconf.h
+++ b/freebsd/sys/netinet/sctp_asconf.h
@@ -73,9 +73,6 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *,
struct sockaddr *);
extern void
- sctp_set_primary_ip_address(struct sctp_ifa *ifa);
-
-extern void
sctp_check_address_list(struct sctp_tcb *, struct mbuf *, int, int,
struct sockaddr *, uint16_t, uint16_t, uint16_t, uint16_t);
diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index dca34cc5..56772b34 100644
--- a/freebsd/sys/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
@@ -555,11 +555,9 @@ __FBSDID("$FreeBSD$");
#define SCTP_TIMER_TYPE_INPKILL 15
#define SCTP_TIMER_TYPE_ASOCKILL 16
#define SCTP_TIMER_TYPE_ADDR_WQ 17
-#define SCTP_TIMER_TYPE_ZERO_COPY 18
-#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 19
-#define SCTP_TIMER_TYPE_PRIM_DELETED 20
+#define SCTP_TIMER_TYPE_PRIM_DELETED 18
/* add new timers here - and increment LAST */
-#define SCTP_TIMER_TYPE_LAST 21
+#define SCTP_TIMER_TYPE_LAST 19
#define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \
((t) < SCTP_TIMER_TYPE_LAST))
@@ -971,9 +969,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_SO_NOT_LOCKED 0
-#define SCTP_HOLDS_LOCK 1
-#define SCTP_NOT_LOCKED 0
-
/*-
* For address locks, do we hold the lock?
*/
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 1924aeab..c27dd485 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -1381,10 +1381,10 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
if (sctp_place_control_in_stream(strm, asoc, control)) {
/* Duplicate SSN? */
- sctp_clean_up_control(stcb, control);
sctp_abort_in_reasm(stcb, control, chk,
abort_flag,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_6);
+ sctp_clean_up_control(stcb, control);
return;
}
if ((tsn == (asoc->cumulative_tsn + 1) && (asoc->idata_supported == 0))) {
@@ -1596,9 +1596,17 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
next_fsn, control->fsn_included);
TAILQ_REMOVE(&control->reasm, at, sctp_next);
lenadded = sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD);
- asoc->size_on_all_streams += lenadded;
if (control->on_read_q) {
do_wakeup = 1;
+ } else {
+ /*
+ * We only add to the
+ * size-on-all-streams if its not on
+ * the read q. The read q flag will
+ * cause a sballoc so its accounted
+ * for there.
+ */
+ asoc->size_on_all_streams += lenadded;
}
next_fsn++;
if (control->end_added && control->pdapi_started) {
@@ -1611,7 +1619,6 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
control,
&stcb->sctp_socket->so_rcv, control->end_added,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- do_wakeup = 1;
}
break;
}
@@ -4207,8 +4214,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- int to_ticks;
-
if (win_probe_recovery && (net->window_probe)) {
win_probe_recovered = 1;
/*
@@ -4224,15 +4229,9 @@ again:
}
}
}
- if (net->RTO == 0) {
- to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
- } else {
- to_ticks = MSEC_TO_TICKS(net->RTO);
- }
if (net->flight_size) {
j++;
- (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
- sctp_timeout_handler, &net->rxt_timer);
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net);
if (net->window_probe) {
net->window_probe = 0;
}
@@ -4244,8 +4243,7 @@ again:
*/
net->window_probe = 0;
if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
- SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
- sctp_timeout_handler, &net->rxt_timer);
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net);
}
} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index 2e844fb5..0871bdb8 100644
--- a/freebsd/sys/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
@@ -199,8 +199,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset,
src, dst, sh, cp,
mflowtype, mflowid,
- vrf_id, port,
- ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
+ vrf_id, port);
}
outnow:
if (stcb == NULL) {
@@ -702,6 +701,14 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
struct sctpasochead *head;
+ if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_INFO_WLOCK();
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
/* generate a new vtag and send init */
LIST_REMOVE(stcb, sctp_asocs);
@@ -713,6 +720,7 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
+ SCTP_INP_INFO_WUNLOCK();
return (1);
}
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
@@ -734,6 +742,7 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
+ SCTP_INP_INFO_WUNLOCK();
return (1);
}
return (0);
@@ -2555,15 +2564,12 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* Expire time is in Ticks, so we convert to seconds */
time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life);
time_expires.tv_usec = cookie->time_entered.tv_usec;
- /*
- * TODO sctp_constants.h needs alternative time macros when _KERNEL
- * is undefined.
- */
if (timevalcmp(&now, &time_expires, >)) {
/* cookie is stale! */
struct mbuf *op_err;
struct sctp_error_stale_cookie *cause;
- uint32_t tim;
+ struct timeval diff;
+ uint32_t staleness;
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie),
0, M_NOWAIT, 1, MT_DATA);
@@ -2577,12 +2583,19 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE);
cause->cause.length = htons((sizeof(struct sctp_paramhdr) +
(sizeof(uint32_t))));
- /* seconds to usec */
- tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
- /* add in usec */
- if (tim == 0)
- tim = now.tv_usec - cookie->time_entered.tv_usec;
- cause->stale_time = htonl(tim);
+ diff = now;
+ timevalsub(&diff, &time_expires);
+ if (diff.tv_sec > UINT32_MAX / 1000000) {
+ staleness = UINT32_MAX;
+ } else {
+ staleness = diff.tv_sec * 1000000;
+ }
+ if (UINT32_MAX - staleness >= (uint32_t)diff.tv_usec) {
+ staleness += diff.tv_usec;
+ } else {
+ staleness = UINT32_MAX;
+ }
+ cause->stale_time = htonl(staleness);
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
mflowtype, mflowid, l_inp->fibnum,
vrf_id, port);
@@ -3135,14 +3148,14 @@ sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sct
* make sure that we have a covered ECNE in the control chunk part.
* If so remove it.
*/
- struct sctp_tmit_chunk *chk;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_ecne_chunk *ecne;
int override;
uint32_t cwr_tsn;
cwr_tsn = ntohl(cp->tsn);
override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
- TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
+ TAILQ_FOREACH_SAFE(chk, &stcb->asoc.control_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
continue;
}
diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index 194a03ed..045ccc38 100644
--- a/freebsd/sys/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
@@ -404,11 +404,6 @@ typedef struct rtentry sctp_rtentry_t;
#define SCTP_RTALLOC(ro, vrf_id, fibnum) \
rtalloc_ign_fib((struct route *)ro, 0UL, fibnum)
-/* Future zero copy wakeup/send function */
-#define SCTP_ZERO_COPY_EVENT(inp, so)
-/* This is re-pulse ourselves for sendbuf */
-#define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so)
-
/*
* SCTP protocol specific mbuf flags.
*/
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 5e2fbbc2..2540b5b9 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -4279,11 +4279,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint32_t mtu;
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (net->port) {
- mtu -= sizeof(struct udphdr);
- }
- if (mtu && (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ if (mtu > 0) {
+ if (net->port) {
+ mtu -= sizeof(struct udphdr);
+ }
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ }
net->mtu = mtu;
}
} else if (ro->ro_rt == NULL) {
@@ -4635,13 +4637,14 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint32_t mtu;
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (mtu &&
- (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
- net->mtu = mtu;
+ if (mtu > 0) {
if (net->port) {
- net->mtu -= sizeof(struct udphdr);
+ mtu -= sizeof(struct udphdr);
+ }
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
}
+ net->mtu = mtu;
}
} else if (ifp) {
if (ND_IFINFO(ifp)->linkmtu &&
@@ -5490,7 +5493,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_init_chunk *init_chk,
uint8_t mflowtype, uint32_t mflowid,
- uint32_t vrf_id, uint16_t port, int hold_inp_lock)
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_association *asoc;
struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err;
@@ -5838,10 +5841,6 @@ do_a_abort:
} else {
uint32_t vtag, itsn;
- if (hold_inp_lock) {
- SCTP_INP_INCR_REF(inp);
- SCTP_INP_RUNLOCK(inp);
- }
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -5861,12 +5860,12 @@ do_a_abort:
SCTP_TCB_LOCK(stcb);
atomic_add_int(&asoc->refcnt, -1);
} else {
+ SCTP_INP_INCR_REF(inp);
+ SCTP_INP_RUNLOCK(inp);
vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1);
initack->init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initack->init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
- }
- if (hold_inp_lock) {
SCTP_INP_RLOCK(inp);
SCTP_INP_DECR_REF(inp);
}
@@ -12423,7 +12422,6 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb);
sp->data = sp->tail_mbuf = NULL;
if (sp->length == 0) {
- *error = 0;
goto skip_copy;
}
if (srcv->sinfo_keynumber_valid) {
@@ -13156,7 +13154,7 @@ skip_preblock:
if (strm->last_msg_incomplete == 0) {
do_a_copy_in:
sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
- if ((sp == NULL) || (error)) {
+ if (error) {
goto out;
}
SCTP_TCB_SEND_LOCK(stcb);
diff --git a/freebsd/sys/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index 32f968c1..0a5cf10b 100644
--- a/freebsd/sys/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
@@ -86,7 +86,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_init_chunk *,
uint8_t, uint32_t,
- uint32_t, uint16_t, int);
+ uint32_t, uint16_t);
struct mbuf *
sctp_arethere_unrecognized_parameters(struct mbuf *, int, int *,
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index 1907991e..46a91110 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -711,12 +711,11 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
SCTP_WQ_ADDR_LOCK();
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
-
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
} else {
/* it's ready for use */
sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
@@ -823,12 +822,11 @@ out_now:
* the newest first :-0
*/
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
-
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
}
return;
}
@@ -2488,7 +2486,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
SCTP_PCB_FLAGS_UNBOUND);
/* Be sure we have blocking IO by default */
+ SOCK_LOCK(so);
SCTP_CLEAR_SO_NBIO(so);
+ SOCK_UNLOCK(so);
} else {
/*
* unsupported socket type (RAW, etc)- in case we missed it
@@ -2921,9 +2921,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
*/
/* got to be root to get at low ports */
if (ntohs(lport) < IPPORT_RESERVED) {
- if (p && (error =
+ if ((p != NULL) && ((error =
priv_check(p, PRIV_NETINET_RESERVEDPORT)
- )) {
+ ) != 0)) {
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h
index 86fae1f4..acc68311 100644
--- a/freebsd/sys/netinet/sctp_pcb.h
+++ b/freebsd/sys/netinet/sctp_pcb.h
@@ -314,10 +314,6 @@ struct sctp_pcb {
*/
struct sctp_timer signature_change;
- /* Zero copy full buffer timer */
- struct sctp_timer zero_copy_timer;
- /* Zero copy app to transport (sendq) read repulse timer */
- struct sctp_timer zero_copy_sendq_timer;
uint32_t def_cookie_life;
/* defaults to 0 */
int auto_close_time;
diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index a2364431..52361602 100644
--- a/freebsd/sys/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
@@ -508,6 +508,14 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.rtt = net->rtt / 1000;
xraddr.heartbeat_interval = net->heart_beat_delay;
xraddr.ssthresh = net->ssthresh;
+ xraddr.encaps_port = net->port;
+ if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+ xraddr.state = SCTP_UNCONFIRMED;
+ } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ xraddr.state = SCTP_ACTIVE;
+ } else {
+ xraddr.state = SCTP_INACTIVE;
+ }
xraddr.start_time.tv_sec = (uint32_t)net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t)net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h
index d6055163..daa6847d 100644
--- a/freebsd/sys/netinet/sctp_uio.h
+++ b/freebsd/sys/netinet/sctp_uio.h
@@ -1239,7 +1239,9 @@ struct xsctp_raddr {
uint32_t rtt;
uint32_t heartbeat_interval;
uint32_t ssthresh;
- uint32_t extra_padding[30]; /* future */
+ uint16_t encaps_port;
+ uint16_t state;
+ uint32_t extra_padding[29]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index fa136d4e..6ab04456 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -1961,6 +1961,7 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
} else {
id->assoc_value = stcb->asoc.vrf_id;
+ SCTP_TCB_UNLOCK(stcb);
*optsize = sizeof(struct sctp_assoc_value);
}
break;
@@ -3065,7 +3066,6 @@ flags_out:
if (event_type > 0) {
if (stcb) {
event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
- SCTP_TCB_UNLOCK(stcb);
} else {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
@@ -3079,6 +3079,9 @@ flags_out:
}
}
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
if (error == 0) {
*optsize = sizeof(struct sctp_event);
}
@@ -3649,12 +3652,16 @@ flags_out:
sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
#endif
- SCTP_TCB_UNLOCK(stcb);
- *optsize = sizeof(struct sctp_prstatus);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_prstatus);
+ }
break;
}
case SCTP_PR_ASSOC_STATUS:
@@ -3677,12 +3684,16 @@ flags_out:
sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
}
- SCTP_TCB_UNLOCK(stcb);
- *optsize = sizeof(struct sctp_prstatus);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_prstatus);
+ }
break;
}
case SCTP_MAX_CWND:
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index 75c989d3..f8fd23f1 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -1464,13 +1464,11 @@ sctp_handle_addr_wq(void)
LIST_INIT(&asc->list_of_work);
asc->cnt = 0;
- SCTP_WQ_ADDR_LOCK();
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
asc->cnt++;
}
- SCTP_WQ_ADDR_UNLOCK();
if (asc->cnt == 0) {
SCTP_FREE(asc, SCTP_M_ASC_IT);
@@ -1494,11 +1492,9 @@ sctp_handle_addr_wq(void)
if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) {
sctp_asconf_iterator_end(asc, 0);
} else {
- SCTP_WQ_ADDR_LOCK();
LIST_FOREACH(wi, &asc->list_of_work, sctp_nxt_addr) {
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
}
- SCTP_WQ_ADDR_UNLOCK();
SCTP_FREE(asc, SCTP_M_ASC_IT);
}
}
@@ -1567,8 +1563,7 @@ sctp_timeout_handler(void *t)
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
- (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
- ) {
+ (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))) {
SCTP_INP_DECR_REF(inp);
CURVNET_RESTORE();
return;
@@ -1614,6 +1609,12 @@ sctp_timeout_handler(void *t)
CURVNET_RESTORE();
return;
}
+ } else if (inp != NULL) {
+ if (type != SCTP_TIMER_TYPE_INPKILL) {
+ SCTP_INP_WLOCK(inp);
+ }
+ } else {
+ SCTP_WQ_ADDR_LOCK();
}
/* record in stopped what t-o occurred */
tmr->stopped_from = type;
@@ -1635,22 +1636,6 @@ sctp_timeout_handler(void *t)
/* call the handler for the appropriate timer type */
switch (type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- }
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
- }
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
sctp_handle_addr_wq();
break;
@@ -1777,7 +1762,6 @@ sctp_timeout_handler(void *t)
}
SCTP_STAT_INCR(sctps_timosecret);
(void)SCTP_GETTIME_TIMEVAL(&tv);
- SCTP_INP_WLOCK(inp);
inp->sctp_ep.time_of_secret_change = tv.tv_sec;
inp->sctp_ep.last_secret_number =
inp->sctp_ep.current_secret_number;
@@ -1791,7 +1775,6 @@ sctp_timeout_handler(void *t)
inp->sctp_ep.secret_key[secret][i] =
sctp_select_initial_TSN(&inp->sctp_ep);
}
- SCTP_INP_WUNLOCK(inp);
sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
}
did_output = 0;
@@ -1939,7 +1922,12 @@ sctp_timeout_handler(void *t)
get_out:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
+ } else if (inp != NULL) {
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_WQ_ADDR_UNLOCK();
}
+
out_decr:
if (inp) {
SCTP_INP_DECR_REF(inp);
@@ -1964,14 +1952,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
}
switch (t_type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- tmr = &inp->sctp_ep.zero_copy_timer;
- to_ticks = SCTP_ZERO_COPY_TICK_DELAY;
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- tmr = &inp->sctp_ep.zero_copy_sendq_timer;
- to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY;
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
/* Only 1 tick away :-) */
tmr = &SCTP_BASE_INFO(addr_wq_timer);
@@ -2253,12 +2233,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
}
switch (t_type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- tmr = &inp->sctp_ep.zero_copy_timer;
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- tmr = &inp->sctp_ep.zero_copy_sendq_timer;
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
tmr = &SCTP_BASE_INFO(addr_wq_timer);
break;
@@ -4472,36 +4446,32 @@ sctp_wakeup_the_read_socket(struct sctp_inpcb *inp,
)
{
if ((inp != NULL) && (inp->sctp_socket != NULL)) {
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- } else {
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
+ struct socket *so;
- so = SCTP_INP_SO(inp);
- if (!so_locked) {
- if (stcb) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_SOCKET_LOCK(so, 1);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- }
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
- }
+ so = SCTP_INP_SO(inp);
+ if (!so_locked) {
+ if (stcb) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
}
-#endif
- sctp_sorwakeup(inp, inp->sctp_socket);
-#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
+ SCTP_SOCKET_LOCK(so, 1);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
+ return;
}
+ }
#endif
+ sctp_sorwakeup(inp, inp->sctp_socket);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if (!so_locked) {
+ SCTP_SOCKET_UNLOCK(so, 1);
}
+#endif
}
}
@@ -6182,11 +6152,11 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
* newest first :-0
*/
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
return (0);
}
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index 2195a778..663b8bc2 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -1696,25 +1696,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
to.to_tsecr = 0;
}
/*
- * If timestamps were negotiated during SYN/ACK they should
- * appear on every segment during this session and vice versa.
- */
- if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
- log(LOG_DEBUG, "%s; %s: Timestamp missing, "
- "no action\n", s, __func__);
- free(s, M_TCPLOG);
- }
- }
- if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
- log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
- "no action\n", s, __func__);
- free(s, M_TCPLOG);
- }
- }
-
- /*
* Process options only when we get SYN/ACK back. The SYN case
* for incoming connections is handled in tcp_syncache.
* According to RFC1323 the window field in a SYN (i.e., a <SYN>
@@ -1745,6 +1726,25 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
/*
+ * If timestamps were negotiated during SYN/ACK they should
+ * appear on every segment during this session and vice versa.
+ */
+ if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp missing, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+ if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+
+ /*
* Header prediction: check for the two common cases
* of a uni-directional data xfer. If the packet has
* no control flags, is in-sequence, the window didn't
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index cf1f0ad1..a30def41 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -1644,9 +1644,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
tlen = hlen + sizeof(struct tcphdr);
/* Determine MSS we advertize to other end of connection. */
- mssopt = tcp_mssopt(&sc->sc_inc);
- if (sc->sc_peer_mss)
- mssopt = max( min(sc->sc_peer_mss, mssopt), V_tcp_minmss);
+ mssopt = max(tcp_mssopt(&sc->sc_inc), V_tcp_minmss);
/* XXX: Assume that the entire packet will fit in a header mbuf. */
KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN,
@@ -1995,7 +1993,7 @@ syncookie_mac(struct in_conninfo *inc, tcp_seq irs, uint8_t flags,
static tcp_seq
syncookie_generate(struct syncache_head *sch, struct syncache *sc)
{
- u_int i, mss, secbit, wscale;
+ u_int i, secbit, wscale;
uint32_t iss, hash;
uint8_t *secbits;
union syncookie cookie;
@@ -2005,8 +2003,8 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc)
cookie.cookie = 0;
/* Map our computed MSS into the 3-bit index. */
- mss = min(tcp_mssopt(&sc->sc_inc), max(sc->sc_peer_mss, V_tcp_minmss));
- for (i = nitems(tcp_sc_msstab) - 1; tcp_sc_msstab[i] > mss && i > 0;
+ for (i = nitems(tcp_sc_msstab) - 1;
+ tcp_sc_msstab[i] > sc->sc_peer_mss && i > 0;
i--)
;
cookie.flags.mss_idx = i;
diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index ebd9e852..b4528801 100644
--- a/freebsd/sys/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
@@ -150,29 +150,6 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
&VNET_NAME(tcp_pmtud_blackhole_detect), 0,
"Path MTU Discovery Black Hole Detection Enabled");
-static VNET_DEFINE(int, tcp_pmtud_blackhole_activated);
-#define V_tcp_pmtud_blackhole_activated \
- VNET(tcp_pmtud_blackhole_activated)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_activated), 0,
- "Path MTU Discovery Black Hole Detection, Activation Count");
-
-static VNET_DEFINE(int, tcp_pmtud_blackhole_activated_min_mss);
-#define V_tcp_pmtud_blackhole_activated_min_mss \
- VNET(tcp_pmtud_blackhole_activated_min_mss)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated_min_mss,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_activated_min_mss), 0,
- "Path MTU Discovery Black Hole Detection, Activation Count at min MSS");
-
-static VNET_DEFINE(int, tcp_pmtud_blackhole_failed);
-#define V_tcp_pmtud_blackhole_failed VNET(tcp_pmtud_blackhole_failed)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_failed,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_failed), 0,
- "Path MTU Discovery Black Hole Detection, Failure Count");
-
#ifdef INET
static VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200;
#define V_tcp_pmtud_blackhole_mss VNET(tcp_pmtud_blackhole_mss)
@@ -751,18 +728,20 @@ tcp_timer_rexmt(void * xtp)
*/
if (((tp->t_flags2 & (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) ==
(TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) &&
- (tp->t_rxtshift >= 2 && tp->t_rxtshift % 2 == 0)) {
+ (tp->t_rxtshift >= 2 && tp->t_rxtshift < 6 &&
+ tp->t_rxtshift % 2 == 0)) {
/*
* Enter Path MTU Black-hole Detection mechanism:
* - Disable Path MTU Discovery (IP "DF" bit).
* - Reduce MTU to lower value than what we
* negotiated with peer.
*/
- /* Record that we may have found a black hole. */
- tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
-
- /* Keep track of previous MSS. */
- tp->t_pmtud_saved_maxseg = tp->t_maxseg;
+ if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) == 0) {
+ /* Record that we may have found a black hole. */
+ tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
+ /* Keep track of previous MSS. */
+ tp->t_pmtud_saved_maxseg = tp->t_maxseg;
+ }
/*
* Reduce the MSS to blackhole value or to the default
@@ -774,7 +753,7 @@ tcp_timer_rexmt(void * xtp)
tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss) {
/* Use the sysctl tuneable blackhole MSS. */
tp->t_maxseg = V_tcp_v6pmtud_blackhole_mss;
- V_tcp_pmtud_blackhole_activated++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated);
} else if (isipv6) {
/* Use the default MSS. */
tp->t_maxseg = V_tcp_v6mssdflt;
@@ -783,7 +762,7 @@ tcp_timer_rexmt(void * xtp)
* minmss.
*/
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
- V_tcp_pmtud_blackhole_activated_min_mss++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
}
#endif
#if defined(INET6) && defined(INET)
@@ -793,7 +772,7 @@ tcp_timer_rexmt(void * xtp)
if (tp->t_maxseg > V_tcp_pmtud_blackhole_mss) {
/* Use the sysctl tuneable blackhole MSS. */
tp->t_maxseg = V_tcp_pmtud_blackhole_mss;
- V_tcp_pmtud_blackhole_activated++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated);
} else {
/* Use the default MSS. */
tp->t_maxseg = V_tcp_mssdflt;
@@ -802,7 +781,7 @@ tcp_timer_rexmt(void * xtp)
* minmss.
*/
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
- V_tcp_pmtud_blackhole_activated_min_mss++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
}
#endif
/*
@@ -821,11 +800,11 @@ tcp_timer_rexmt(void * xtp)
* stage (1448, 1188, 524) 2 chances to recover.
*/
if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) &&
- (tp->t_rxtshift > 6)) {
+ (tp->t_rxtshift >= 6)) {
tp->t_flags2 |= TF2_PLPMTU_PMTUD;
tp->t_flags2 &= ~TF2_PLPMTU_BLACKHOLE;
tp->t_maxseg = tp->t_pmtud_saved_maxseg;
- V_tcp_pmtud_blackhole_failed++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_failed);
/*
* Reset the slow-start flight size as it
* may depend on the new MSS.
diff --git a/freebsd/sys/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c
index 198291f2..88cc3501 100644
--- a/freebsd/sys/netinet/tcp_usrreq.c
+++ b/freebsd/sys/netinet/tcp_usrreq.c
@@ -1920,6 +1920,8 @@ tcp_attach(struct socket *so)
#ifdef INET6
if (inp->inp_vflag & INP_IPV6PROTO) {
inp->inp_vflag |= INP_IPV6;
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
+ inp->inp_vflag |= INP_IPV4;
inp->in6p_hops = -1; /* use kernel default */
}
else
diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index 2e2f88ac..967a5139 100644
--- a/freebsd/sys/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
@@ -580,6 +580,11 @@ struct tcpstat {
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
+ /* Path MTU Discovery Black Hole Detection related stats */
+ uint64_t tcps_pmtud_blackhole_activated; /* Black Hole Count */
+ uint64_t tcps_pmtud_blackhole_activated_min_mss; /* BH at min MSS Count */
+ uint64_t tcps_pmtud_blackhole_failed; /* Black Hole Failure Count */
+
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
};
@@ -650,7 +655,7 @@ struct tcp_hhook_data {
struct xtcpcb {
size_t xt_len; /* length of this structure */
struct xinpcb xt_inp;
- char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (n) */
+ char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (s) */
int64_t spare64[8];
int32_t t_state; /* (s,p) */
uint32_t t_flags; /* (s,p) */