Show idr_lower.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.
*
*/
/*
* idr_lower.c: The "lower" half of idr, i.e. handling the link
* layer interfaces underneath the daemon that we use to send the
* packets.
*
* $Id: idr_lower.c,v 1.5 2003/07/11 22:29:52 cerpa Exp $
*/
char idr_lower_c_cvsid[] = "$Id: idr_lower.c,v 1.5 2003/07/11 22:29:52 cerpa Exp $";
#include <stdio.h>
#include <stdlib.h>
#include "link/link.h"
#include "idr_i.h"
/*******************************************************************/
/*
* This callback is called whenever a packet arrives up from one of
* the underlying datalink interfaces
*/
static int idr_receive(link_pkt_t *link_pkt, ssize_t data_len, link_context_t *link)
{
idr_state_t *f = (idr_state_t *) link_opts(link)->data;
idr_pkt_t *idr_pkt = (idr_pkt_t *) link_pkt->data;
// Make sure the packet has the right packet type. Since we
// specified the desired packet type when we registered to receive
// packets, this test should never fail.
if (link_pkt->type != PKT_TYPE_IDR) {
elog(LOG_WARNING, "got a packet not meant for us - filter failed!");
goto done;
}
// Make sure the data portion of the packet is at least the size of
// a idr packet header
if (data_len < sizeof(idr_pkt_t)) {
elog(LOG_ERR, "got a short idr packet (%d bytes < %d)!", data_len,
sizeof(idr_pkt_t));
goto done;
}
// We now know that the data pointed to by idr_pkt is valid
switch( idr_pkt->sub_type) {
case IDR_DATA:
elog(LOG_DEBUG(4), "got idr data packet");
idr_handle_data_pkt(f, link_pkt, data_len);
break;
case IDR_NACK:
elog(LOG_DEBUG(4), "got idr nack packet");
idr_handle_nack_pkt(f, link_pkt, data_len);
break;
default:
elog(LOG_ERR, "got idr packet with an unknown subtype %d\n",
idr_pkt->sub_type);
}
done:
free(link_pkt);
return EVENT_RENEW;
}
/*
* This function opens one of the underlying transport devices used by
* the idr daemon (e.g., a basic datalink such as motenic)
*/
void idr_open_link(idr_state_t *f, int link_index, int POT)
{
idr_iface_t *i;
// make sure we don't have too many interfaces open
if (f->num_ifaces >= MAX_IFACES) {
elog(LOG_ERR, "can't open link interface: too many interfaces!");
exit(1);
}
// get a pointer to the next available iface struct
i = &(f->iface[f->num_ifaces]);
// set options for this link
memset(i, 0, sizeof(idr_iface_t));
i->if_opts.link_index = link_index;
i->if_opts.pkt_type = PKT_TYPE_IDR;
// Make the queues large enough to handle retransmission storms
i->if_opts.q_opts.outq_len = 500;
i->if_opts.q_opts.inq_len = 3000;
i->if_opts.receive = idr_receive;
i->if_opts.data = f;
// try to open it
if (link_open(&i->if_opts, &i->if_context) < 0) {
elog(LOG_CRIT, "can't open %s: %m", link_name(&i->if_opts));
exit(1);
}
if (link_ioctl(i->if_context, LINK_SET_POT, &POT) < 0)
elog(LOG_CRIT, "warning: can't set POT: %m");
// Open succeeded - increment interface count
f->num_ifaces++;
elog(LOG_NOTICE, "opened lower interface %d: %s",
f->num_ifaces, link_name(&i->if_opts));
}
/*
* Send a link_pkt to all interfaces opened by the function above
*/
void idr_send_to_all(idr_state_t *f, link_pkt_t *pkt, int data_len)
{
int i;
uint8_t count;
idr_pkt_t *p=(idr_pkt_t *)(pkt->data);
if (p->sub_type==IDR_DATA) {
idr_data_pkt_t *d=(idr_data_pkt_t *)(p->next_hdr);
count=d->count;
elog(LOG_NOTICE, "Node %d sending DATA packet, count=%d\n",
my_node_id, count);
} else {
idr_nack_pkt_t *n=(idr_nack_pkt_t *)(p->next_hdr);
count=n->count;
elog(LOG_NOTICE, "Node %d sending NACK packet, count=%d\n",
my_node_id, count);
}
elog(LOG_DEBUG(4), "sending; %d interfaces", f->num_ifaces);
for (i = 0; i < f->num_ifaces; i++) {
elog(LOG_DEBUG(4), "sending to %s",
link_name(link_opts(f->iface[i].if_context)));
if (link_send(f->iface[i].if_context, pkt, data_len) < 0)
elog(LOG_WARNING, "sending to %s: %m",
link_name(&(f->iface[i].if_opts)));
}
}
See more files for this project here