/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RDC interface health monitoring code.
*/
#ifdef _SunOS_2_6
/*
* on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
* anyway and make it look like we included it. Yuck.
*/
#define _RPC_TYPES_H
typedef int enum_t;
#else
#ifndef DS_DDICT
#endif
#endif /* _SunOS_2_6 */
#include <sys/nsc_thread.h>
#ifdef DS_DDICT
#endif
#include "rdc_io.h"
#include "rdc_clnt.h"
/*
* Forward declarations.
*/
static void rdc_update_health(rdc_if_t *);
/*
* Global data.
*/
/*
* These structures are added when a new host name is introduced to the
* kernel. They never disappear (but that won't waste much space at all).
*/
typedef struct rdc_link_down {
/*
* IPv6 addresses are represented as 16bit hexadecimal integers
* separated by colons. Contiguous runs of zeros can be abbreviated by
* double colons:
* FF02:0:0:0:0:1:200E:8C6C
* |
* v
* FF02::1:200E:8C6C
*/
void
{
int i;
for (i = 0; i < end; i++) {
if (i > 0)
/* first, last, or non-zero value */
} else {
/* single zero */
} else {
/* skip contiguous zeros */
i++;
}
}
}
}
static void
{
} else {
"!SNDR: Interface %d.%d.%d.%d <==> %d.%d.%d.%d : %s",
updown);
}
}
static void
{
}
static void
{
}
/*
* Health monitor for a single interface.
*
* The secondary sends ping RPCs to the primary.
* The primary just stores the results and updates its structures.
*/
static void
{
struct timeval t;
int sec = 0;
/* setup RPC timeout */
t.tv_sec = rdc_rpc_tmout;
t.tv_usec = 0;
/* primary ifaddr */
/* secondary ifaddr */
} else {
}
/* RPC failed - link is down */
/*
* don't print messages if also
* a primary - the primary will
* take care of it.
*/
down = 1;
}
/*
* Start back at the max possible version
* since the remote server could come back
* on a different protocol version.
*/
} else {
/*
* was failed, but now ok
*
* don't print messages if also
* a primary - the primary will
* take care of it.
*/
down = 0;
}
}
}
sec = 0;
}
}
/* signal that this thread is done */
}
int
{
int rc = 0;
/* search for existing interface structure */
continue;
/* found matching interface structure */
rc = 1;
rc = 1;
}
break;
}
}
return (rc);
}
/*
* Set the rdc rpc version of the rdc_if_t.
*
* Called from incoming rpc calls which start before
* the health service becomes established.
*/
void
{
} else {
}
/* search for existing interface structure */
continue;
/* found matching interface structure */
#ifdef DEBUG
#endif
break;
}
}
}
/*
* Free all the rdc_link_down structures (only at module unload time)
*/
void
{
rdc_link_down_t *p;
rdc_link_down_t *q;
if (rdc_link_down == NULL)
return;
q = p;
p = p->next;
kmem_free(q, sizeof (*q));
}
kmem_free(rdc_link_down, sizeof (*q));
}
/*
* Look up the supplied hostname in the rdc_link_down chain. Add a new
* entry if it isn't found. Return a pointer to the new or found entry.
*/
static rdc_link_down_t *
{
rdc_link_down_t *p;
if (rdc_link_down == NULL) {
}
/* Match */
return (p);
}
}
/* No match, must create a new entry */
p = kmem_zalloc(sizeof (*p), KM_SLEEP);
p->link_down = 1;
rdc_link_down->next = p;
return (p);
}
/*
* Handle the RDC_LINK_DOWN ioctl.
* The user specifies which host he is interested in.
* This function is woken up when the link to that host goes down.
*/
/* ARGSUSED3 */
int
{
int rc = 0;
return (EFAULT);
/* Woken by a signal, not a link down event */
}
}
return (rc);
}
/*
* Add an RDC set to an interface
*
* If the interface is new, add it to the list of interfaces.
*/
rdc_if_t *
int primary)
{
return (NULL);
/* setup a new interface structure */
if (!new)
return (NULL);
return (NULL);
}
/* search for existing interface structure */
/* found matching interface structure */
break;
}
}
if (!ip) {
/* add new into the chain */
rdc_if_top = new;
/* start daemon */
return (NULL);
}
}
/* mark usage type */
if (primary) {
} else {
}
/* throw away new if it was not used */
}
return (ip);
}
/*
* Update an interface following the removal of an RDC set.
*
* If there are no more RDC sets using the interface, delete it from
* the list of interfaces.
*
* Either clear krdc->intf, or ensure !IS_CONFIGURED(krdc) before calling this.
*/
void
{
int pfound = 0;
int sfound = 0;
int index;
/*
* search for RDC sets using this interface and update
* the isprimary and issecondary flags.
*/
delete = 0;
pfound = 1;
} else {
sfound = 1;
}
break;
}
}
return;
}
/* mark and wait for daemon to exit */
/* remove from chain */
break;
}
}
/* free unused interface structure */
}
/*
* Check the status of the link to the secondary, and optionally update
* the primary-side ping variables.
*
* For use on a primary only.
*
* Returns:
* TRUE - interface up.
* FALSE - interface down.
*/
int
{
#ifdef DEBUG
"!rdc_check_secondary: ip %p, isprimary %d, issecondary %d",
#endif
return (FALSE);
}
#ifdef DEBUG
#endif
return (FALSE);
}
if (!update) {
/* quick look */
}
/* update (slow) with lock */
/*
* ping has not been received since last update
* or we have not yet been pinged,
* the health thread has started only as a
* local client so far, not so on the other side
*/
/* time has passed, so move closer to death */
/* avoid the wrap */
}
}
/*
* Start back at the max possible version
* since the remote server could come back
* on a different protocol version.
*/
}
} else {
}
return (rc);
}
/*
* Update the interface structure with the latest ping info, and
*
* For use on a primary only.
*/
static void
{
int index;
#ifdef DEBUG
"!rdc_update_health: ip %p, isprimary %d, issecondary %d",
#endif
return;
}
/* interface down */
/* scan rdc sets and update status */
/* mark down */
/*
* check for possible race with
* with delete logic
*/
if (!IS_ENABLED(urdc)) {
continue;
}
"hm detected secondary "
"interface down");
/* dump async queues */
}
}
/* dump allocated bufs */
}
/* Link has gone down, notify rdcsyncd daemon */
}
}
} else {
/* interface up */
}
/* Link has come back up */
}
}
}