Mercurial > illumos > illumos-gate
changeset 4311:27c974ce5d7f
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
author | vi117747 |
---|---|
date | Thu, 24 May 2007 12:17:11 -0700 |
parents | 127d7ee782ad |
children | 4fef416ca8cb |
files | usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip_if.c usr/src/uts/common/inet/sctp/sctp_addr.c usr/src/uts/common/inet/sctp/sctp_addr.h usr/src/uts/common/inet/sctp/sctp_input.c usr/src/uts/common/inet/sctp_ip.h usr/src/uts/common/inet/tcp/tcp.c usr/src/uts/common/inet/tcp_impl.h usr/src/uts/common/net/if.h |
diffstat | 9 files changed, 131 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip.c Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/ip/ip.c Thu May 24 12:17:11 2007 -0700 @@ -20658,6 +20658,8 @@ 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; }
--- a/usr/src/uts/common/inet/ip/ip_if.c Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/ip/ip_if.c Thu May 24 12:17:11 2007 -0700 @@ -22278,6 +22278,9 @@ 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);
--- a/usr/src/uts/common/inet/sctp/sctp_addr.c Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/sctp/sctp_addr.c Thu May 24 12:17:11 2007 -0700 @@ -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 @@ 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 @@ 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_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_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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ 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); }
--- a/usr/src/uts/common/inet/sctp/sctp_addr.h Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/sctp/sctp_addr.h Thu May 24 12:17:11 2007 -0700 @@ -116,6 +116,7 @@ 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 @@ #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);
--- a/usr/src/uts/common/inet/sctp/sctp_input.c Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/sctp/sctp_input.c Thu May 24 12:17:11 2007 -0700 @@ -2866,6 +2866,7 @@ } fp->acked = 0; } + fp = sctp->sctp_current; check_ss_rxmit: /* * If this is a SACK following a timeout, check if there are
--- a/usr/src/uts/common/inet/sctp_ip.h Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/sctp_ip.h Thu May 24 12:17:11 2007 -0700 @@ -79,14 +79,14 @@ 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,
--- a/usr/src/uts/common/inet/tcp/tcp.c Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/tcp/tcp.c Thu May 24 12:17:11 2007 -0700 @@ -12914,6 +12914,12 @@ * 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 @@ * 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 @@ 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; }
--- a/usr/src/uts/common/inet/tcp_impl.h Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/inet/tcp_impl.h Thu May 24 12:17:11 2007 -0700 @@ -109,6 +109,41 @@ } /* + * 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
--- a/usr/src/uts/common/net/if.h Thu May 24 12:06:56 2007 -0700 +++ b/usr/src/uts/common/net/if.h Thu May 24 12:17:11 2007 -0700 @@ -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 @@ (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)