[Tinyos-2-commits] CVS: tinyos-2.x/tos/lib/net/tymo ForwardingEngineM.nc, NONE, 1.1 LinkMonitor.nc, NONE, 1.1 LoopBackM.nc, NONE, 1.1 RouteSelect.nc, NONE, 1.1 RoutingTable.nc, NONE, 1.1 RoutingTableInfo.nc, NONE, 1.1 routing.h, NONE, 1.1 routing_table.h, NONE, 1.1

Romain Thouvenin strabest at users.sourceforge.net
Mon Feb 18 12:25:00 PST 2008


Update of /cvsroot/tinyos/tinyos-2.x/tos/lib/net/tymo
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv24227/tymo

Added Files:
	ForwardingEngineM.nc LinkMonitor.nc LoopBackM.nc 
	RouteSelect.nc RoutingTable.nc RoutingTableInfo.nc routing.h 
	routing_table.h 
Log Message:
Initial tymo commit

--- NEW FILE: ForwardingEngineM.nc ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "routing.h"

/**
 * ForwardingEngineM - Handles received packets of a certain protocol
 * in a multihop context.  The component uses a route selector to
 * determine if the packet should be forwarded or passed to the upper
 * layer. If the packet is forwarded, the next hop is given by the
 * route selector.
 *
 * @author Romain Thouvenin
 */

//TODO probably need a lot of cleaning, and to be moved elsewhere
generic module ForwardingEngineM () {
  provides { //For the upper layer
    interface AMSend[uint8_t id];
    interface Receive[uint8_t id];
    interface Intercept[uint8_t id];
    interface LinkMonitor;
  }
  uses {
    interface RouteSelect;
    interface AMSend as SubSend;
    interface AMPacket;
    interface Packet as PPacket; 
    interface Packet as SubPacket;
    interface PacketAcknowledgements as Acks;
    interface Receive as SubReceive;
    interface Timer<TMilli>;
  }

  provides interface MHControl;
}

