summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorvi117747 <none@none>2007-05-24 12:17:11 -0700
committervi117747 <none@none>2007-05-24 12:17:11 -0700
commit1d19ca101f1c458100349d59ba2d115d8e2c6f9d (patch)
tree2ed84c4bcd25a695a624f77a879e9adfa1433502 /usr/src/uts/common
parent9c7f0c7949f4f8c13342ed0167ea42f8d77b5f21 (diff)
downloadillumos-joyent-1d19ca101f1c458100349d59ba2d115d8e2c6f9d.tar.gz
6349696 PANIC: assertion failed: peer_tcp->tcp_loopback && peer_tcp->tcp_loopback_peer == NULL
6350527 assertion failed: !(flags & > >>TH_MARKNEXT_NEEDED), file: ../../common/inet/tcp/tcp.c 6531423 SCTP_IPIF_INSERT is adrift 6539189 IFF_COS_ENABLED can be changed by SIOCS[L]IFFLAGS 6546661 sctp_update_ipif_addr() panics if passed an ipif tied to an unknown ill 6546662 sctp's ill caching cannot handle interface index changes 6553898 Page fault during multithreaded SCTP stress test
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/inet/ip/ip.c2
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c3
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_addr.c99
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_addr.h4
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_input.c1
-rw-r--r--usr/src/uts/common/inet/sctp_ip.h10
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c9
-rw-r--r--usr/src/uts/common/inet/tcp_impl.h35
-rw-r--r--usr/src/uts/common/net/if.h4
9 files changed, 131 insertions, 36 deletions
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 60dedabb18..aa2b0e3dc7 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -20658,6 +20658,8 @@ standard_path:
if (CONN_CACHE_IRE(connp) && connp->conn_ire_cache == NULL) {
rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
+ if (connp->conn_ulp == IPPROTO_TCP)
+ TCP_CHECK_IREINFO(connp->conn_tcp, ire);
connp->conn_ire_cache = ire;
cached = B_TRUE;
}
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 16595a3c4d..87b826f40f 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -22278,6 +22278,9 @@ ip_sioctl_slifindex(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp,
phyi->phyint_ifindex = index;
+ /* Update SCTP's ILL list */
+ sctp_ill_reindex(ill, old_index);
+
connc.cc_old_ifindex = old_index;
connc.cc_new_ifindex = index;
ip_change_ifindex(ill, &connc);
diff --git a/usr/src/uts/common/inet/sctp/sctp_addr.c b/usr/src/uts/common/inet/sctp/sctp_addr.c
index d181162fd3..80b100eaf1 100644
--- a/usr/src/uts/common/inet/sctp/sctp_addr.c
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/stream.h>
+#include <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/kmem.h>
@@ -53,28 +54,12 @@ static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t,
zoneid_t, boolean_t, uint_t, uint_t, boolean_t,
sctp_stack_t *);
static int sctp_get_all_ipifs(sctp_t *, int);
-int sctp_valid_addr_list(sctp_t *, const void *, uint32_t,
- uchar_t *, size_t);
static int sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int,
boolean_t, boolean_t);
static void sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *);
static int sctp_compare_ipif_list(sctp_ipif_hash_t *,
sctp_ipif_hash_t *);
-int sctp_compare_saddrs(sctp_t *, sctp_t *);
static int sctp_copy_ipifs(sctp_ipif_hash_t *, sctp_t *, int);
-int sctp_dup_saddrs(sctp_t *, sctp_t *, int);
-void sctp_free_saddrs(sctp_t *);
-void sctp_update_ill(ill_t *, int);
-void sctp_update_ipif(ipif_t *, int);
-void sctp_move_ipif(ipif_t *, ill_t *, ill_t *);
-void sctp_del_saddr(sctp_t *, sctp_saddr_ipif_t *);
-void sctp_del_saddr_list(sctp_t *, const void *, int,
- boolean_t);
-sctp_saddr_ipif_t *sctp_saddr_lookup(sctp_t *, in6_addr_t *, uint_t);
-in6_addr_t sctp_get_valid_addr(sctp_t *, boolean_t);
-int sctp_getmyaddrs(void *, void *, int *);
-void sctp_saddr_init(sctp_stack_t *);
-void sctp_saddr_fini(sctp_stack_t *);
#define SCTP_ADDR4_HASH(addr) \
(((addr) ^ ((addr) >> 8) ^ ((addr) >> 16) ^ ((addr) >> 24)) & \
@@ -670,8 +655,10 @@ sctp_update_ill(ill_t *ill, int op)
index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
sctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
- if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
+ if ((sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill)) &&
+ (sctp_ill->sctp_ill_isv6 == ill->ill_isv6)) {
break;
+ }
sctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
sctp_ill);
}
@@ -688,14 +675,16 @@ sctp_update_ill(ill_t *ill, int op)
sctp_ill = kmem_zalloc(sizeof (sctp_ill_t), KM_NOSLEEP);
/* Need to re-try? */
if (sctp_ill == NULL) {
- ip1dbg(("sctp_ill_insert: mem error..\n"));
+ cmn_err(CE_WARN, "sctp_update_ill: error adding "
+ "ILL %p to SCTP's ILL list", (void *)ill);
rw_exit(&sctps->sctps_g_ills_lock);
return;
}
sctp_ill->sctp_ill_name = kmem_zalloc(ill->ill_name_length,
KM_NOSLEEP);
if (sctp_ill->sctp_ill_name == NULL) {
- ip1dbg(("sctp_ill_insert: mem error..\n"));
+ cmn_err(CE_WARN, "sctp_update_ill: error adding "
+ "ILL %p to SCTP's ILL list", (void *)ill);
kmem_free(sctp_ill, sizeof (sctp_ill_t));
rw_exit(&sctps->sctps_g_ills_lock);
return;
@@ -706,6 +695,7 @@ sctp_update_ill(ill_t *ill, int op)
sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill);
sctp_ill->sctp_ill_flags = ill->ill_phyint->phyint_flags;
sctp_ill->sctp_ill_netstack = ns; /* No netstack_hold */
+ sctp_ill->sctp_ill_isv6 = ill->ill_isv6;
list_insert_tail(&sctps->sctps_g_ills[index].sctp_ill_list,
(void *)sctp_ill);
sctps->sctps_g_ills[index].ill_count++;
@@ -736,6 +726,55 @@ sctp_update_ill(ill_t *ill, int op)
rw_exit(&sctps->sctps_g_ills_lock);
}
+/*
+ * The ILL's index is being changed, just remove it from the old list,
+ * change the SCTP ILL's index and re-insert using the new index.
+ */
+void
+sctp_ill_reindex(ill_t *ill, uint_t orig_ill_index)
+{
+ sctp_ill_t *sctp_ill = NULL;
+ sctp_ill_t *nxt_sill;
+ uint_t indx;
+ uint_t nindx;
+ boolean_t once = B_FALSE;
+ netstack_t *ns = ill->ill_ipst->ips_netstack;
+ sctp_stack_t *sctps = ns->netstack_sctp;
+
+ rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER);
+
+ indx = SCTP_ILL_HASH_FN(orig_ill_index);
+ nindx = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
+ sctp_ill = list_head(&sctps->sctps_g_ills[indx].sctp_ill_list);
+ while (sctp_ill != NULL) {
+ nxt_sill = list_next(&sctps->sctps_g_ills[indx].sctp_ill_list,
+ sctp_ill);
+ if (sctp_ill->sctp_ill_index == orig_ill_index) {
+ sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill);
+ /*
+ * if the new index hashes to the same value, all's
+ * done.
+ */
+ if (nindx != indx) {
+ list_remove(
+ &sctps->sctps_g_ills[indx].sctp_ill_list,
+ (void *)sctp_ill);
+ sctps->sctps_g_ills[indx].ill_count--;
+ list_insert_tail(
+ &sctps->sctps_g_ills[nindx].sctp_ill_list,
+ (void *)sctp_ill);
+ sctps->sctps_g_ills[nindx].ill_count++;
+ }
+ if (once)
+ break;
+ /* We might have one for v4 and for v6 */
+ once = B_TRUE;
+ }
+ sctp_ill = nxt_sill;
+ }
+ rw_exit(&sctps->sctps_g_ills_lock);
+}
+
/* move ipif from f_ill to t_ill */
void
sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
@@ -754,8 +793,10 @@ sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill));
fsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
- if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill))
+ if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill) &&
+ fsctp_ill->sctp_ill_isv6 == f_ill->ill_isv6) {
break;
+ }
fsctp_ill = list_next(
&sctps->sctps_g_ills[hindex].sctp_ill_list, fsctp_ill);
}
@@ -763,8 +804,10 @@ sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill));
tsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
- if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill))
+ if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill) &&
+ tsctp_ill->sctp_ill_isv6 == t_ill->ill_isv6) {
break;
+ }
tsctp_ill = list_next(
&sctps->sctps_g_ills[hindex].sctp_ill_list, tsctp_ill);
}
@@ -937,16 +980,19 @@ sctp_update_ipif_addr(ipif_t *ipif, in6_addr_t v6addr)
ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
- if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
+ if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) &&
+ sctp_ill->sctp_ill_isv6 == ill->ill_isv6) {
break;
+ }
sctp_ill = list_next(
&sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
}
if (sctp_ill == NULL) {
- ip1dbg(("sctp_ipif_insert: ill not found ..\n"));
+ ip1dbg(("sctp_update_ipif_addr: ill not found ..\n"));
rw_exit(&sctps->sctps_g_ipifs_lock);
rw_exit(&sctps->sctps_g_ills_lock);
+ return;
}
if (osctp_ipif != NULL) {
@@ -1005,7 +1051,8 @@ sctp_update_ipif_addr(ipif_t *ipif, in6_addr_t v6addr)
sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
/* Try again? */
if (sctp_ipif == NULL) {
- ip1dbg(("sctp_ipif_insert: mem failure..\n"));
+ cmn_err(CE_WARN, "sctp_update_ipif_addr: error adding "
+ "IPIF %p to SCTP's IPIF list", (void *)ipif);
rw_exit(&sctps->sctps_g_ipifs_lock);
rw_exit(&sctps->sctps_g_ills_lock);
return;
@@ -1057,8 +1104,10 @@ sctp_update_ipif(ipif_t *ipif, int op)
ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
- if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
+ if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) &&
+ sctp_ill->sctp_ill_isv6 == ill->ill_isv6) {
break;
+ }
sctp_ill = list_next(
&sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
}
diff --git a/usr/src/uts/common/inet/sctp/sctp_addr.h b/usr/src/uts/common/inet/sctp/sctp_addr.h
index 2625b2e06a..9159aac29d 100644
--- a/usr/src/uts/common/inet/sctp/sctp_addr.h
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.h
@@ -116,6 +116,7 @@ typedef struct sctp_ill_s {
uint32_t sctp_ill_ipifcnt;
uint_t sctp_ill_index;
uint64_t sctp_ill_flags;
+ boolean_t sctp_ill_isv6;
netstack_t *sctp_ill_netstack; /* Does not have a netstack_hold */
} sctp_ill_t;
@@ -152,9 +153,6 @@ typedef struct sctp_ill_hash_s {
#define SCTP_ADDR_OVERLAP 3
#define SCTP_ADDR_DISJOINT 4
-extern void sctp_update_ill(ill_t *, int);
-extern void sctp_update_ipif(ipif_t *, int);
-
extern int sctp_valid_addr_list(sctp_t *, const void *, uint32_t,
uchar_t *, size_t);
extern int sctp_dup_saddrs(sctp_t *, sctp_t *, int);
diff --git a/usr/src/uts/common/inet/sctp/sctp_input.c b/usr/src/uts/common/inet/sctp/sctp_input.c
index 6a5f1ef965..80e28152e0 100644
--- a/usr/src/uts/common/inet/sctp/sctp_input.c
+++ b/usr/src/uts/common/inet/sctp/sctp_input.c
@@ -2866,6 +2866,7 @@ ret:
}
fp->acked = 0;
}
+ fp = sctp->sctp_current;
check_ss_rxmit:
/*
* If this is a SACK following a timeout, check if there are
diff --git a/usr/src/uts/common/inet/sctp_ip.h b/usr/src/uts/common/inet/sctp_ip.h
index 567a600671..16ab99abab 100644
--- a/usr/src/uts/common/inet/sctp_ip.h
+++ b/usr/src/uts/common/inet/sctp_ip.h
@@ -79,14 +79,14 @@ extern void sctp_update_ill(ill_t *, int);
extern void sctp_update_ipif(ipif_t *, int);
extern void sctp_move_ipif(ipif_t *, ill_t *, ill_t *);
extern void sctp_update_ipif_addr(ipif_t *, in6_addr_t);
+extern void sctp_ill_reindex(ill_t *, uint_t);
#define SCTP_ILL_INSERT 1
#define SCTP_ILL_REMOVE 2
-#define SCTP_IPIF_INSERT 3
-#define SCTP_IPIF_REMOVE 4
-#define SCTP_IPIF_UP 5
-#define SCTP_IPIF_DOWN 6
-#define SCTP_IPIF_UPDATE 7
+#define SCTP_IPIF_REMOVE 3
+#define SCTP_IPIF_UP 4
+#define SCTP_IPIF_DOWN 5
+#define SCTP_IPIF_UPDATE 6
/* IP routines for SCTP to call. */
extern void ip_fanout_sctp_raw(mblk_t *, ill_t *, ipha_t *, boolean_t,
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 356cbd279c..23eaaf43cf 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -12914,6 +12914,12 @@ tcp_rput_data(void *arg, mblk_t *mp, void *arg2)
* the connection has been accept()ed since it can't
* buffer OOB data. Discard segment if this happens.
*
+ * We can't just rely on a non-null tcp_listener to indicate
+ * that the accept() has completed since unlinking of the
+ * eager and completion of the accept are not atomic.
+ * tcp_detached, when it is not set (B_FALSE) indicates
+ * that the accept() has completed.
+ *
* Nor can it reassemble urgent pointers, so discard
* if it's not the next segment expected.
*
@@ -12922,7 +12928,7 @@ tcp_rput_data(void *arg, mblk_t *mp, void *arg2)
* data, and new data all are in the same mblk.
*/
ASSERT(mp != NULL);
- if (tcp->tcp_listener || !pullupmsg(mp, -1)) {
+ if (tcp->tcp_detached || !pullupmsg(mp, -1)) {
freemsg(mp);
return;
}
@@ -18769,6 +18775,7 @@ tcp_send_find_ire(tcp_t *tcp, ipaddr_t *dst, ire_t **irep)
if (CONN_CACHE_IRE(connp)) {
rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
+ TCP_CHECK_IREINFO(tcp, ire);
connp->conn_ire_cache = ire;
cached = B_TRUE;
}
diff --git a/usr/src/uts/common/inet/tcp_impl.h b/usr/src/uts/common/inet/tcp_impl.h
index 2f31dc531a..cfbbe84e3a 100644
--- a/usr/src/uts/common/inet/tcp_impl.h
+++ b/usr/src/uts/common/inet/tcp_impl.h
@@ -109,6 +109,41 @@ extern "C" {
}
/*
+ * Before caching the conn IRE, we need to make sure certain TCP
+ * states are in sync with the ire. The mismatch could occur if the
+ * TCP state has been set in tcp_adapt_ire() using a different IRE,
+ * e.g if an address was not present during an initial connect(),
+ * tcp_adapt_ire() will set the state using the interface route.
+ * Subsequently, if the address is added to the local machine, the
+ * retransmitted SYN will get the correct (loopback) IRE, but the TCP
+ * state (tcp_loopback and tcp_localnet) will remain out of sync.
+ * This is especially an issue with TCP fusion which relies on the
+ * TCP state to be accurate.
+ *
+ * This check/change should be made only if the TCP is not yet in
+ * the established state, else it would lead to inconsistencies.
+ */
+#define TCP_CHECK_IREINFO(tcp, ire) { \
+ if ((tcp)->tcp_state < TCPS_ESTABLISHED) { \
+ if (((ire)->ire_type & (IRE_LOOPBACK | \
+ IRE_LOCAL)) && !(tcp)->tcp_loopback) { \
+ (tcp)->tcp_loopback = B_TRUE; \
+ } else if ((tcp)->tcp_loopback && \
+ !((ire)->ire_type & (IRE_LOOPBACK | IRE_LOCAL))) { \
+ (tcp)->tcp_loopback = B_FALSE; \
+ } \
+ if ((tcp)->tcp_ipversion == IPV4_VERSION) { \
+ (tcp)->tcp_localnet = \
+ ((ire)->ire_gateway_addr == 0); \
+ } else { \
+ (tcp)->tcp_localnet = \
+ IN6_IS_ADDR_UNSPECIFIED( \
+ &(ire)->ire_gateway_addr_v6); \
+ } \
+ } \
+}
+
+/*
* Write-side flow-control is implemented via the per instance STREAMS
* write-side Q by explicitly setting QFULL to stop the flow of mblk_t(s)
* and clearing QFULL and calling qbackenable() to restart the flow based
diff --git a/usr/src/uts/common/net/if.h b/usr/src/uts/common/net/if.h
index b4454bb645..2d4b5845b7 100644
--- a/usr/src/uts/common/net/if.h
+++ b/usr/src/uts/common/net/if.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -178,7 +178,7 @@ struct ifnet {
(IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING | IFF_PROMISC | \
IFF_MULTICAST | IFF_MULTI_BCAST | IFF_UNNUMBERED | IFF_IPV4 | \
IFF_IPV6 | IFF_INACTIVE | IFF_FIXEDMTU | IFF_VIRTUAL | \
- IFF_LOOPBACK | IFF_ALLMULTI | IFF_DUPLICATE)
+ IFF_LOOPBACK | IFF_ALLMULTI | IFF_DUPLICATE | IFF_COS_ENABLED)
/*
* Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)