Show lqe_passthru.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.
*
*/
/*
* lqe_passthru.c: The "upper" half and "lower" half of lqe, i.e. the
* data interface that we provide to users of the lqe service *and*
* the data interface we use to send messages on behalf of our users.
*
* $Id: lqe_passthru.c,v 1.1 2005/01/26 01:30:59 cerpa Exp $
*/
char lqe_passthru_c_cvsid[] = "$Id: lqe_passthru.c,v 1.1 2005/01/26 01:30:59 cerpa Exp $";
#include <stdio.h>
#include <stdlib.h>
#include "lqe_i.h"
/********************************************************************/
/*
* This callback is called whenever a packet arrives up from the
* underlying datalink interfaces
*/
static int
lqe_from_lower(link_pass_ctx_t *ctx, link_pkt_t *link_pkt, int data_len)
{
neighbor_list_t *nl = (neighbor_list_t *) link_pass_data(ctx);
lqe_pkt_t *lqe_pkt = (lqe_pkt_t *) link_pkt->data;
link_pkt_t up_link_hdr = *link_pkt;
buf_t *up_pkt;
elog(LOG_DEBUG(70), "calling lqe_reciever(), with pkt type: %d",
link_pkt->type);
/*
* 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_LQE) {
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 lqe header
*/
if (data_len < sizeof(lqe_pkt_t)) {
elog(LOG_ERR, "got a short lqe packet (%d bytes < %d)!",
data_len, sizeof(lqe_pkt_t));
goto done;
}
/* We now know that the data pointed to by lqe_pkt is valid */
elog(LOG_DEBUG(3), "got lqe packet from node [%d] with seqno:"
" %llu, with inner type: %d", lqe_pkt->src_id,
lqe_pkt->seqno, lqe_pkt->inner_type);
/* Update packet statistics for this neighbor */
update_stats(nl, &up_link_hdr, lqe_pkt);
/*
* Send it up the stack, modifying *only* the protocol number in the
* link header
*/
up_link_hdr.type = lqe_pkt->inner_type;
up_pkt = buf_new();
/* first construct the link header */
bufcpy(up_pkt, &up_link_hdr, sizeof(up_link_hdr));
/* followed by user data */
bufcpy(up_pkt, lqe_pkt->data, data_len - sizeof(lqe_pkt_t));
/* send it up */
elog(LOG_DEBUG(5), "sending packet up to the application");
link_pass_to_upper(ctx, up_pkt);
done:
return EVENT_RENEW;
}
/*
* Callback when the queue of packets written to our local device file
* is serviced
*/
static int lqe_from_upper(link_pass_ctx_t *ctx, link_pkt_t *link_pkt_in,
int data_len)
{
neighbor_list_t *nl = (neighbor_list_t *) link_pass_data(ctx);
/* pkt_out is the packet we're getting ready to transmit */
buf_t *pkt_out = buf_new();
/* Create the lqe-specific header */
lqe_pkt_t lqe_hdr = {
src_id: my_node_id,
inner_type: link_pkt_in->type,
/* the upper layer puts the sender info in the link_pkt src field */
sender_id: (node_id_t)link_pkt_in->src.id,
/* increase seqno for this source / next hop pair */
seqno: ++(nl->seq_num[(uint32_t)link_pkt_in->src.id]
[(uint32_t)link_pkt_in->dst.id])
};
/* Create our *outgoing* link header */
link_pkt_t link_hdr = *link_pkt_in;
link_hdr.type = PKT_TYPE_LQE;
/* we update the link_hdr src field with our source id */
link_hdr.src.id = (if_id_t) my_node_id;
/*
* Construct the packet: outer link header, inner lqe header,
* user payload
*/
bufcpy(pkt_out, &link_hdr, sizeof(link_hdr));
bufcpy(pkt_out, &lqe_hdr, sizeof(lqe_hdr));
bufcpy(pkt_out, link_pkt_in->data, data_len);
elog(LOG_DEBUG(3), "lqe packet sent; src_id: %u, inner pkt "
"type: %u, seqno: %llu", lqe_hdr.src_id,
lqe_hdr.inner_type, lqe_hdr.seqno);
/* Send to the lower interface */
link_pass_to_lower(ctx, pkt_out);
/* Even if the passthru is blocked, our packet is queued, so we
* can forget about it. So we always return 0 here to register
* that we're prepared to process the next message */
return 0;
}
/*
* Register the lqe device that other processes open to send
* packets and gather statistics on the link.
*/
void lqe_register_passthru(neighbor_list_t *nl)
{
/* set options for the link provider interface */
link_pass_opts_t opts = {
description: "LQE Adaptor",
uses: {
name: nl->link_uses,
data: nl,
q_opts: {
inq_len: 200,
//outq_len: 1
},
pkt_type: PKT_TYPE_LQE
},
provides: {
name: nl->link_provides,
data: nl
},
pkt_from_lower: lqe_from_lower,
pkt_from_upper: lqe_from_upper,
mtu_adjust: -sizeof(lqe_pkt_t)
};
/* try to register the packetdev as a link interface */
if (link_pass_new(&opts, &(nl->pass_context)) < 0) {
elog(LOG_CRIT, "can't create passthru %s: %m",
link_name(&opts.provides, NULL));
exit(1);
}
elog(LOG_INFO, "created upper interface, %s",
link_pass_name(nl->pass_context, NULL));
}
See more files for this project here