implementation {
  message_t buf; //first available, do NOT use it
  message_t * avail = &buf;
  message_t * waiting;
  uint8_t typebuf;
  uint8_t lenWaiting;
  uint8_t amWaiting;
  am_addr_t bufAddr;
  am_addr_t * addrWaiting;
  bool lockAvail, lockWaiting;
  uint32_t wait_time;
  bool acks;

  enum {
    WAIT_BEFORE_RETRY = 100,
    MAX_WAIT = 10 * WAIT_BEFORE_RETRY
  };

  command error_t AMSend.send[uint8_t am](am_addr_t addr, message_t * msg, uint8_t len){
    switch(call RouteSelect.selectRoute(msg, &addr, &am)){
    case FW_SEND:
      call PPacket.setPayloadLength(msg, len);
      acks = DYMO_LINK_FEEDBACK && (call Acks.requestAck(msg) == SUCCESS);
      return call SubSend.send(call AMPacket.destination(msg), msg, call SubPacket.payloadLength(msg));

    case FW_WAIT: 
      atomic {
	if(lockWaiting)
	  return EBUSY;
	lockWaiting = TRUE;
      }
      waiting = msg;
      amWaiting = am;
      call PPacket.setPayloadLength(msg, len);
      lenWaiting = call SubPacket.payloadLength(msg);
      bufAddr = addr;
      addrWaiting = &bufAddr;
      wait_time = 0;
      call Timer.startOneShot(WAIT_BEFORE_RETRY); 
      dbg("fwe", "FE: I'll retry later.\n");
      return SUCCESS;
      
    default: //We don't allow sending to oneself
      return FAIL; 
    }
  }

  event message_t * SubReceive.receive(message_t * msg, void * payload, uint8_t len){
    dbg("fwe", "FE: Received a message from %u\n", call AMPacket.source(msg));
    signal MHControl.msgReceived(msg);
    switch(call RouteSelect.selectRoute(msg, NULL, &typebuf)){
    case FW_SEND:
      atomic {
	if(lockAvail)
	  return msg;
	lockAvail = TRUE;
      }
      if ( signal Intercept.forward[typebuf](msg, call PPacket.getPayload(msg, call PPacket.payloadLength(msg)), call PPacket.payloadLength(msg)) ) {
	  call SubSend.send(call AMPacket.destination(msg), msg, len);
      }
      return avail;

    case FW_RECEIVE:
      payload = call PPacket.getPayload(msg, call PPacket.payloadLength(msg));
      return signal Receive.receive[typebuf](msg, payload, call PPacket.payloadLength(msg));

    case FW_WAIT:
      atomic {
	if(lockAvail || lockWaiting)
	  return msg;
	lockAvail = lockWaiting = TRUE;
      }
      waiting = msg;
      lenWaiting = len;
      addrWaiting = NULL;
      wait_time = 0;
      call Timer.startOneShot(WAIT_BEFORE_RETRY);
      return avail;

    default:
      return msg;
    }
  }

  event void SubSend.sendDone(message_t * msg, error_t e){
    dbg("fwe", "FE: Sending done.\n");
    if( (e == SUCCESS) && acks ){
      if( !(call Acks.wasAcked(msg)) ){
	e = FAIL;
	dbg("fwe", "FE: The message was not acked => FAIL.\n");
	signal MHControl.sendFailed(msg, 2);
	signal LinkMonitor.brokenLink(call AMPacket.destination(msg));
      }
    } else if (e != SUCCESS) {
      dbg("fwe", "FE: But failed!\n");
      signal MHControl.sendFailed(msg, 1);
    }

    if(lockAvail){
      avail = msg;
      atomic {
	lockAvail = FALSE;
      }
    } else {
      signal AMSend.sendDone[amWaiting](msg, e);
      atomic {
	lockWaiting = FALSE;
      }
    }
  }

  event void Timer.fired(){
    switch(call RouteSelect.selectRoute(waiting, addrWaiting, &amWaiting)){
    case FW_SEND:
      dbg("fwe", "FE: I'm retrying to send my message.\n");
      if (addrWaiting) {
	call SubSend.send(call AMPacket.destination(waiting), waiting, lenWaiting);
      } else if ( signal Intercept.forward[amWaiting](waiting, 
				      call PPacket.getPayload(waiting, call PPacket.payloadLength(waiting)), 
				      call PPacket.payloadLength(waiting)) ) {
	call SubSend.send(call AMPacket.destination(waiting), waiting, lenWaiting);
      }
      call Timer.stop();
      break;

    case FW_WAIT:
      dbg("fwe", "FE: I'll retry later again.\n");
      wait_time += call Timer.getdt();
      if(wait_time < MAX_WAIT){
	call Timer.startOneShot(wait_time);
	break;
      }
      //else: Continue to default

    default:
      if(addrWaiting)
	signal AMSend.sendDone[amWaiting](waiting, FAIL);
      if(lockAvail){
	avail = waiting;
	atomic {
	  lockAvail = FALSE;
	}
      }
      atomic {
	lockWaiting = FALSE;
      }
    }
  }

  command error_t AMSend.cancel[uint8_t am](message_t *msg){
    if(lockWaiting){
      call Timer.stop();
      atomic {
	lockWaiting = FALSE;
      }
      return SUCCESS;
    } else {
      return call SubSend.cancel(msg);
    }
  }

  command void * AMSend.getPayload[uint8_t am](message_t *msg, uint8_t len){
    return call PPacket.getPayload(msg, len);
  }

  command uint8_t AMSend.maxPayloadLength[uint8_t am](){
    return call PPacket.maxPayloadLength();
  }


  /*** defaults ***/

 default event message_t * Receive.receive[uint8_t am](message_t * msg, void * payload, uint8_t len){
   return msg;
 }

 default event void AMSend.sendDone[uint8_t am](message_t * msg, error_t e){}

 default event bool Intercept.forward[uint8_t am](message_t * msg, void * payload, uint8_t len){
   return TRUE;
 }

 default event void MHControl.msgReceived(message_t * msg){ }

 default event void MHControl.sendFailed(message_t * msg, uint8_t why){ }

 default event void LinkMonitor.brokenLink(addr_t neighbor){ }
}

--- NEW FILE: LinkMonitor.nc ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "AM.h"

/**
 * LinkMonitor - Interface to signals broken links in the neighborhood.
 *
 * @author Romain Thouvenin
 */

interface LinkMonitor {

  event void brokenLink(am_addr_t neighbor);

}

--- NEW FILE: LoopBackM.nc ---
module LoopBackM {
  provides {
    interface AMSend[uint8_t id];
    interface Receive[uint8_t id];
  }
  uses {
    interface AMSend as SubSend[uint8_t id];
    interface Receive as SubReceive[uint8_t id];
    interface AMPacket;
    interface Packet;
  }
}
implementation {

  message_t first_avail;
  message_t * avail = &first_avail;

  message_t * buf_msg;
  uint8_t buf_am;

  task void sendDoneTask(){
    signal AMSend.sendDone[buf_am](buf_msg, SUCCESS);
  }

  command error_t AMSend.send[uint8_t am](am_addr_t addr, message_t *msg, uint8_t len){ //TODO set acks
    if(addr == call AMPacket.address()){
      buf_am = am;
      buf_msg = msg;
      *avail = *msg;
      dbg("lo", "LO: I am sending the buffer %p.\n", avail);
      dbg("lo", "LO: its length is %hhu.\n", len);
      call Packet.setPayloadLength(avail, len);
      call AMPacket.setDestination(avail, addr);
      call AMPacket.setSource(avail, addr);
      post sendDoneTask();
      avail = signal Receive.receive[call AMPacket.type(msg)](
				 avail, 
				 call Packet.getPayload(avail, len),
				 len);
      return SUCCESS;
    } else {
      return call SubSend.send[am](addr, msg, len);
    }
  }

  command error_t AMSend.cancel[uint8_t am](message_t *msg){
    if(call AMPacket.destination(msg) == call AMPacket.address()){
      return FAIL;
    } else {
      return call SubSend.cancel[am](msg);
    }
  }

  command void * AMSend.getPayload[uint8_t am](message_t *msg, uint8_t len){
    return call SubSend.getPayload[am](msg, len);
  }

  command uint8_t AMSend.maxPayloadLength[uint8_t am](){
    return call SubSend.maxPayloadLength[am]();
  }

  event void SubSend.sendDone[uint8_t am](message_t *msg, error_t error){
    signal AMSend.sendDone[am](msg, error);
  }


  event message_t * SubReceive.receive[uint8_t am](message_t *msg, void *payload, uint8_t len){
    return signal Receive.receive[am](msg, payload, len);
  }

 default event void AMSend.sendDone[uint8_t am](message_t *msg, error_t error){ }

 default event message_t * Receive.receive[uint8_t am](message_t *msg, void *payload, uint8_t len){ return msg; }

}

--- NEW FILE: RouteSelect.nc ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "routing.h"

/**
 * Interface to a route selection in a multi-hop context.
 *
 * @author Romain Thouvenin
 */

interface RouteSelect {

  /**
   * Ask the routing engine to fill a message with routing
   * information, in order to send it to its target.
   *
   * @param msg The message to be sent
   * @param destination The target of the route. If NULL, it is assumed it can be read in the packet
   * @return The action that should be taken by the forwarding engine.
   */
  command fw_action_t selectRoute(message_t * msg, addr_t * destination, uint8_t * am_type);
  
}

--- NEW FILE: RoutingTable.nc ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "routing_table.h"

/**
 * RoutingTable - Interface to manipulate a data structure that stores
 * a table of routes toward a number of destinations.
 *
 * @author Romain Thouvenin
 */

interface RoutingTable {

