⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dymotablem.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
/* * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin@gmail.com> * Published under the terms of the GNU General Public License (GPLv2). */#include "dymo_table.h"/** * DymoTableM - Implements a routing table with DYMO routing information. * @param maxsize maximum number of entries in the table, cannot be higher than 51 * * @author Romain Thouvenin */generic module DymoTableM(uint8_t maxsize) {  provides {    interface StdControl;    interface RoutingTable;    interface DymoTable;  }  uses {    interface Timer<TMilli>[uint8_t id];    interface LinkMonitor;  }#ifdef DYMO_MONITORING  provides interface RoutingTableInfo;#endif}implementation {  rt_entry_t table[maxsize];  rt_info_t buf_info;  uint8_t size;   uint8_t num_entries;  uint8_t replace;  /* declared at the end */  void replace_info(uint8_t entry_id, const rt_info_t * route_info);  int8_t get_route(addr_t address);  void delete_route(uint8_t entry_id, reason_t r);  bool is_superior(const rt_info_t * info1, const rt_entry_t * entry, dymo_msg_t msg_type);  void set_timer(uint8_t entry_id, rt_timer_t timer_id);  void cancel_timer(uint8_t entry_id, rt_timer_t timer);  void cancel_timers(uint8_t entry_id);  command error_t StdControl.start(){    num_entries = 0;    size = 0;    replace = 0;    return SUCCESS;  }  command error_t StdControl.stop(){    uint8_t i;    for(i=0; i<num_entries; i++){      if( !(table[i].flags & FLAG_DELETED) ){	cancel_timers(i);      }    }    return SUCCESS;  }  command error_t RoutingTable.getForwardingRoute(addr_t address, rt_info_t * info){    int8_t i = get_route(address);    dbg("dt", "DT: Someone wants a forwarding route for %u.\n", address);    if(i == -1){      dbg("dt", "DT: But I don't have it. => brokenRouteNeeded\n");      buf_info.address = address;      buf_info.seqnum = 0;      buf_info.has_hopcnt = 0;      signal DymoTable.brokenRouteNeeded(&buf_info);      return FAIL;    }    //The caller may want to know what is in the table even if it is broken    if(info && !(table[i].flags & FLAG_DELETED)){      *info = table[i].info;    }    if(table[i].flags & (FLAG_BROKEN | FLAG_DELETED)){      dbg("dt", "DT: But it is deleted. => brokenRouteNeeded\n");      signal DymoTable.brokenRouteNeeded(&table[i].info); //TODO not if not used recently (for other signals too)      return FAIL;    }    cancel_timer(i, ROUTE_NEW);    table[i].flags &= ~FLAG_NEW;    cancel_timer(i, ROUTE_DELETE);    set_timer(i, ROUTE_USED);    table[i].flags |= FLAG_USED;    dbg("dt", "DT: Here it is: %u.\n", table[i].info.nexthop);    return SUCCESS;  }  command error_t RoutingTable.getRoute(addr_t address, rt_info_t * info){    int i = get_route(address);    dbg("dt", "DT: Someone wants a sending route for %u.\n", address);    if(i == -1){      dbg("dt", "DT: But I don't have it. => routeNeeded\n");      signal DymoTable.routeNeeded(address);      return EBUSY;    }    //The caller may want to know what is in the table even if it is broken    if(info){      *info = table[i].info;    }    if(table[i].flags & (FLAG_DELETED | FLAG_BROKEN)){      dbg("dt", "DT: But it is deleted or broken. => routeNeeded\n");      signal DymoTable.routeNeeded(address);      return EBUSY;    }        //We assume the route is going to be used    cancel_timer(i, ROUTE_NEW);    table[i].flags &= ~FLAG_NEW;    cancel_timer(i, ROUTE_DELETE);    set_timer(i, ROUTE_USED);    table[i].flags |= FLAG_USED;    dbg("dt", "DT: Here it is: %u-%u-%hhu.\n", table[i].info.nexthop, table[i].info.seqnum, table[i].info.hopcnt);    return SUCCESS;  }  command error_t DymoTable.update(const rt_info_t * route_info, dymo_msg_t msg_type){    int8_t i = get_route(route_info->address);    if(msg_type == DYMO_RERR){      if(i != -1){	if( (table[i].info.nexthop == route_info->nexthop) 	    && ((table[i].info.seqnum == 0)		|| (route_info->seqnum == 0)		|| (route_info->seqnum >= table[i].info.seqnum)) ){	  table[i].flags |= FLAG_BROKEN;	  dbg("dt", "DT: Route for %u evicted because of a RERR.\n", route_info->address);	  signal RoutingTable.evicted(&table[i].info, REASON_UNREACHABLE);	  return SUCCESS;	} else {	  return EINVAL;	}      } else {	return EINVAL;      }    } else {      if(i == -1){		if(num_entries < maxsize){ //We have room to add a new route	  	  replace_info(num_entries, route_info);	  num_entries++;	  size++;	  dbg("dt", "DT: Updated route for %u in entry %hhu.\n", route_info->address, num_entries-1); //TODO debug below too	  return SUCCESS;	} else { //We have to find a route to replace	  //TODO possible optimization : caching the last deleted and broken route	  int8_t j = -1; //will be set to a non-new route if found	  	  //We look for a deleted route	  for(i=0; i<num_entries; i++){	    if(table[i].flags & FLAG_DELETED){	      replace_info(i, route_info);	      return SUCCESS;	    }	  }	  //the table is full, we try to replace an existing route	  for(i=0; i<num_entries; i++){	    if(table[i].flags & FLAG_BROKEN){	      replace_info(i, route_info);	      return SUCCESS;	    } else if( !(table[i].flags & FLAG_NEW) ){	      j = i;	    }	  }	  //no broken route found, we a take a non-new route	  //TODO rather take a non-used route	  if(j != -1){	    delete_route(j, REASON_FULL);	    replace_info(j, route_info);	    return SUCCESS;	  }	  /* No room found. We delete a random route */	  delete_route(replace, REASON_FULL);	  replace_info(replace++, route_info);	  if (replace == maxsize)	    replace = 0;	  return SUCCESS;	}      } else { //if(i == -1)	if(is_superior(route_info, table + i, msg_type)){	  replace_info(i, route_info);	  return SUCCESS;	} else {	  return EINVAL;	}      }    }  }  command bool DymoTable.isSuperior(const rt_info_t * info, dymo_msg_t t){    int8_t i = get_route(info->address);    return ((i == -1) || is_superior(info, table + i, t));  }  event void Timer.fired[uint8_t timer_id](){    uint8_t e = timer_id / NB_ROUTE_TIMERS;    switch(timer_id % NB_ROUTE_TIMERS){    case ROUTE_AGE_MIN:      table[e].flags &= ~FLAG_NEW;      break;    case ROUTE_AGE_MAX:      dbg("dt", "DT: Route for %u is really old, I delete it.\n", table[e].info.address);      delete_route(e, REASON_OLD);      break;    case ROUTE_NEW:      table[e].flags &= ~FLAG_NEW;      set_timer(e, ROUTE_DELETE);      break;    case ROUTE_USED:      table[e].flags &= ~FLAG_USED;      set_timer(e, ROUTE_DELETE);      break;    case ROUTE_DELETE:      dbg("dt", "DT: Route for %u is unused, I delete it.\n", table[e].info.address);      delete_route(e, REASON_OLD);      break;    }  }  event void LinkMonitor.brokenLink(addr_t neighbor){    int8_t i = get_route(neighbor);    if (i != -1) {      table[i].flags |= FLAG_BROKEN;      signal RoutingTable.evicted(&table[i].info, REASON_UNREACHABLE);      if (table[i].flags & (FLAG_NEW | FLAG_USED)) {	cancel_timer(i, ROUTE_NEW);	cancel_timer(i, ROUTE_USED);	set_timer(i, ROUTE_DELETE);      }    }  }  void replace_info(uint8_t pos, const rt_info_t * route_info){    table[pos].info = *route_info;    table[pos].flags = FLAG_NEW;    cancel_timers(pos);    set_timer(pos, ROUTE_AGE_MIN);    set_timer(pos, ROUTE_AGE_MAX);    set_timer(pos, ROUTE_NEW);  }  /* Return the index of the route toward address if it exists, -1 otherwise */  int8_t get_route(addr_t address){    uint8_t i = 0;    for(i=0;i<num_entries;i++){      if(table[i].info.address == address){	return i;      }    }    return -1;  }  /* Remove a route from the table */  void delete_route(uint8_t entry_id, reason_t r){    table[entry_id].flags = FLAG_DELETED;    cancel_timers(entry_id);    dbg("dt", "DT: I'm deleting route number %hhu (for node %u).\n", entry_id, table[entry_id].info.address);    signal RoutingTable.evicted(&table[entry_id].info, r);  }  /* compare two pieces of routing information   * returns true if info1 > entry->info */  bool is_superior(const rt_info_t * info1, const rt_entry_t * entry, dymo_msg_t msg_type){    //a copy of the superior test in the specifications    //with nil values discarded    return ((info1->seqnum > entry->info.seqnum)	    || ((info1->seqnum == entry->info.seqnum)		&& info1->has_hopcnt		&& entry->info.has_hopcnt		&& ((info1->hopcnt < entry->info.has_hopcnt)		    || ((info1->hopcnt == entry->info.has_hopcnt)			&& ((msg_type == DYMO_RREP)			    || (entry->flags & FLAG_BROKEN))))));  }  /* Start a timer for a route */  void set_timer(uint8_t entry_id, rt_timer_t timer_id){    call Timer.startOneShot[entry_id * NB_ROUTE_TIMERS + timer_id](timer_values[timer_id]);  }  /* Cancel a timer for a route */  void cancel_timer(uint8_t entry_id, rt_timer_t timer_id){    call Timer.stop[entry_id * NB_ROUTE_TIMERS + timer_id]();  }  /* Cancel all the timers of an entry */  void cancel_timers(uint8_t entry_id){    uint8_t i = entry_id * NB_ROUTE_TIMERS;    for(i=0; i<NB_ROUTE_TIMERS; i++){      call Timer.stop[i]();    }  }#ifdef DYMO_MONITORING  command uint8_t RoutingTableInfo.size(){    return size;  }  command uint8_t RoutingTableInfo.maxSize(){    return maxsize;  }  command uint8_t  RoutingTableInfo.getTableContent(rt_info_t * buf){    uint8_t i=0, j=0;    for(i=0; i<num_entries; i++){      if( !(table[i].flags & (FLAG_DELETED | FLAG_BROKEN)) ){	buf[j++] = table[i].info;      }    }    return j;  }  command uint8_t RoutingTableInfo.getLinks(rt_link_t * buf){    uint8_t i=0, j=0;    for(i=0; i<num_entries; i++){      if( !(table[i].flags & (FLAG_DELETED | FLAG_BROKEN)) ){	buf[j].target = table[i].info.address;	buf[j].nexthop = table[i].info.nexthop;	j++;      }    }    return j;  }#endif default event void RoutingTable.evicted(const rt_info_t * route_info, reason_t r){ }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -