*** stock_iot-lab_M3/openwsn/03b-IPv6/icmpv6rpl.c Thu Apr 24 11:01:36 2014 --- riot-openwsn-wip/openwsn/03b-IPv6/icmpv6rpl.c Thu Apr 24 16:55:54 2014 *************** *** 11,56 **** #include "opentimers.h" #include "IEEE802154E.h" ! //=========================== variables ======================================= ! typedef struct { ! // admin ! bool busySending; ///< currently sending DIO/DAO. ! uint8_t DODAGIDFlagSet; ///< is DODAGID set already? ! // DIO-related ! icmpv6rpl_dio_ht dio; ///< pre-populated DIO packet. ! open_addr_t dioDestination; ///< IPv6 destination address for DIOs. ! uint16_t periodDIO; ///< duration, in ms, of a timerIdDIO timeout. ! opentimer_id_t timerIdDIO; ///< ID of the timer used to send DIOs. ! uint8_t delayDIO; ///< number of timerIdDIO events before actually sending a DIO. ! // DAO-related ! icmpv6rpl_dao_ht dao; ///< pre-populated DAO packet. ! icmpv6rpl_dao_transit_ht dao_transit; ///< pre-populated DAO "Transit Info" option header. ! icmpv6rpl_dao_target_ht dao_target; ///< pre-populated DAO "Transit Info" option header. ! opentimer_id_t timerIdDAO; ///< ID of the timer used to send DAOs. ! uint16_t periodDAO; ///< duration, in ms, of a timerIdDAO timeout. ! uint8_t delayDAO; ///< number of timerIdDIO events before actually sending a DAO. ! } icmpv6rpl_vars_t; icmpv6rpl_vars_t icmpv6rpl_vars; //=========================== prototypes ====================================== // DIO-related ! void icmpv6rpl_timer_DIO_cb(); ! void icmpv6rpl_timer_DIO_task(); ! void sendDIO(); // DAO-related ! void icmpv6rpl_timer_DAO_cb(); ! void icmpv6rpl_timer_DAO_task(); ! void sendDAO(); //=========================== public ========================================== /** \brief Initialize this module. */ ! void icmpv6rpl_init() { //===== reset local variables memset(&icmpv6rpl_vars,0,sizeof(icmpv6rpl_vars_t)); --- 11,41 ---- #include "opentimers.h" #include "IEEE802154E.h" ! #include "thread.h" ! //=========================== variables ======================================= icmpv6rpl_vars_t icmpv6rpl_vars; + //static char openwsn_icmpv6rpl_DAO_stack[KERNEL_CONF_STACKSIZE_MAIN]; + //static char openwsn_icmpv6rpl_DIO_stack[KERNEL_CONF_STACKSIZE_MAIN]; //=========================== prototypes ====================================== // DIO-related ! void icmpv6rpl_timer_DIO_cb(void); ! void icmpv6rpl_timer_DIO_task(void); ! void sendDIO(void); // DAO-related ! void icmpv6rpl_timer_DAO_cb(void); ! void icmpv6rpl_timer_DAO_task(void); ! void sendDAO(void); //=========================== public ========================================== /** \brief Initialize this module. */ ! void icmpv6rpl_init(void) { //===== reset local variables memset(&icmpv6rpl_vars,0,sizeof(icmpv6rpl_vars_t)); *************** *** 101,107 **** D_DAO | K_DAO; icmpv6rpl_vars.dao.reserved = 0x00; ! icmpv6rpl_vars.dao.DAOSequance = 0x00; // DODAGID: to be populated upon receiving DIO icmpv6rpl_vars.dao_transit.type = OPTION_TRANSIT_INFORMATION_TYPE; --- 86,92 ---- D_DAO | K_DAO; icmpv6rpl_vars.dao.reserved = 0x00; ! icmpv6rpl_vars.dao.DAOSequence = 0x00; // DODAGID: to be populated upon receiving DIO icmpv6rpl_vars.dao_transit.type = OPTION_TRANSIT_INFORMATION_TYPE; *************** *** 133,145 **** } /** \brief Called when DIO/DAO was sent. \param[in] msg Pointer to the message just sent. \param[in] error Outcome of the sending. */ ! void icmpv6rpl_sendDone(OpenQueueEntry_t* msg, error_t error) { // take ownership over that packet msg->owner = COMPONENT_ICMPv6RPL; --- 118,134 ---- } + uint8_t icmpv6rpl_getRPLIntanceID(void){ + return icmpv6rpl_vars.dao.rplinstanceId; + } + /** \brief Called when DIO/DAO was sent. \param[in] msg Pointer to the message just sent. \param[in] error Outcome of the sending. */ ! void icmpv6rpl_sendDone(OpenQueueEntry_t* msg, owerror_t error) { // take ownership over that packet msg->owner = COMPONENT_ICMPv6RPL; *************** *** 244,251 **** \note This function is executed in interrupt context, and should only push a task. */ ! void icmpv6rpl_timer_DIO_cb() { scheduler_push_task(icmpv6rpl_timer_DIO_task,TASKPRIO_RPL); } /** --- 233,243 ---- \note This function is executed in interrupt context, and should only push a task. */ ! void icmpv6rpl_timer_DIO_cb(void) { scheduler_push_task(icmpv6rpl_timer_DIO_task,TASKPRIO_RPL); + /*thread_create(openwsn_icmpv6rpl_DIO_stack, KERNEL_CONF_STACKSIZE_MAIN, + PRIORITY_OPENWSN_ICMPV6RPL, CREATE_STACKTEST, + icmpv6rpl_timer_DIO_task, "icmpv6rpl_timer_DIO_task");*/ } /** *************** *** 253,259 **** \note This function is executed in task context, called by the scheduler. */ ! void icmpv6rpl_timer_DIO_task() { // update the delayDIO icmpv6rpl_vars.delayDIO = (icmpv6rpl_vars.delayDIO+1)%5; --- 245,251 ---- \note This function is executed in task context, called by the scheduler. */ ! void icmpv6rpl_timer_DIO_task(void) { // update the delayDIO icmpv6rpl_vars.delayDIO = (icmpv6rpl_vars.delayDIO+1)%5; *************** *** 279,285 **** /** \brief Prepare and a send a RPL DIO. */ ! void sendDIO() { OpenQueueEntry_t* msg; // stop if I'm not sync'ed --- 271,277 ---- /** \brief Prepare and a send a RPL DIO. */ ! void sendDIO(void) { OpenQueueEntry_t* msg; // stop if I'm not sync'ed *************** *** 370,377 **** \note This function is executed in interrupt context, and should only push a task. */ ! void icmpv6rpl_timer_DAO_cb() { ! scheduler_push_task(icmpv6rpl_timer_DAO_task,TASKPRIO_RPL); } /** --- 362,372 ---- \note This function is executed in interrupt context, and should only push a task. */ ! void icmpv6rpl_timer_DAO_cb(void) { ! scheduler_push_task(icmpv6rpl_timer_DAO_task,TASKPRIO_RPL); ! /*thread_create(openwsn_icmpv6rpl_DAO_stack, KERNEL_CONF_STACKSIZE_MAIN, ! PRIORITY_OPENWSN_ICMPV6RPL, CREATE_STACKTEST, ! icmpv6rpl_timer_DAO_task, "icmpv6rpl_timer_DAO_task");*/ } /** *************** *** 379,385 **** \note This function is executed in task context, called by the scheduler. */ ! void icmpv6rpl_timer_DAO_task() { // update the delayDAO icmpv6rpl_vars.delayDAO = (icmpv6rpl_vars.delayDAO+1)%5; --- 374,380 ---- \note This function is executed in task context, called by the scheduler. */ ! void icmpv6rpl_timer_DAO_task(void) { // update the delayDAO icmpv6rpl_vars.delayDAO = (icmpv6rpl_vars.delayDAO+1)%5; *************** *** 405,415 **** /** \brief Prepare and a send a RPL DAO. */ ! void sendDAO() { OpenQueueEntry_t* msg; // pointer to DAO messages uint8_t nbrIdx; // running neighbor index uint8_t numTransitParents,numTargetParents; // the number of parents indicated in transit option open_addr_t address; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed --- 400,411 ---- /** \brief Prepare and a send a RPL DAO. */ ! void sendDAO(void) { OpenQueueEntry_t* msg; // pointer to DAO messages uint8_t nbrIdx; // running neighbor index uint8_t numTransitParents,numTargetParents; // the number of parents indicated in transit option open_addr_t address; + open_addr_t* prefix; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed *************** *** 464,499 **** //===== fill in packet ! //=== transit option -- from RFC 6550, page 55 - 1 transit information header per parent is required. ! numTransitParents = 0; ! for (nbrIdx=0;nbrIdxpayload)), ! &(icmpv6rpl_vars.dao_transit), ! sizeof(icmpv6rpl_dao_transit_ht) ! ); ! ! // remember I found it ! numTransitParents++; ! } ! } //target information is required. RFC 6550 page 55. /* --- 460,490 ---- //===== fill in packet ! //NOTE: limit to preferrred parent only the number of DAO transit addresses to send ! ! //=== transit option -- from RFC 6550, page 55 - 1 transit information header per parent is required. ! //getting only preferred parent as transit ! numTransitParents=0; ! neighbors_getPreferredParentEui64(&address); ! packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); ! prefix=idmanager_getMyID(ADDR_PREFIX); ! packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); ! // update transit info fields ! // from rfc6550 p.55 -- Variable, depending on whether or not the DODAG ParentAddress subfield is present. ! // poipoi xv: it is not very clear if this includes all fields in the header. or as target info 2 bytes are removed. ! // using the same pattern as in target information. ! icmpv6rpl_vars.dao_transit.optionLength = LENGTH_ADDR128b + sizeof(icmpv6rpl_dao_transit_ht)-2; ! icmpv6rpl_vars.dao_transit.PathControl=0; //todo. this is to set the preference of this parent. ! icmpv6rpl_vars.dao_transit.type=OPTION_TRANSIT_INFORMATION_TYPE; ! // write transit info in packet ! packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_transit_ht)); ! memcpy( ! ((icmpv6rpl_dao_transit_ht*)(msg->payload)), ! &(icmpv6rpl_vars.dao_transit), ! sizeof(icmpv6rpl_dao_transit_ht) ! ); ! numTransitParents++; //target information is required. RFC 6550 page 55. /* *************** *** 506,519 **** // this neighbor is of higher DAGrank as I am. so it is my child // write it's address in DAO RFC6550 page 80 check point 1. ! neighbors_getNeighbor(&address,ADDR_64B,nbrIdx); ! packetfunctions_writeAddress(msg,&address,BIG_ENDIAN); // update target info fields ! icmpv6rpl_vars.dao_target.optionLength = LENGTH_ADDR64b + sizeof(icmpv6rpl_dao_target_ht); icmpv6rpl_vars.dao_target.type = OPTION_TARGET_INFORMATION_TYPE; icmpv6rpl_vars.dao_target.flags = 0; //must be 0 ! icmpv6rpl_vars.dao_target.prefixLength = 0; //no prefix. // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_target_ht)); --- 497,514 ---- // this neighbor is of higher DAGrank as I am. so it is my child // write it's address in DAO RFC6550 page 80 check point 1. ! neighbors_getNeighbor(&address,ADDR_64B,nbrIdx); ! packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); ! prefix=idmanager_getMyID(ADDR_PREFIX); ! packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); // update target info fields ! // from rfc6550 p.55 -- Variable, length of the option in octets excluding the Type and Length fields. ! // poipoi xv: assuming that type and length fields refer to the 2 first bytes of the header ! icmpv6rpl_vars.dao_target.optionLength = LENGTH_ADDR128b +sizeof(icmpv6rpl_dao_target_ht) - 2; //no header type and length icmpv6rpl_vars.dao_target.type = OPTION_TARGET_INFORMATION_TYPE; icmpv6rpl_vars.dao_target.flags = 0; //must be 0 ! icmpv6rpl_vars.dao_target.prefixLength = 128; //128 leading bits -- full address. // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_target_ht)); *************** *** 526,531 **** --- 521,530 ---- // remember I found it numTargetParents++; } + //limit to MAX_TARGET_PARENTS the number of DAO target addresses to send + //section 8.2.1 pag 67 RFC6550 -- using a subset + // poipoi TODO base selection on ETX rather than first X. + if (numTargetParents>=MAX_TARGET_PARENTS) break; }