fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * RDC interface health monitoring code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * define enum_t here as it is all we need from rpc/types.h
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * anyway and make it look like we included it. Yuck.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* _SunOS_2_6 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Forward declarations.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Global data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * These structures are added when a new host name is introduced to the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * kernel. They never disappear (but that won't waste much space at all).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char host[MAX_RDC_HOST_SIZE]; /* The host name of this link */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int waiting; /* A user is waiting to be woken up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int link_down; /* The current state of the link */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IPv6 addresses are represented as 16bit hexadecimal integers
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * separated by colons. Contiguous runs of zeros can be abbreviated by
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * double colons:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FF02:0:0:0:0:1:200E:8C6C
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FF02::1:200E:8C6C
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const int end = 8; /* 8 shorts, 128 bits in an IPv6 address */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < end; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* first, last, or non-zero value */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* single zero */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* skip contiguous zeros */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strcmp("inet6", ip->srv->ri_knconf->knc_protofmly) == 0) {
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana cmn_err(CE_NOTE, "!SNDR: Interface %s <==> %s : %s",
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana "!SNDR: Interface %d.%d.%d.%d <==> %d.%d.%d.%d : %s",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (int)this[4], (int)this[5], (int)this[6], (int)this[7],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (int)other[4], (int)other[5], (int)other[6], (int)other[7],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Health monitor for a single interface.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The secondary sends ping RPCs to the primary.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The primary just stores the results and updates its structures.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ip->r_ifaddr.buf, r_ifaddr, ip->r_ifaddr.len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((ip->exiting != 1) && (net_exit != ATM_EXIT)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup RPC timeout */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* primary ifaddr */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* secondary ifaddr */
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana (char *)&ping6, xdr_int, (char *)&ret, &t);
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana RDCPROC_PING4, xdr_rdc_ping, (char *)&ping,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* RPC failed - link is down */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * don't print messages if also
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a primary - the primary will
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * take care of it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Start back at the max possible version
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * since the remote server could come back
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on a different protocol version.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * was failed, but now ok
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * don't print messages if also
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a primary - the primary will
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * take care of it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* signal that this thread is done */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forterdc_isactive_if(struct netbuf *addr, struct netbuf *r_addr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* search for existing interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((bcmp(ip->ifaddr.buf, addr->buf, addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (bcmp(ip->r_ifaddr.buf, r_addr->buf, r_addr->len) == 0)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((bcmp(ip->r_ifaddr.buf, addr->buf, addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (bcmp(ip->ifaddr.buf, r_addr->buf, r_addr->len) == 0))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* found matching interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Set the rdc rpc version of the rdc_if_t.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Called from incoming rpc calls which start before
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the health service becomes established.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forterdc_set_if_vers(rdc_u_info_t *urdc, rpcvers_t vers)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* search for existing interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((bcmp(ip->ifaddr.buf, addr->buf, addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (bcmp(ip->r_ifaddr.buf, r_addr->buf, r_addr->len) == 0)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((bcmp(ip->r_ifaddr.buf, addr->buf, addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (bcmp(ip->ifaddr.buf, r_addr->buf, r_addr->len) == 0))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* found matching interface structure */
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana cmn_err(CE_NOTE, "!rdc intf %p rpc version set to %u",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Free all the rdc_link_down structures (only at module unload time)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (p = rdc_link_down->next; p != rdc_link_down; ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(q, sizeof (*q));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Look up the supplied hostname in the rdc_link_down chain. Add a new
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * entry if it isn't found. Return a pointer to the new or found entry.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rdc_link_down = kmem_zalloc(sizeof (*rdc_link_down), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (p = rdc_link_down->next; p != rdc_link_down; p = p->next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* No match, must create a new entry */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) strncpy(p->host, host, MAX_RDC_HOST_SIZE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&p->syncd_mutex, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Handle the RDC_LINK_DOWN ioctl.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The user specifies which host he is interested in.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This function is woken up when the link to that host goes down.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte_rdc_link_down(void *arg, int mode, spcs_s_info_t kstatus, int *rvp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte clock_t timeout = RDC_SYNC_EVENT_TIMEOUT * 2; /* 2 min */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ddi_copyin(arg, host, MAX_RDC_HOST_SIZE, mode))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cv_timedwait_sig(&syncdp->syncd_cv, &syncdp->syncd_mutex,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Woken by a signal, not a link down event */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Add an RDC set to an interface
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the interface is new, add it to the list of interfaces.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forterdc_add_to_if(rdc_srv_t *svp, struct netbuf *addr, struct netbuf *r_addr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((addr->buf == NULL) || (r_addr->buf == NULL))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup a new interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte new = (rdc_if_t *)kmem_zalloc(sizeof (*new), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte new->srv = rdc_create_svinfo(svp->ri_hostname, &svp->ri_addr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* search for existing interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((bcmp(ip->ifaddr.buf, addr->buf, addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (bcmp(ip->r_ifaddr.buf, r_addr->buf, r_addr->len) == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* found matching interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* add new into the chain */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* start daemon */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (nsc_create_process(rdc_health_thread, ip, TRUE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* mark usage type */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* throw away new if it was not used */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Update an interface following the removal of an RDC set.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If there are no more RDC sets using the interface, delete it from
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the list of interfaces.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Either clear krdc->intf, or ensure !IS_CONFIGURED(krdc) before calling this.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * search for RDC sets using this interface and update
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the isprimary and issecondary flags.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* mark and wait for daemon to exit */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* remove from chain */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ipp = &rdc_if_top; *ipp; ipp = &((*ipp)->next)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* free unused interface structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check the status of the link to the secondary, and optionally update
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the primary-side ping variables.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For use on a primary only.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * TRUE - interface up.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FALSE - interface down.
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana "!rdc_check_secondary: ip %p, isprimary %d, issecondary %d",
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana cmn_err(CE_WARN, "!rdc_check_secondary: ip %p, ip->deadness %d",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* quick look */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ((ip->deadness > rdc_health_thres) ? FALSE : TRUE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update (slow) with lock */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ping has not been received since last update
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or we have not yet been pinged,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the health thread has started only as a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * local client so far, not so on the other side
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* time has passed, so move closer to death */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* avoid the wrap */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Start back at the max possible version
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * since the remote server could come back
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on a different protocol version.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Update the interface structure with the latest ping info, and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * perform interface up/down transitions if required.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For use on a primary only.
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana "!rdc_update_health: ip %p, isprimary %d, issecondary %d",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* interface down */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* scan rdc sets and update status */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* mark down */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * check for possible race with
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * with delete logic
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana "hm detected secondary "
3270659f55e0928d6edec3d26217cc29398a8149Srikanth, Ramana "interface down");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* dump async queues */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* dump allocated bufs */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Link has gone down, notify rdcsyncd daemon */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* interface up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Link has come back up */