centroute_upper.c from EmStar at Krugle
Show centroute_upper.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.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <math.h>
#include "emrun/emrun.h"
#include "link/link.h"
#include <link/link_headers.h>
#include <libmisc/misc.h>
#include <libdev/status_dev.h>
#include <libdev/command_dev.h>
#include <libdev/query_dev.h>
#include <libdev/packet_client.h>
#include <libdev/packet_dev.h>
#include <libdev/em_sched.h>
#include <centroute_i.h>
#include <routing/routing_table.h>
#include <libdev/command_dev.h>
#include <devel/state/ssync.h>
#include <devel/herd/centroute.h>
#include "tos-contrib/herd/tos/system/CentTree_defs.h"
#include "tos-contrib/herd/tos/system/CentTree.h"
#ifndef SECOND
#define SECOND 1000
#endif
#ifndef TOS_BCAST_ADDR
#define TOS_BCAST_ADDR 0xFFFF
#endif
int centroute_data_dev_send(lp_context_t *lp, link_pkt_t *pkt, int datalen,
int loop_needed);
int centroute_data_dev_status(lp_context_t *lp);
int centroute_data_dev_ioctl(lp_context_t *lp, int cmd, void *arg);
int centroute_data_dev_parse_commands(lp_context_t *lp,
parser_state_t *cmd_input);
void centroute_data_dev_usage(lp_context_t *lp, buf_t *buf);
//int send_data_pkt_to_pd(node_t *node, char *data, int len, cr_state_t *crstate);
int send_data_pkt_to_pd(node_t *node, char *data, uint8_t type,
int len, cr_state_t *crstate)
{
pd_hdr_t *pd_hdr=NULL;
int offset=0;
int total_len=0;
node_t *parent=NULL;
int retcode=0;
pd_hdr = create_downstream_pkt_hdr(node, DATA, type,
len, &offset, &total_len);
if (pd_hdr==NULL) {
elog(LOG_ERR, "Cannot send data pkt to node %u: NULL pd_hdr",
node->id);
return -1;
}
parent = find_parent_from_path(node, node->preferred_path);
if (parent==NULL) {
elog(LOG_ERR, "NULL (!) parent for node %u", node->id);
exit(1);
}
// don't send data pkt if parent hasn't verified assoc
if (parent->is_root==0) {
if (parent->state != ASSOCIATED_VERIFIED) {
elog(LOG_ERR, "Node %u's parent (%u) hasn't verified"
" its association (in state %d). Will not send data pkt",
node->id, parent->id, parent->state);
goto done;
}
}
// copy the payload
memcpy(&pd_hdr->data[offset], data, len);
// send the packet to PD
retcode = pd_client_send(crstate->centroute_data_pd, pd_hdr, total_len);
if (retcode < 0) {
elog(LOG_ERR, "Could not send data pkt to node %u: %m", node->id);
goto done;
} else {
elog(LOG_DEBUG(2), "Data pkt to node %u sent to PD successfully",
node->id);
}
done:
free(pd_hdr);
return retcode;
}
int centroute_data_dev_send(lp_context_t *lp, link_pkt_t *pkt, int datalen,
int loop_needed)
{
cr_state_t *crstate = (cr_state_t *)lp_data(lp);
node_t *node=NULL;
int n=0;
uint16_t node_id= (uint16_t)(pkt->dst.id);
link_pkt_t *link_pkt = (link_pkt_t *)pkt;
if (pkt->type != PKT_TYPE_CENTROUTE_DATA) {
elog(LOG_ERR, "Got unexpected pkt type %d, ignoring pkt", pkt->type);
return EINVALIDTYPE;
}
node = find_node_in_local_nodes_list(node_id, crstate);
// TODO: handle transmissions to nodes in OTHER FLOCKS!!!
if (node==NULL) {
elog(LOG_ERR, "Cannot send pkt to node %u; node doesn't exist in"
" local nodes list!", node_id);
return 0;
}
// TODO: perhaps handle A_P case?
if (node->state!=ASSOCIATED_VERIFIED) {
elog(LOG_ERR, "Cannot send data to node %u: node hasn't verified"
" association (state = %d)",
node->id, node->state);
return 0;
}
// node is good
// send the pkt over
n = send_data_pkt_to_pd(node, pkt->data, pkt->ext_type, datalen, crstate);
if (loop_needed) {
link_pkt->src.id = crstate->data_lp_status.if_id;
lp_loop_receive(lp, link_pkt, datalen);
}
// XXX XXX XXX
// Note: changing this to n instead of 0...need to figure out if it's ok
return n;
}
int centroute_data_dev_status(lp_context_t *lp)
{
cr_state_t *crstate = (cr_state_t *)lp_data(lp);
lp_push_status(lp, &(crstate->data_lp_status));
return EVENT_RENEW;
}
int centroute_data_dev_ioctl(lp_context_t *lp, int cmd, void *arg)
{
return 0;
}
int centroute_data_dev_parse_commands(lp_context_t *lp,
parser_state_t *cmd_input)
{
return 0;
}
void centroute_data_dev_usage(lp_context_t *lp, buf_t *buf)
{
}
int create_data_link_dev(cr_state_t *crstate, char *link_name_str,
char *class_name)
{
lp_opts_t opts = {
description: "Centroute raw data interface",
opts: {
name: link_name_str,
if_class: class_name,
data: crstate,
},
initial_status : {
// TODO: fix the mtu!
MTU: 200,
if_id: my_node_id,
},
send: centroute_data_dev_send,
status_request: centroute_data_dev_status,
ioctl: centroute_data_dev_ioctl,
command_request: centroute_data_dev_parse_commands,
usage: centroute_data_dev_usage,
we_are_root:1
};
if (lp_register(&opts, &(crstate->data_lp_context)) < 0) {
elog(LOG_CRIT, "Can't create link device %s: %m",
link_name(&opts.opts, NULL));
exit(1);
}
if (crstate==NULL) {
elog(LOG_ERR, "NULL crstate ptr!");
exit(1);
}
crstate->data_lp_status.active=1;
crstate->data_lp_status.POT=0;
crstate->data_lp_status.MTU=opts.initial_status.MTU;
crstate->data_lp_status.if_id = opts.initial_status.if_id;
return 0;
}
int convert_raw_data_pkt_to_link_pkt(up_hdr_t *up_hdr, link_pkt_t **link_pkt,
uint8_t client_type, int orig_len)
{
int buf_len=sizeof(link_pkt_t)+orig_len;
int payload_len=0;
char *buf=NULL;
int len_adjust=0;
int offset=0;
int i=0;
if (link_pkt==NULL) {
elog(LOG_ERR, "NULL link_pkt ptr");
exit(1);
}
if (up_hdr==NULL) {
elog(LOG_ERR, "NULL up_hdr ptr!");
exit(1);
}
offset = up_hdr->path_entries * sizeof(up_path_entry_t);
len_adjust = offset + sizeof(up_hdr_t);
// adjust buf_len
buf_len -= len_adjust;
payload_len = buf_len - sizeof(link_pkt_t);
// allocate mem for the buf based on the buf_length
buf = malloc(buf_len);
memset(buf, 0, buf_len);
*link_pkt = (link_pkt_t *)buf;
if (up_hdr->final_dst==TOS_BCAST_ADDR) {
(*link_pkt)->dst.id = my_node_id;
} else {
(*link_pkt)->dst.id = up_hdr->final_dst;
}
(*link_pkt)->src.id = up_hdr->orig_src;
(*link_pkt)->type = PKT_TYPE_CENTROUTE_DATA;
(*link_pkt)->ext_type = client_type;
// we're using max hop to store the number of path entries
(*link_pkt)->max_hops = up_hdr->path_entries;
for (i=0; i<up_hdr->path_entries; i++) {
up_path_entry_t *entry = (up_path_entry_t *)(up_hdr->data);
(*link_pkt)->numTx += entry->retx_count;
}
// copy payload
memcpy((*link_pkt)->data, &up_hdr->data[offset], payload_len);
// done, return buf_len which is the length of the entire link_pkt
// INCLUDING the header
return payload_len;
}
See more files for this project here