  /**
   * Request for a route toward a destination.
   * @param Address of the destination node
   * @param info A pointer where to store the routing information 
   *        associated to the destination, ignored if NULL
   * @return SUCCESS if the route exists<br/>
   *         EBUSY if the route does not exist but may be available soon
   *         FAIL  if the route exists but is broken
   */
  command error_t getRoute(addr_t address, rt_info_t * info);

  command error_t getForwardingRoute(addr_t address, rt_info_t * info);

  /**
   * Signal that a route has been removed from the table.
   * @param route_info Routing information associated to the evicted entry
   * @param r reason of the eviction
   */
  event void evicted(const rt_info_t * route_info, reason_t r);

}

--- NEW FILE: RoutingTableInfo.nc ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#include "routing_table.h"

typedef nx_struct rt_link {
  nx_addr_t target;
  nx_addr_t nexthop;
} rt_link_t;

interface RoutingTableInfo {

  /**
   * Size of the table.
   * @return the number of entries stored in the table
   */
  command uint8_t size();

  command uint8_t maxSize();

  command uint8_t getTableContent(rt_info_t * buf);

  command uint8_t getLinks(rt_link_t * buf);

}

--- NEW FILE: routing.h ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#ifndef _DYMO_ROUTING_H_
#define _DYMO_ROUTING_H_

#include "AM.h"

typedef am_addr_t addr_t;
typedef nx_am_addr_t nx_addr_t;
typedef uint16_t seqnum_t;
typedef nx_uint16_t nx_seqnum_t;

#ifndef MAX_TABLE_SIZE
#define MAX_TABLE_SIZE 5
#endif

#ifndef DYMO_HOPLIMIT
#define DYMO_HOPLIMIT 10
#endif

#ifndef DYMO_ROUTE_AGE_MAX
#define DYMO_ROUTE_AGE_MAX 300000
#endif

#ifndef DYMO_ROUTE_TIMEOUT
#define DYMO_ROUTE_TIMEOUT 10000
#endif

#ifndef DYMO_APPEND_INFO
#define DYMO_APPEND_INFO      0      //1 to append info to forwarded RMs
#endif

#ifndef DYMO_INTER_RREP
#define DYMO_INTER_RREP       1      //1 to allow intermediate RREP 
#endif

#ifndef DYMO_FORCE_INTER_RREP
#define DYMO_FORCE_INTER_RREP 1      //1 to send intermediate RREP even without target's seqnum in the RREQ
#endif

#ifndef DYMO_LINK_FEEDBACK
#define DYMO_LINK_FEEDBACK    1      //1 to use acks to detect broken links
#endif

enum {
  AM_MULTIHOP = 9,
  AM_DYMO = 8
};

typedef enum {
  DYMO_RREQ = 10,
  DYMO_RREP,
  DYMO_RERR
} dymo_msg_t;

//processing action
typedef enum {
  ACTION_KEEP,   //info is kept in the forwarded message
  //  ACTION_UPDATE, //info is kept, and updated with the provided info
  ACTION_DISCARD, //info is not kept in the forwarded message
  ACTION_DISCARD_MSG //The message won't be forwarded, no need to build a forwarded message anymore
} proc_action_t;

typedef enum {
  FW_SEND,      //Put the message in the sending queue
  FW_RECEIVE,   //Give the message to the upper layer
  FW_WAIT,      //Retry later
  FW_DISCARD,   //Discard the message
} fw_action_t;


#endif

--- NEW FILE: routing_table.h ---
/*
 * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin at gmail.com>
 * Published under the terms of the GNU General Public License (GPLv2).
 */

#ifndef _ROUTING_TABLE_H_
#define _ROUTING_TABLE_H_

#include "routing.h"

/**
 * Types associated to a routing table.
 */

typedef struct rt_info {
  addr_t address;
  addr_t nexthop;
  seqnum_t seqnum;
  bool has_hopcnt;
  uint8_t hopcnt;
} rt_info_t;

typedef enum {
  REASON_FULL,
  REASON_OLD,
  REASON_UNREACHABLE
} reason_t;

#endif



More information about the Tinyos-2-commits mailing list