linkstats_status.c from EmStar at Krugle
Show linkstats_status.c syntax highlighted
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* linkstats_status.c: Functions that provide the status interface to
* the users of the linkstats service
*
* $Id: linkstats_status.c,v 1.10 2004/09/15 18:03:10 girod Exp $
*/
char linkstats_status_c_id[] = "$Id: linkstats_status.c,v 1.10 2004/09/15 18:03:10 girod Exp $";
#include "linkstats_i.h"
#define NULL_TIME(timeval) ((timeval).tv_sec == 0 && (timeval).tv_usec == 0)
/****************** Status Device Printing ************************/
static int marshal_status(neighbor_list_t *nl, buf_t *buf)
{
neighbor_el_t *ne;
int num = 0;
/* copy all the entries onto the buf */
for (ne = neighbor_list_top(nl); ne; ne = neighbor_list_next(ne)) {
bufcpy(buf, &ne->info, sizeof(ne->info));
num++;
}
return num;
}
char *print_ago(struct timeval *now, struct timeval *t)
{
DECLARE_STATIC_BUF_RING(buf, 5, 20);
if (NULL_TIME(*t))
sprintf(buf, "--");
else
sprintf(buf, "%.2f", misc_tv_offset(now, t) / MILLION_F);
return buf;
}
static int linkstats_status_printable(status_context_t *info, buf_t *buf)
{
neighbor_list_t *nl = (neighbor_list_t *) sd_data(info);
buf_t *bin_buf = buf_new();
int num_neighbors = marshal_status(nl, bin_buf), i;
neigh_t *n = (neigh_t *) bin_buf->buf;
struct timeval now;
gettimeofday(&now, NULL);
bufprintf(buf, "Interface ID Connectivity IN (%%) Last Heard\n"
"------------ ------------------- ----------\n");
for (i = 0; i < num_neighbors; n++, i++)
bufprintf(buf, "%12s %19.3f %10s\n", print_if_id(n->if_id),
n->conn_in, print_ago(&now, &n->last_heard));
buf_free(bin_buf);
return STATUS_MSG_COMPLETE;
}
static int linkstats_status_binary(status_context_t *info, buf_t *buf)
{
neighbor_list_t *nl = (neighbor_list_t *) sd_data(info);
marshal_status(nl, buf);
return STATUS_MSG_COMPLETE;
}
void linkstats_status_notify(neighbor_list_t *nl)
{
elog(LOG_DEBUG(2), "notifying status interface");
g_status_dev_notify(nl->status);
}
/************* Evaluation of Neighbor State ***********************/
/*
* Evaluate one neighbor. If the state has changed, return 1; else,
* return 0
*/
int linkstats_evaluate_one(neighbor_list_t *nl, neighbor_el_t *ne)
{
elog(LOG_DEBUG(2), "evaluating neighbor id %s",
print_if_id(ne->info.if_id));
elog(LOG_DEBUG(5), "Previous connectivity value: %3.2f -- New "
"connectivity value: %3.2f", ne->status_conn*100.0,
ne->info.conn_in*100.0);
/* if connectivity has changed, update value and notify */
if(ne->status_conn != ne->info.conn_in) {
ne->status_conn = ne->info.conn_in;
return 1;
}
return 0;
}
/* Evaluate the state of ONE neighbor */
void linkstats_evaluate(neighbor_list_t *nl, neighbor_el_t *ne)
{
if (linkstats_evaluate_one(nl, ne))
linkstats_status_notify(nl);
}
/* Evaluate the state of ALL our neighbors */
void linkstats_evaluate_all(neighbor_list_t *nl)
{
neighbor_el_t *ne;
int notify = 0;
/* If there are new neighbors, we nofify */
if (nl->num_neighbors < neighbor_list_qlen(nl)) {
nl->num_neighbors = neighbor_list_qlen(nl);
notify = 1;
goto notify;
}
/* if there is new data from some neighbor, we notify */
for (ne = neighbor_list_top(nl); ne; ne = neighbor_list_next(ne))
notify += linkstats_evaluate_one(nl, ne);
notify:
if (notify)
linkstats_status_notify(nl);
}
/* Check neighbors connectivity values */
static int eval_periodic_timer(void *data, int interval, g_event_t *ev)
{
neighbor_list_t *nl = (neighbor_list_t *) data;
linkstats_evaluate_all(nl);
return EVENT_RENEW;
}
void linkstats_status_init(neighbor_list_t *nl)
{
/* Basic opts for our linkstats status device */
status_dev_opts_t status_opts = {
device: {
devname: link_pass_name(nl->pass_context, "linkstats"),
device_info: nl,
},
printable: linkstats_status_printable,
binary: linkstats_status_binary
};
/* Now create the status device */
if (g_status_dev(&status_opts, &nl->status) < 0) {
elog(LOG_CRIT, "can't create status device %s: %m",
status_opts.device.devname);
exit(1);
}
/* Every second, evaluate all neighbors connectivity values to check
* if they have chenged */
g_timer_add(1000, eval_periodic_timer, nl, NULL, NULL);
}
See more files for this project here