From 436dfa9aaa2e990b4626554d12cf440c2bd582fe Mon Sep 17 00:00:00 2001 From: "md.jamal" Date: Wed, 20 Aug 2014 12:48:17 +0530 Subject: [PATCH 1/2] Neighbor Discovery Implementation according to RFC 6775 Added Neighbor Discovery support to tinyos blip stack where a node can act in any of the three roles:host,router and LBR.There is no need of wiring to IPStackC for starting the radio,just we can use the splitcontrol interface provided by the NeighborDiscovery Component NDC,which will start the radio performs all the Neighbor Discovery message transactions.Once an IP is assigned to him by the router signals the splitcontrol.startDone. Now the node can use the global ip assigned by the router --- tools/tinyos/c/blip/lib6lowpan/ip.h | 3 +- tos/interfaces/Node.nc | 43 + tos/lib/net/blip/IPAddressP.nc | 14 + tos/lib/net/blip/IPForwardingEngineP.nc | 33 + tos/lib/net/blip/IPNeighborDiscoveryC.nc | 3 + tos/lib/net/blip/IPNeighborDiscoveryP.nc | 18 +- tos/lib/net/blip/IPStackC.nc | 5 + tos/lib/net/blip/MinuteConfigurationC.nc | 18 + tos/lib/net/blip/MinuteTimerC.nc | 14 + tos/lib/net/blip/MinuteTimerP.nc | 69 + tos/lib/net/blip/ND.h | 366 +++++ tos/lib/net/blip/NDC.nc | 81 ++ tos/lib/net/blip/NDP.nc | 1420 +++++++++++++++++++ tos/lib/net/blip/Neighbr.h | 96 ++ tos/lib/net/blip/NeighbrCacheC.nc | 36 + tos/lib/net/blip/NeighbrCacheP.nc | 981 +++++++++++++ tos/lib/net/blip/OptionC.nc | 60 + tos/lib/net/blip/interfaces/IPAddress.nc | 4 + tos/lib/net/blip/interfaces/MinuteTimer.nc | 12 + tos/lib/net/blip/interfaces/NeighbrCache.nc | 73 + tos/lib/net/blip/interfaces/Option.nc | 14 + tos/lib/net/blip/interfaces/RouterList.nc | 18 + tos/system/NodeC.nc | 17 + tos/system/NodeP.nc | 60 + 24 files changed, 3455 insertions(+), 3 deletions(-) create mode 100755 tos/interfaces/Node.nc create mode 100644 tos/lib/net/blip/MinuteConfigurationC.nc create mode 100644 tos/lib/net/blip/MinuteTimerC.nc create mode 100644 tos/lib/net/blip/MinuteTimerP.nc create mode 100644 tos/lib/net/blip/ND.h create mode 100644 tos/lib/net/blip/NDC.nc create mode 100644 tos/lib/net/blip/NDP.nc create mode 100644 tos/lib/net/blip/Neighbr.h create mode 100644 tos/lib/net/blip/NeighbrCacheC.nc create mode 100644 tos/lib/net/blip/NeighbrCacheP.nc create mode 100644 tos/lib/net/blip/OptionC.nc create mode 100644 tos/lib/net/blip/interfaces/MinuteTimer.nc create mode 100644 tos/lib/net/blip/interfaces/NeighbrCache.nc create mode 100644 tos/lib/net/blip/interfaces/Option.nc create mode 100644 tos/lib/net/blip/interfaces/RouterList.nc create mode 100755 tos/system/NodeC.nc create mode 100755 tos/system/NodeP.nc diff --git a/tools/tinyos/c/blip/lib6lowpan/ip.h b/tools/tinyos/c/blip/lib6lowpan/ip.h index 53b7a966b8..2c9cade308 100644 --- a/tools/tinyos/c/blip/lib6lowpan/ip.h +++ b/tools/tinyos/c/blip/lib6lowpan/ip.h @@ -168,9 +168,10 @@ enum { ICMP_TYPE_ROUTER_ADV = 134, ICMP_TYPE_NEIGHBOR_SOL = 135, ICMP_TYPE_NEIGHBOR_ADV = 136, + ICMP_TYPE_DUPLICATE_REQ = 157, + ICMP_TYPE_DUPLICATE_CONFIRM = 158, ICMP_TYPE_RPL_CONTROL = 155, ICMP_NEIGHBOR_HOPLIMIT = 255, - ICMP_CODE_HOPLIMIT_EXCEEDED = 0, ICMP_CODE_ASSEMBLY_EXCEEDED = 1, }; diff --git a/tos/interfaces/Node.nc b/tos/interfaces/Node.nc new file mode 100755 index 0000000000..06b6498b81 --- /dev/null +++ b/tos/interfaces/Node.nc @@ -0,0 +1,43 @@ +/* +@author Md.Jamal +@version $Revision: 1.0 + +*/ + +interface Node { + + + /* It is used to set the node acts as Host*/ + + command void setHost(); + + + /*It is used to check whether the node is host or not + Returns FALSE if it is not a host + Returns TRUE if it is a host*/ + + command bool getHostState(); + + + /* It is used to unset the Node from Host */ + command void unsetHost(); + + /* It is used to set the node to act as Router*/ + command void setRouter(); + + /* It is used to check whether the node is router or not + Returns FALSE when it is not a Router + Returns TRUE when it is Router */ + command bool getRouterState(); + + /* It is used to set the node to act as 6LoWPAN Border Router*/ + command void setLBR(); + + + /* It is used to check whether the node is EdgeRouter or Not + Returns FALSE when it is not a EdgeRouter + Returns TRUE when it is a EdgeRouter*/ + + command bool getLBRState(); + +} diff --git a/tos/lib/net/blip/IPAddressP.nc b/tos/lib/net/blip/IPAddressP.nc index ceb3bd19d3..101a1893ce 100644 --- a/tos/lib/net/blip/IPAddressP.nc +++ b/tos/lib/net/blip/IPAddressP.nc @@ -178,3 +178,17 @@ module IPAddressP { event void Ieee154Address.changed() {} } + +command bool IPAddress.getEUILLAddress(struct in6_addr *addr) +{ + int i; + ieee154_laddr_t laddr = call Ieee154Address.getExtAddr();//getting the Extended Address + + memclr(addr->s6_addr, 16); //clearing the address passed + addr->s6_addr16[0] = htons(0xfe80); // setting the prefix as fe80 + //copying the EUI-64 into interface identifier + for (i = 0; i < 8; i++) + addr->s6_addr[8+i] = laddr.data[7-i]; + addr->s6_addr[8] ^= 0x2; /* toggle U/L bit */ + return TRUE; +} diff --git a/tos/lib/net/blip/IPForwardingEngineP.nc b/tos/lib/net/blip/IPForwardingEngineP.nc index 851f53ffb5..5b61217f47 100644 --- a/tos/lib/net/blip/IPForwardingEngineP.nc +++ b/tos/lib/net/blip/IPForwardingEngineP.nc @@ -29,6 +29,8 @@ module IPForwardingEngineP { interface IPAddress; interface IPPacket; interface Pool; + interface RouterList; + interface NeighbrCache; #ifdef PRINTFUART_ENABLED interface Timer as PrintTimer; @@ -193,6 +195,7 @@ module IPForwardingEngineP { } command error_t IP.send(struct ip6_packet *pkt) { + struct in6_addr next; struct route_entry *next_hop_entry = call ForwardingTable.lookupRoute(pkt->ip6_hdr.ip6_dst.s6_addr, 128); @@ -240,6 +243,25 @@ module IPForwardingEngineP { return do_send(next_hop_entry->ifindex, &next_hop_entry->next_hop, pkt); } + //check whether any entry exists in the Neighbor Cache + if(call NeighbrCache.findEntry(pkt->ip6_hdr.ip6_dst)){ + //printf("found from neighbor cache"); + return call IPForward.send[ROUTE_IFACE_154](&pkt->ip6_hdr.ip6_dst, pkt, NULL); + } + + #ifdef NODE_ROUTER //if u r a router and if u dont have any information about the destination send it to the LBR + call NeighbrCache.getLBRAddress(&next); + return do_send(ROUTE_IFACE_154,&next,pkt); + #endif + #ifdef NODE_HOST //if u r a host and if u dont have any information about the destination send it to the router + //RFC 6775(Section 5.6) Send to the Default Router IP and send it to the Default Router as the destination is OFF-Link + if(call RouterList.getRouterIP(&next)!=-1) + { + //printf("\n Using Router to send the packet for:"); + //printf_in6addr(&pkt->ip6_hdr.ip6_dst); + return do_send(ROUTE_IFACE_154,&next,pkt); //just convert it into linklocal address here + } + #endif printf("Forwarding -- no route found for packet. FAIL.\n"); printf("Forwarding -- dest addr: "); printf_in6addr(&pkt->ip6_hdr.ip6_dst); @@ -296,6 +318,12 @@ module IPForwardingEngineP { /* oops, no route. */ /* RPL will reencapsulate the packet in some cases here */ // call ForwardingEvents.drop(iph, payload, len, ROUTE_DROP_NOROUTE); + if(call NeighbrCache.findEntry(iph->ip6_dst)) + { + //printf("\n Got entry from destination cache"); + do_send(ROUTE_IFACE_154, &iph->ip6_dst,&pkt); + return; + } return; } next_hop = &next_hop_entry->next_hop; @@ -383,5 +411,10 @@ module IPForwardingEngineP { default event void ForwardingTableEvents.defaultRouteAdded() {} default event void ForwardingTableEvents.defaultRouteRemoved() {} + event void NeighbrCache.default_rtrlistempty(){} + + event void NeighbrCache.NUD_reminder(struct in6_addr ip_address){} + + event void NeighbrCache.prefixReg(){} event void IPAddress.changed(bool global_valid) {} } diff --git a/tos/lib/net/blip/IPNeighborDiscoveryC.nc b/tos/lib/net/blip/IPNeighborDiscoveryC.nc index 32bc215eb2..cd2370aef9 100644 --- a/tos/lib/net/blip/IPNeighborDiscoveryC.nc +++ b/tos/lib/net/blip/IPNeighborDiscoveryC.nc @@ -26,6 +26,9 @@ configuration IPNeighborDiscoveryC { IPForward = IPNeighborDiscoveryP.IPForward; StdControl = IPNeighborDiscoveryP.StdControl; + components NeighbrCacheC; + IPNeighborDiscoveryP.NeighbrCache -> NeighbrCacheC; + IPNeighborDiscoveryP.IP_RS -> ICMP_RS.IP[ICMPV6_CODE_RS]; IPNeighborDiscoveryP.IP_RA -> ICMP_RA.IP[ICMPV6_CODE_RA]; IPNeighborDiscoveryP.RSTimer -> RSTimer.Timer; diff --git a/tos/lib/net/blip/IPNeighborDiscoveryP.nc b/tos/lib/net/blip/IPNeighborDiscoveryP.nc index 05f55d6573..c172aaef0e 100644 --- a/tos/lib/net/blip/IPNeighborDiscoveryP.nc +++ b/tos/lib/net/blip/IPNeighborDiscoveryP.nc @@ -41,6 +41,7 @@ module IPNeighborDiscoveryP { interface IPLower; interface IPAddress; interface Ieee154Address; + interface NeighbrCache; #if BLIP_ADDR_AUTOCONF interface SetIPAddress; @@ -511,13 +512,20 @@ module IPNeighborDiscoveryP { if (call NeighborDiscovery.resolveAddress(&local_addr, &fr_addr.ieee_src) != SUCCESS) { - printf("IPND - local address resolution failed\n"); + //this is if ip exist in the neighbor cache not in routing table + if(call NeighbrCache.resolveIP(&local_addr,&fr_addr.ieee_src)!=SUCCESS) { + // printf("IPND - local address resolution failed\n"); + return FAIL; + } return FAIL; } if (call NeighborDiscovery.resolveAddress(next, &fr_addr.ieee_dst) != SUCCESS) { - printf("IPND - next-hop address resolution failed\n"); + if(call NeighbrCache.resolveIP(next,&fr_addr.ieee_dst) != SUCCESS){ + // printf("IPND - next-hop address resolution failed"); + return FAIL; + } return FAIL; } printf("l2 source: "); printf_ieee154addr(&fr_addr.ieee_src); @@ -540,4 +548,10 @@ module IPNeighborDiscoveryP { event void Ieee154Address.changed() {} event void IPAddress.changed(bool global_valid) {} + + event void NeighbrCache.default_rtrlistempty(){} + + event void NeighbrCache.NUD_reminder(struct in6_addr ip_address){} + + event void NeighbrCache.prefixReg(){} } diff --git a/tos/lib/net/blip/IPStackC.nc b/tos/lib/net/blip/IPStackC.nc index 03c139b134..b95a3f6fcb 100644 --- a/tos/lib/net/blip/IPStackC.nc +++ b/tos/lib/net/blip/IPStackC.nc @@ -79,6 +79,11 @@ configuration IPStackC { FwdP.IPPacket -> IPPacketC.IPPacket; IPProtocolsP.IPPacket -> IPPacketC.IPPacket; IPStackControlP.IPAddress -> IPAddressC.IPAddress; + + components NeighbrCacheC; + FwdP.RouterList->NeighbrCacheC; + FwdP.NeighbrCache->NeighbrCacheC; + components new PoolC(struct in6_iid, N_CONCURRENT_SENDS) as FwdAddrPoolC; FwdP.Pool -> FwdAddrPoolC; diff --git a/tos/lib/net/blip/MinuteConfigurationC.nc b/tos/lib/net/blip/MinuteConfigurationC.nc new file mode 100644 index 0000000000..43a8f3b584 --- /dev/null +++ b/tos/lib/net/blip/MinuteConfigurationC.nc @@ -0,0 +1,18 @@ +configuration MinuteConfigurationC { +provides interface MinuteTimer[uint8_t id]; +} +implementation { + components MinuteTimerP; + + #if defined(PLATFORM_TELOSB) || defined(PLATFORM_IWISE) || defined(PLATFORM_SMOTE) + components new AlarmMilli32C() as Alarm, new AlarmToTimerC(TMilli) as AlarmToTimer; + #elif defined(PLATFORM_MICAZ) || defined(PLATFORM_IRIS) + components AlarmCounterMilliP as Alarm, new AlarmToTimerC(TMilli) as AlarmToTimer; + #endif + components new VirtualizeTimerC(TMilli,uniqueCount("Minute")); + MinuteTimer=MinuteTimerP; + MinuteTimerP.Timer->VirtualizeTimerC; + VirtualizeTimerC.TimerFrom -> AlarmToTimer; + AlarmToTimer.Alarm -> Alarm; + +} diff --git a/tos/lib/net/blip/MinuteTimerC.nc b/tos/lib/net/blip/MinuteTimerC.nc new file mode 100644 index 0000000000..d43a23c142 --- /dev/null +++ b/tos/lib/net/blip/MinuteTimerC.nc @@ -0,0 +1,14 @@ + +#include "Timer.h" +generic configuration MinuteTimerC() +{ + provides interface MinuteTimer[uint8_t id]; + +} + +implementation +{ + + components MinuteConfigurationC; + MinuteTimer=MinuteConfigurationC; +} diff --git a/tos/lib/net/blip/MinuteTimerP.nc b/tos/lib/net/blip/MinuteTimerP.nc new file mode 100644 index 0000000000..e0e1c58458 --- /dev/null +++ b/tos/lib/net/blip/MinuteTimerP.nc @@ -0,0 +1,69 @@ + +module MinuteTimerP +{ + provides interface MinuteTimer[uint8_t id]; + uses interface Timer as Timer[uint8_t num]; + uses interface Leds; +} + +implementation +{ + + enum + { + RUNNING=1, + STARTING=2, + FIRED=3, + COMPLETED=4, + + + }; + + uint8_t STATE[uniqueCount("Minute")]; + uint16_t period[uniqueCount("Minute")]; + uint16_t count[uniqueCount("Minute")]; + + + event void Timer.fired[uint8_t num]() + { + + count[num]++; + if(STATE[num]==FIRED) + { + if(count[num]==2*period[num]) + { + STATE[num]=COMPLETED; + + } + else + { + call Timer.startOneShot[num](30720U); //30seconds=30*1024 + } + } + + if(STATE[num]==COMPLETED) + { + + signal MinuteTimer.fired[num](); + call Timer.stop[num](); + count[num]=0; + + } + + + } + + command error_t MinuteTimer.startOneShot[uint8_t id](uint16_t minutes) + { + period[id]=minutes; + call Timer.startOneShot[id](30720U); //30seconds=30*1024 + STATE[id]=FIRED; + return SUCCESS; + + } + + default event void MinuteTimer.fired[uint8_t id](){ + } + + +} diff --git a/tos/lib/net/blip/ND.h b/tos/lib/net/blip/ND.h new file mode 100644 index 0000000000..009b814e7d --- /dev/null +++ b/tos/lib/net/blip/ND.h @@ -0,0 +1,366 @@ +/*Header file for Neighbour Discovery + +@author Md.Jamal +@version $Revision: 1.0 + +*/ +#ifndef ND_H +#define ND_H + +#include + + + +#define ICMPV6_ND_CODE 0 +#define LOWPAN_CONTEXT_MAX 16 + +/* ICMP types of these messages are present in ip.h */ + +/* ICMPv6 Header */ + +struct icmpv6_header { + uint8_t type; //type field indicates the type of the message + uint8_t code; //code field depends on the message type to create additional level of granularity + nx_uint16_t checksum; //used to detect data corruption in the ICMPv6 message +}__attribute__((packed)); + + +/* Neighbour Discovery Messages */ + + +/* Neighbour Solicitation Message Format + A node send Neighbour Solicitation to request the link-layer address of a target node while also providing their own link-layer address to the target + Possible Options:SLLA(Source Link Layer Address) which contains the link-layer address for the sender +*/ +typedef struct { + struct icmpv6_header icmpv6; + uint32_t reserved; //field unused and must be initialized to zero by the sender + struct in6_addr target; //IP address of the target of the solicitation +}__attribute__((packed)) neighbr_solicit; + + + +/* Neighbour Advertisement Message Format + A node sends Neighbour Advertisement in response to Neighbour Solicitation in order to propogate new information quickly +Possible Options:TLLA(Target Link Layer Address) which contains the link layer address of sender of advt +*/ + +typedef struct { + struct icmpv6_header icmpv6; + uint8_t r_bit:1; //if set indicates that the sender is a router + uint8_t s_bit:1; //if set indicates that the advt was sent in response to a solicitation + uint8_t o_bit:1; //if set advt should override an existing cache entry and update it + uint8_t reserved:5; //field unused and should be set to zero by sender + uint8_t reserved1; + uint16_t reserved2; + struct in6_addr target; //IPv6 address of the node that prompted this advt +}__attribute__((packed)) neighbr_advt; + + +/* Router Solicitation Message Format + Hosts send Router solicitations in order to prompt routers to generate Router Advertisements quickly + Possible Options: SLLA(Source Link Layer Address) which contains the link layer address of the sender +*/ + + +typedef struct { + struct icmpv6_header icmpv6; + uint32_t reserved; //field unused and should be set to zero by sender +}__attribute__((packed)) router_solicit; + + +/* Router Advertisement Message Format + Routers send out Router Advertisement messages periodically or in response of an Router solicit + Possible Options: SLLA,MTU,Prefix Information +*/ + +typedef struct { + struct icmpv6_header icmpv6; + uint8_t cur_hop_limit; //default value that should be placed in the Hop Count field of IP header + uint8_t m_bit:1; //if set indicates that the address are available via DHCPv6 and o flag is redundant + uint8_t o_bit:1; //if set indicates that other config info such as DNS info is available via DHCPv6 + uint8_t reserved:6; //must be initialized to zero by sender + uint16_t router_lifetime; //lifetime associated with the default router + uint32_t reachable_time; //time in sec a node will assume that node is reachable after reachable confirmation + uint32_t retrans_timer; //time in ms b/w retransmitted neighbour solicitation message +}__attribute__((packed)) router_advt; + + + +/* Duplicate Address Request and Duplicate Address Confirmation Message Format + + These are used for multihop DAD exchanges between a 6LR and 6LBR +*/ + +typedef struct { + struct icmpv6_header icmpv6; + uint8_t status; //indicates the status of a registration in the DAC + uint8_t reserved; //set to zero by sender + uint16_t reg_lifetime; //amount of time in units of 60 seconds that the 6LBR should keep the DAD table entry + ieee_eui64_t eui64; //Used to uniquely identify the interface of the Registered Address + struct in6_addr reg_addr; //carries the host address that was contained in the IPv6 Source field in the NS that contained the ARO sent by the host +} __attribute__((packed)) darc; + + +/* Neighbour Discovery options */ + +/* Source Target Link layer address option format +Description: SLLAO contains the link-layer address of the sender + + */ + +typedef struct { + uint8_t type; + uint8_t length; +}__attribute__((packed)) opt_hdr; + +typedef struct { + opt_hdr option_header; + ieee_eui64_t ll_addr; //link-layer address of the sender + uint8_t reserved[6]; //for padding(RFC 4944) + } __attribute__((packed)) stlla_opt; + + +/* Prefix Information Option +Description:Appears only in Router Advertisements.This option provides the on-link prefixes and prefixes for Address Autoconfiguration + +*/ + +typedef struct { + uint8_t prefix_length; //number of leading bits in the prefix that are valid.value ranges from 0 to 128 + uint8_t l_bit:1; //on-link flag when set indicates that this prefix can be used for on-link determination + uint8_t a_bit:1; //Autonomous Address Configuration Flag.When set indicates that prefix can be used for stateless address configuration + uint8_t reserved1:6; //set to zero by the sender + uint32_t valid_lifetime; //length of the time in seconds the prefix is valid for on-link prefix determination + uint32_t preferrd_lifetime; //length of the time in seconds that addresses generated from the prefix via stateless address autoconfiguration remain valid + uint32_t reserved2; //must be set to zero by the sender + struct in6_addr prefix; //An IP Address or a prefix of an IP Address.A router should not send a prefix option for link-local prefix and host should ignore such a prefix + +}__attribute__((packed)) prefix_info; + +typedef struct { + opt_hdr option_header; + prefix_info prefix_information; +}__attribute__((packed)) prefix_opt; + + +/* Address Registration Option Format +Description:ARO is used for registration of IP Address along with its link layer address at the router + +*/ + +typedef struct { + opt_hdr option_header; + uint8_t status; //Indicates the status of the registration in the NA response.Must be set to 0 in NS messages + uint8_t reserved1; + uint16_t reserved2; //should be set to zero by the sender + uint16_t reg_lifetime; //Amount of time in units of 60 seconds that the router should keep the NCE for sender of NS + ieee_eui64_t eui64; //Used to uniquely identify the interface of the Registered Address +}__attribute__((packed)) aro_opt; + +/* 6LoWPAN Context Option Format +Description:Carries Prefix Information for LOWPAN header compression and is similar to PIO +*/ + +typedef struct { + opt_hdr option_header; + uint8_t context_length; //no. of leading bits in the context prefix field that are valid.value ranges from 0 to 128 + uint8_t c_bit:1; //one-bit context compression which indicates whether the context is valid for compression + uint8_t cid:4; //used for context based header compression + uint8_t res:3; //set to zero by the sender + uint16_t reserved; //set to zero by the sender + uint16_t valid_lifetime; //length of time in units of 60 seconds that the context is valid for + struct in6_addr prefix; //IPv6 prefix or address corresponding to the CID field +}__attribute__((packed)) context_opt; + + + +/* Authoritative Border Routr Option Format +Description:Needed when RA messages are used to disseminate prefixes and context information across a route-over topology +*/ + +typedef struct { + uint16_t ver_low; + uint16_t ver_high; //ver_low and ver_high together constitute the version number field + uint16_t valid_lifetime; //length of time in units of 60 sec that the border router information is valid for + struct in6_addr lbr_addr; //IPv6 address of the 6LBR +}__attribute__((packed))abro_info; + +typedef struct { + opt_hdr option_header; + abro_info abro_information; +}__attribute__((packed)) abro_opt; + + +/* Type defined by IANA for the various options */ +enum option_types { + SLLAO=1, + TLLAO=2, + PREFIX_INFORMATION=3, + ARO=33, + CONTEXT_0PTION=34, + ABRO=35, +}; + + +/* Length of the Options Predefined */ +enum option_length { + LENGTH_ICMPHEADER=4, + LENGTH_RS=4, //Excluding ICMP header and options + LENGTH_RA=12, + LENGTH_NS=20, + LENGTH_NA=20, + LENGTH_SLLAO=2, //Including Options Header + LENGTH_TLLAO=2, + LENGTH_PREFIX=4, + LENGTH_ARO=2, + LENGTH_ABRO=3, + LENGTH_CONTEXT1=2, + LENGTH_CONTEXT2=3, + +}; + + +/*Reachability States*/ +/* The receipt of a solicited Neighbor Advertisement serves as reachability confirmation,since the advertisements with the solicited flag set to one are sent only in response to a Neighbor Solicitation */ +enum { +/* Section 5.5.3 of RFC 6775 says that the procedure for maintaining reachability information about a neighbor is same as in RFC 4861 Section 7.3,with the exception that the address resolution is not performed So there is no INCOMPLETE state*/ + + REACHABLE=2, //Confirmation is received within ReachableTime milliseconds + STALE=3, //More than Reachable Time milliseconds has been elapsed since the confirmation was received + DELAY=4, //When the packet is going to be sent it enters DELAY state and wait for DELAY_FIRST_PROBE_TIME seconds + PROBE=5, //after the timer expires it enters into PROBE state and retransmitting NS every RetransTimer ms until a reachability confirmation is received +}; + + +/* Different States for Sending Messages*/ + +enum { + + UNDEFINED=0, + HOST=1, + ROUTER=2, + MULTICAST=3, + UNICAST=4, + ROUTER_RESPONSE=5, + LBR_RESPONSE=6, + SEND_ARO=7, + NUD=8, + LBR=9, + NOTSENT=10, + SENT=11, +}; + + +/*Message Types*/ + +enum { + + RS=1, + RA=2, + NS=3, + NA=4, + + +}; + + + +/* Context Table (RFC 6775 Section 5.4.2) +Description: The host maintains a data structure called Context table to store the context information it receives from the routers +*/ + +typedef struct context_table_t { + uint8_t cid:4; //used for context based header compression + struct in6_addr prefix; //IPv6 prefix corresponding to the CID field + uint8_t c_bit:1; //bit indicates whether the context is valid or not + uint16_t valid_lifetime; //time in units of 60 seconds the context is valid for + +}__attribute__((packed)) context_table_t; + + + + +typedef struct abr_cache_t { + uint16_t valid_lifetime; + uint32_t version; + struct in6_addr abr_addr; + uint8_t cid[LOWPAN_CONTEXT_MAX] ; +}__attribute__((packed)) abr_cache; + + +/* Protocol Constants (RFC 6775 Section 9) */ + + +/* 6LR Constants */ + + +/* + +MAX_RTR_ADVERTISEMENTS:Number of Maximum Router Advertisements messages should be transmitted,each separated by the interval in the range MIN_DELAY_BETWEEN_RAS and MAX_RA_DELAY_TIME + +MaxRtrAdvInterval: The maximum time allowed between sending unsolicited multicast Router Advertisements from the interface + +MinRtrAdvInterval: The minimum time allowed between sending unsolicited multicast Router Advertisements from the interface + + +*/ + +#define MAX_RTR_ADVERTISEMENTS 3 +#define MIN_DELAY_BETWEEN_RAS 10000U //10 seconds +#define MAX_RA_DELAY_TIME 2000 //2 seconds +#define MULTIHOP_HOPLIMIT 64 +#define MaxRtrAdvInterval 600000 //600 seconds +#define MinRtrAdvInterval 0.33*MaxRtrAdvInterval +#define DELAY_FIRST_PROBE_TIME 60000U //60Seconds + +/* Host Constants */ +/* + +RTR_SOLICITATION_INTERVAL:The interval after which next Router Solicitation is sent + +MAX_RTR_SOLICITATIONS: Number of Router Solicitation messages host should transmit,each separated by RTR_SOLICITATION_INTERVAL in order to receive Router Advertisement. + +MAX_RTR_SOLICITATION_INTERVAL: It is the increase in the interval of retransmission timer after MAX_RTR_SOLICATIONS transmissions + +RETRANS_TIMER: The time between retransmissions of Neighbour Solicitation messages to a neighbour when resolving the address or when probing the reachability of a neighbor + + +MAX_UNICAST_SOLICIT: The number of solicitations after which we stop retransmitting Neighbour Solicitations and the entry should be deleted + +*/ + + + + +#define RTR_SOLICITATION_INTERVAL 10000U //10 seconds +#define MAX_RTR_SOLICITATIONS 3 +#define MAX_RTR_SOLICITATION_INTERVAL 60000U //60 seconds +#define RETRANS_TIMER 60000U //60000 milliseconds(60 seconds) +#define MAX_UNICAST_SOLICIT 3 +#define REACHABLE_TIME 600U //1 hour(3600000 milliseconds) +#define RTR_HOP_LIMIT 255 +#define RTR_LIFE_TIME 500 //500 Minutes +#define RTR_REACHABLE_TIME 2 //2minutes +#define PREFIX_PREF_LIFETIME 15 //400 Minutes +#define ABR_VER_LOW 1 +#define ABR_VER_HIGH 0 +#define ABR_LIFETIME 500 //500 Minutes +#define PREFIX_VALID_LIFETIME 0xffff +#define PREFIX_LENGTH 16 + + +//IP Packet Size is 44 Bytes+RS Message size is 8 bytes + SLLAO is 10 Bytes + ARO is 15 Bytes + RA Message size is 16 bytes+ NS Message Size is 24 bytes + NA Message Size is 24 bytes + DAR Message size is 32+ DAC Message Size is 32 + prefix option size is 30 bytes+ abro option is 24 bytes + +#define MSG_SIZE 52 +#define RA_MSG_SIZE 120 +#define NA_MSG_SIZE 52 +#define DAR_MSG_SIZE 32 +#define DAC_MSG_SIZE 32 + + + + + +#endif + diff --git a/tos/lib/net/blip/NDC.nc b/tos/lib/net/blip/NDC.nc new file mode 100644 index 0000000000..7da130de7f --- /dev/null +++ b/tos/lib/net/blip/NDC.nc @@ -0,0 +1,81 @@ +/* Configuration file of Neighbour Discovery + +@author Md.Jamal +@version $Revision: 1.0 + +*/ + +#include "ND.h" +configuration NDC { + + provides interface SplitControl; + + + + +} + + +implementation { + + components NDP; + SplitControl= NDP; + + components IPAddressC; + NDP.IPAddress->IPAddressC; + NDP.SetIPAddress -> IPAddressC; + + components LedsC as LedsC; + NDP.Leds->LedsC; + + components IPStackC; + NDP.RadioControl->IPStackC; + + components new ICMPCodeDispatchC(ICMP_TYPE_ROUTER_SOL) as ICMP_RS; + NDP.IP_RS -> ICMP_RS.IP[ICMPV6_ND_CODE]; + + components new ICMPCodeDispatchC(ICMP_TYPE_ROUTER_ADV) as ICMP_RA; + NDP.IP_RA -> ICMP_RA.IP[ICMPV6_ND_CODE]; + + components new ICMPCodeDispatchC(ICMP_TYPE_NEIGHBOR_SOL) as ICMP_NS; + NDP.IP_NS -> ICMP_NS.IP[ICMPV6_ND_CODE]; + + components new ICMPCodeDispatchC(ICMP_TYPE_NEIGHBOR_ADV) as ICMP_NA; + NDP.IP_NA -> ICMP_NA.IP[ICMPV6_ND_CODE]; + + components new ICMPCodeDispatchC(ICMP_TYPE_DUPLICATE_REQ) as ICMP_DAR; + NDP.IP_DAR -> ICMP_DAR.IP[ICMPV6_ND_CODE]; + + components new ICMPCodeDispatchC(ICMP_TYPE_DUPLICATE_CONFIRM) as ICMP_DAC; + NDP.IP_DAC -> ICMP_DAC.IP[ICMPV6_ND_CODE]; + + components new TimerMilliC() as RSTimer; + NDP.RSTimer->RSTimer; + + components new TimerMilliC() as NSTimer; + NDP.NSTimer->NSTimer; + + components NodeC; + NDP.Node->NodeC; + + + components Ieee154AddressC; + NDP.Ieee154Address->Ieee154AddressC; + + + + components new MinuteTimerC() as MT; + NDP.AROTimer->MT.MinuteTimer[unique("Minute")]; + + + components OptionC; + NDP.Option->OptionC; + + + components NeighbrCacheC; + NDP.NeighbrCache->NeighbrCacheC; + NDP.RouterList->NeighbrCacheC; + + components RandomC; + NDP.Random->RandomC; +} diff --git a/tos/lib/net/blip/NDP.nc b/tos/lib/net/blip/NDP.nc new file mode 100644 index 0000000000..3050a6ada3 --- /dev/null +++ b/tos/lib/net/blip/NDP.nc @@ -0,0 +1,1420 @@ +/*Implementation of Neighbour Discovery + +@author Md.Jamal +@version $Revision: 1.0 + +*/ + +#include +#include +#include +#include +#include +#include "Neighbr.h" + + +module NDP { + + provides interface SplitControl; + uses interface SplitControl as RadioControl; + uses interface IPAddress; + uses interface SetIPAddress; + uses interface Leds; + uses interface IP as IP_RS; //Router Solicitations + uses interface IP as IP_RA; + uses interface IP as IP_NS; + uses interface IP as IP_NA; + uses interface IP as IP_DAR; + uses interface IP as IP_DAC; + uses interface Timer as RSTimer; + uses interface Timer as NSTimer; + uses interface MinuteTimer as AROTimer; + uses interface Ieee154Address; + uses interface Option; + uses interface NeighbrCache; + uses interface Node; + uses interface Random; + uses interface RouterList; +} + + +implementation { + + + struct in6_addr ALL_RTR_MULTICAST_ADDR; + bool running= FALSE; + struct in6_addr LLAddress; //contains the Link Local Address formed with interface identifier being the EUI-64 + struct in6_addr global;//contains the global address of the node formed with the prefix received from Router Advertisement + struct in6_addr NS_DEST;//contains the destination address of the NS message + struct in6_addr TENTATIVE_ADDRESS;//This contains the tentative address formed after getting prefix + struct in6_addr NA_DEST;//contains the destination address of the NA message + struct in6_addr NA_SRC; + struct in6_addr target;//contains the target received in the NS message + ieee_eui64_t extended_addr;//contains the EUI-64 extended address + ieee_eui64_t NA_EUI; //contains the EUI-64 OF THE destination of NA message useful when the status is not zero + uint8_t numRSSent=0; //variable that will hold the count of number of RS messages sent + uint8_t numNSSent=0; //variable that will hold the count of number of NS messages sent + uint32_t RSInterval=RTR_SOLICITATION_INTERVAL; //Interval of the RS message + uint8_t NODESTATE=UNDEFINED; //contains the state of the node such as Host,Router,LBR + uint8_t HOP_LIMIT=0; + uint8_t RSSTATE=UNDEFINED; + uint8_t NSSTATE=UNDEFINED; + uint8_t SplitControlSTATE=NOTSENT; + bool RSSENT=FALSE; + uint32_t time=RTR_SOLICITATION_INTERVAL; + uint32_t remain; + uint16_t reachable_lifetime; + uint32_t RETRANSMISSION_TIME; + struct ip6_packet pkt; + context_opt context_option; + +#define ADD_BUFFER(DATA, LENGTH) ip_memcpy(buffer, (uint8_t *)(DATA), LENGTH);\ +buffer += (LENGTH); +/*******************************************Tasks and Fn*************************************************************************/ + void init() + { + memset(ALL_RTR_MULTICAST_ADDR.s6_addr, 0, 16); + ALL_RTR_MULTICAST_ADDR.s6_addr[0] = 0xFF; + ALL_RTR_MULTICAST_ADDR.s6_addr[1] = 0x2; + ALL_RTR_MULTICAST_ADDR.s6_addr[15] = 0x02; + extended_addr=call Ieee154Address.getExtAddr(); + call IPAddress.getEUILLAddress(&LLAddress); +// printf("link layer address:"); +// printf_buf(extended_addr.data,8); +// printf("\nLink Local Address"); +// printf_in6addr(&LLAddress); +// printfflush(); + + } + + void fillSAO(stlla_opt *sao) + { + int i; + sao->option_header.type=SLLAO; + sao->option_header.length=LENGTH_SLLAO; + sao->ll_addr=extended_addr; +// for(i=0;i<8;i++) + //sao->ll_addr.data[i]=extended_addr.data[7-i]; //byte ordering works at the linux side only + //filling the padding with zeroes + memset(&sao->reserved,0,sizeof(uint8_t)*6); + + } + + void fillTAO(stlla_opt *sao) + { + int i; + sao->option_header.type=TLLAO; + sao->option_header.length=LENGTH_SLLAO; + sao->ll_addr=extended_addr; +// for(i=0;i<8;i++) + //sao->ll_addr.data[i]=extended_addr.data[7-i]; //byte ordering works at the linux side only + //filling the padding with zeroes + memset(&sao->reserved,0,sizeof(uint8_t)*6); + + } + + void fillPacket(uint16_t length,struct ip6_packet *packet,struct ip_iovec *v) + { + + + packet->ip6_hdr.ip6_nxt=IANA_ICMP; + packet->ip6_hdr.ip6_plen=htons(length); + packet->ip6_hdr.ip6_hops=HOP_LIMIT; + packet->ip6_data=v; + //call Leds.led0Toggle(); + + } + + void fillARO(aro_opt *addr_opt) + { + addr_opt->option_header.type=ARO; + addr_opt->option_header.length=LENGTH_ARO; + addr_opt->status=0; + addr_opt->reserved1=0; + addr_opt->reserved2=0; + if(call Node.getRouterState()) + addr_opt->reg_lifetime=10; //10*60 Seconds=10 Minutes + else + addr_opt->reg_lifetime=5; //5*60 seconds=5 Minutes + addr_opt->eui64=call Ieee154Address.getExtAddr(); + } + #ifdef NODE_LBR + void fillPIOABRO(prefix_opt *pio,abro_opt *abr) + { + //filling Prefix Information Option first + pio->option_header.type=PREFIX_INFORMATION; + pio->option_header.length=LENGTH_PREFIX; + pio->prefix_information.prefix_length=PREFIX_LENGTH; //no. of leading bits in the prefix that are valid + pio->prefix_information.a_bit=1; //this can be used for stateless address autoconfiguration + pio->prefix_information.l_bit=0; + pio->prefix_information.valid_lifetime=PREFIX_VALID_LIFETIME;//lifetime in seconds that prefix is valid for on-link determination + pio->prefix_information.preferrd_lifetime=PREFIX_PREF_LIFETIME;//(500min)lifetime in seconds that prefix is valid for stateless address autoconfiguration + //inet_pton6(GLOBAL_PREFIX,&pio->prefix_information.prefix); + inet_pton6(IN6_PREFIX,&pio->prefix_information.prefix); + //filling the Authoritative Border Router Option + abr->option_header.type=ABRO; + abr->option_header.length=LENGTH_ABRO; + abr->abro_information.ver_low=ABR_VER_LOW; + abr->abro_information.ver_high=ABR_VER_HIGH; + abr->abro_information.valid_lifetime=ABR_LIFETIME; //500 minutes + memcpy(&abr->abro_information.lbr_addr,call RPLRoute.getDodagId(),sizeof(struct in6_addr)); + } + #endif + + void fillmsgicmp(struct icmpv6_header *icmpv6,uint8_t type) + { + icmpv6->type=type; + icmpv6->code=ICMPV6_ND_CODE; + icmpv6->checksum=0; + } + + /* Section 5.5.1(RFC 6775)Host triggers sending NS messages containing an ARO when a new address is configured,when it discovers a new default router,or well before the registration lifetime expires.Such an NS must include an SLLAO,since the router needs to record the link-layer address of the host*/ + void sendMsg(struct in6_addr ip,uint8_t type) + { + //messages + router_solicit solicit_msg; + neighbr_solicit msg; + //options + stlla_opt sao; + aro_opt addr_opt; + + struct ip_iovec v[1]; + uint8_t *buffer; + uint8_t data[MSG_SIZE]; + uint16_t length=0; + + + memset(&pkt,0,sizeof(struct ip6_packet)); + + + if(!running) + return; + /* Filling the Message */ + if(type==RS) + { + fillmsgicmp(&solicit_msg.icmpv6,ICMP_TYPE_ROUTER_SOL); + solicit_msg.reserved=0; + + } + if(type==NS) + { + fillmsgicmp(&msg.icmpv6,ICMP_TYPE_NEIGHBOR_SOL); + msg.reserved=0; + if(NSSTATE==ARO) + { + // printf("\n NS asking for registration"); + // printf_in6addr(&TENTATIVE_ADDRESS); + memcpy(&msg.target,&TENTATIVE_ADDRESS,sizeof(struct in6_addr));//TODO:Has to change this and make some generic one + //filling the Address Registration Option + fillARO(&addr_opt); + } + if(NSSTATE==NUD) + { + // printf("\n Checking Neighbor Reachability of:"); + memcpy(&msg.target,&ip,sizeof(struct in6_addr)); + // printf_in6addr(&ip); + } + + } + //filling the options for RS message we just fill the SLLAO whereas for NS message fill SLLAO and ARO if required + fillSAO(&sao); + + buffer = (uint8_t *)&data; + if(type==RS) + { + ADD_BUFFER(&solicit_msg,sizeof(router_solicit)); + length=sizeof(router_solicit); + } + if(type==NS) + { + ADD_BUFFER(&msg,sizeof(neighbr_solicit)); + length=sizeof(neighbr_solicit); + if(NSSTATE==ARO) + { + ADD_BUFFER(&addr_opt,sizeof(aro_opt)); + length=length+sizeof(aro_opt); + } + } + ADD_BUFFER(&sao,sizeof(stlla_opt)); + length=length+sizeof(stlla_opt); + v[0].iov_base=(uint8_t *)data; + v[0].iov_len=length; + v[0].iov_next=NULL; + fillPacket(length,&pkt,&v[0]); + + + if(type==RS) + { + memcpy(&pkt.ip6_hdr.ip6_src,&LLAddress,sizeof(struct in6_addr)); + if(RSSTATE==MULTICAST) + memcpy(&pkt.ip6_hdr.ip6_dst,&ALL_RTR_MULTICAST_ADDR,16); + + if(RSSTATE==UNICAST) + memcpy(&pkt.ip6_hdr.ip6_dst,&ip,16); + + pkt.ip6_hdr.ip6_hops=0xff; //according to rfc 4861 + call IP_RS.send(&pkt); + + //printfflush(); + numRSSent++; + + call RSTimer.startOneShot(time); + //printf("\n Send RS message With destination address"); + //printf_in6addr(&pkt.ip6_hdr.ip6_dst); + } + if(type==NS) + { + pkt.ip6_hdr.ip6_hops=HOP_LIMIT; + #ifdef NODE_LBR + memcpy(&pkt.ip6_hdr.ip6_src,call RPLRoute.getDodagId(),sizeof(struct in6_addr)); + #else + memcpy(&pkt.ip6_hdr.ip6_src,&LLAddress,sizeof(struct in6_addr)); + #endif + if(NSSTATE==ARO) + { + if(call Node.getRouterState()&&NODESTATE==ROUTER) + { + // printf("\ndirectly refresh its registration with lbr"); + call NeighbrCache.getLBRAddress(&pkt.ip6_hdr.ip6_dst); + + } + else + { + // printf("\nRefreshing Registrations with router"); + call RouterList.getRouterIP(&pkt.ip6_hdr.ip6_dst); + } + + } + if(NSSTATE==NUD) + { + memcpy(&pkt.ip6_hdr.ip6_dst,&ip,sizeof(struct in6_addr)); + } + call NSTimer.startOneShot(RETRANS_TIMER); + //printf("\n Sending the NS message to "); + //printf_in6addr(&pkt.ip6_hdr.ip6_dst); + numNSSent++; + pkt.ip6_hdr.ip6_hops=0xff; //according to rfc 4861 + + call IP_NS.send(&pkt); + } + } + + void chooseInterval() + { + + RSSENT=TRUE; + RSInterval*=2; + if(RSInterval>MAX_RTR_SOLICITATION_INTERVAL) + { + RSInterval=MAX_RTR_SOLICITATION_INTERVAL; + + } + time=RSInterval; + time/=2; + time+=call Random.rand32()%time; + sendMsg(ALL_RTR_MULTICAST_ADDR,RS); + } + + + void remainInterval() + { + RSSENT=FALSE; + remain=RSInterval-time; + call RSTimer.startOneShot(remain); + } + + #ifndef NODE_HOST + + + void fill6CO(context_opt *ctx_opt) + { + + //fill in the option header + ctx_opt->option_header.type = CONTEXT_0PTION; + + //fill in the length + ctx_opt->option_header.length = LENGTH_CONTEXT2; + + //fill in the header + + ctx_opt->c_bit = 1; + + ctx_opt->cid=1; + + ctx_opt->valid_lifetime = 30; + + ctx_opt->prefix.s6_addr[0] = 0x20; + ctx_opt->prefix.s6_addr[1] = 0x00; + ctx_opt->prefix.s6_addr[7] = 0x01; + + } + + + void sendRA(struct in6_addr address) + { + + router_advt advt_msg; + stlla_opt sao; + abro_opt abr; + prefix_opt pio; + struct ip_iovec v[1]; + #ifdef NODE_ROUTER + prefix_list *send_prefix; + #endif + uint8_t *buffer; + uint8_t data[RA_MSG_SIZE]; + uint16_t length; //it contains the length of the payload + uint8_t prefix_count,i; + if(!running) + return; + + //printf("\n SendRA function"); + memset(&advt_msg,0,sizeof(router_advt)); + fillmsgicmp(&advt_msg.icmpv6,ICMP_TYPE_ROUTER_ADV); + #ifdef NODE_LBR + /*Filling the Router Advertisement structure */ + + prefix_count=1; + advt_msg.cur_hop_limit=RTR_HOP_LIMIT; + advt_msg.router_lifetime=RTR_LIFE_TIME; //section 5.4(RFC 6775) Maximum value of the RA router Lifetime may be upto 0xffff + advt_msg.reachable_time=RTR_REACHABLE_TIME;//3 min it will be reachable after confirmation(should not be > 1 hour) + advt_msg.retrans_timer=RETRANS_TIMER; //30 sec between NS message + #else + //filling the sllao option + advt_msg.cur_hop_limit=HOP_LIMIT; + advt_msg.router_lifetime=RTR_LIFE_TIME; //section 5.4(RFC 6775) Maximum value of the RA router Lifetime may be upto 0xffff + advt_msg.reachable_time=RTR_REACHABLE_TIME;//3 min it will be reachable after confirmation(should not be > 1 hour) + advt_msg.retrans_timer=RETRANS_TIMER; //30 sec between NS message + prefix_count=call NeighbrCache.prefixes_count(); + #endif + fillSAO(&sao); + //filling the Prefix Information Option and ABRO + for(i=0;iabro_information,sizeof(abro_info)); + } + #endif + #ifdef NODE_LBR + fillPIOABRO(&pio,&abr); + fill6CO(&context_option); + #endif + //adding both the payload and the options + buffer = (uint8_t *)&data; + ADD_BUFFER(&advt_msg,sizeof(router_advt)); + ADD_BUFFER(&sao,sizeof(stlla_opt)); + ADD_BUFFER(&pio,sizeof(prefix_opt)); + ADD_BUFFER(&context_option,sizeof(context_opt)); + ADD_BUFFER(&abr,sizeof(abro_opt)); + length=sizeof(router_advt)+sizeof(stlla_opt)+sizeof(abro_opt)+sizeof(prefix_opt)+sizeof(context_opt); + v[0].iov_base=(uint8_t *)data; + v[0].iov_len=length; + v[0].iov_next=NULL; + fillPacket(length,&pkt,&v[0]); + memcpy(&pkt.ip6_hdr.ip6_dst,&address,16); + #ifdef NODE_LBR + memcpy(&pkt.ip6_hdr.ip6_src,call RPLRoute.getDodagId(),sizeof(struct in6_addr)); + #else + memcpy(&pkt.ip6_hdr.ip6_src,&LLAddress,sizeof(struct in6_addr)); + #endif + call IP_RA.send(&pkt); + } + } + #endif + + /* If Status==3 it means responding to an NS message for NUD */ + void sendNA(uint8_t status,ieee_eui64_t eui, uint16_t reg_lifetime) + { + neighbr_advt na; + struct ip_iovec v[1]; + aro_opt addr_opt; + stlla_opt sao; + uint8_t *buffer; + uint8_t data[NA_MSG_SIZE]; + + uint16_t length; //it contains the length of the payload + if(!running) + return; + + ////printf("\n In SendNA function"); + + + fillmsgicmp(&na.icmpv6,ICMP_TYPE_NEIGHBOR_ADV); + if(call Node.getRouterState()||call Node.getLBRState()) + na.r_bit=1; + if(call Node.getHostState()) + na.r_bit=0; + na.s_bit=0; + na.reserved=15; + na.reserved1=0; + na.reserved2=0; + memcpy(&na.target,&target,sizeof(struct in6_addr)); //TODO:Dont use global variables + //printf("\n SendNA:status is %d",status); + //filling the aro structure + if(status!=3) + { + addr_opt.option_header.type=ARO; + addr_opt.option_header.length=LENGTH_ARO; + addr_opt.status=status; + addr_opt.reserved1=0; + addr_opt.reserved2=0; + addr_opt.reg_lifetime=reg_lifetime; + memcpy(&addr_opt.eui64,&eui,sizeof(ieee_eui64_t)); + } + fillTAO(&sao); + buffer=(uint8_t *)&data; + ADD_BUFFER(&na,sizeof(neighbr_advt)); + ADD_BUFFER(&sao,sizeof(stlla_opt)); + length=sizeof(neighbr_advt)+sizeof(stlla_opt); + if(status!=3) + { + ADD_BUFFER(&addr_opt,sizeof(aro_opt)); + length=length+sizeof(aro_opt); + } + + v[0].iov_base=(uint8_t *)data; + v[0].iov_len=length; + v[0].iov_next=NULL; + fillPacket(length,&pkt,&v[0]); + memcpy(&pkt.ip6_hdr.ip6_dst,&NA_DEST,sizeof(struct in6_addr)); + #ifdef NODE_LBR + memcpy(&pkt.ip6_hdr.ip6_src,call RPLRoute.getDodagId(),sizeof(struct in6_addr)); + #else + if(NA_SRC.s6_addr16[0]==htons(0xff02)) //if multicasts a NS we will copy target as multicasts only happens during address resolution not during address registration + memcpy(&pkt.ip6_hdr.ip6_src,&target,sizeof(struct in6_addr)); + else + memcpy(&pkt.ip6_hdr.ip6_src,&NA_SRC,sizeof(struct in6_addr)); //this is because neighbor cache of the NS sender does not have cache entry + #endif + //printf("\nNA solicited flag:%d",na.s_bit); + //printf_in6addr(&pkt.ip6_hdr.ip6_dst); + pkt.ip6_hdr.ip6_hops=0xff; + call IP_NA.send(&pkt); + } + + #ifdef NODE_ROUTER + void sendDAR(uint16_t reg_lifetime,ieee_eui64_t eui64,struct in6_addr ip) /*Section 8.2.3 */ + { + darc request; + struct ip_iovec v[1]; + uint8_t *buffer; + uint8_t data[DAR_MSG_SIZE]; + uint16_t length; //it contains the length of the payload + // printf("\n Send DAR function"); + //filling the Duplicate Address Request Structure + fillmsgicmp(&request.icmpv6,ICMP_TYPE_DUPLICATE_REQ); + request.status=0; + request.reserved=0; + request.reg_lifetime=reg_lifetime; + + memcpy(&request.eui64,&eui64,sizeof(ieee_eui64_t)); + memcpy(&request.reg_addr,&ip,sizeof(struct in6_addr)); + + //filling the IP Packet + buffer=(uint8_t *)&data; + ADD_BUFFER(&request,sizeof(darc)); + length=sizeof(darc); + + v[0].iov_base=(uint8_t *)data; + v[0].iov_len=length; + v[0].iov_next=NULL; + fillPacket(length,&pkt,&v[0]); + memcpy(&pkt.ip6_hdr.ip6_src,&global,sizeof(struct in6_addr)); + call NeighbrCache.getLBRAddress(&pkt.ip6_hdr.ip6_dst); + call IP_DAR.send(&pkt); + } + + #endif + #ifdef NODE_LBR + void sendDAC(uint8_t status,struct ip6_hdr *hdr,void *packet) + { + + darc reply; + struct ip_iovec v[1]; + uint8_t *buffer; + uint8_t data[DAC_MSG_SIZE]; + uint16_t length; //it contains the length of the payload + darc *request; + request=(darc *)packet; + //printf("\n Send DAC function"); + + + //filling the DAC structure + + fillmsgicmp(&reply.icmpv6,ICMP_TYPE_DUPLICATE_CONFIRM); + reply.status=status; + reply.reserved=0; + reply.reg_lifetime=request->reg_lifetime; + memcpy(&reply.eui64,&request->eui64,sizeof(ieee_eui64_t)); + memcpy(&reply.reg_addr,&request->reg_addr,sizeof(struct in6_addr)); + + buffer=(uint8_t *)&data; + ADD_BUFFER(&reply,sizeof(darc)); + length=sizeof(darc); + + v[0].iov_base=(uint8_t *)data; + v[0].iov_len=length; + v[0].iov_next=NULL; + fillPacket(length,&pkt,&v[0]); + + + memcpy(&pkt.ip6_hdr.ip6_src,call RPLRoute.getDodagId(),sizeof(struct in6_addr)); + memcpy(&pkt.ip6_hdr.ip6_dst,&hdr->ip6_src,sizeof(struct in6_addr)); + + + call IP_DAC.send(&pkt); + } + #endif + /*******************************************COMMANDS*************************************************************************/ + command error_t SplitControl.start() + { + + running=TRUE; + init(); + call RadioControl.start(); //starting the radio + call NeighbrCache.init(); + #if! defined NODE_LBR && !defined NODE_HOST && !defined NODE_ROUTER + /*this is to make sure that user has selected one type of role of the node*/ + //call Node.setHost(); + signal SplitControl.startDone(FAIL); + SplitControlSTATE=SENT; + call Leds.led1Toggle(); + #warning "*** NO Neighbor role set ***" + return FAIL; + #endif + #ifdef NODE_LBR + NODESTATE=LBR; + call Node.setLBR(); + //call RootControl.setRoot(); + //printf("\n Iam a LBR so Iam the Root of this network"); + call NeighbrCache.startNUD(); + signal SplitControl.startDone(SUCCESS); + SplitControlSTATE=SENT; + + #endif + #ifdef NODE_ROUTER + call Node.setRouter(); //again setting to host for autoconfiguration + call Node.setHost(); + NODESTATE=HOST; + RSSTATE=MULTICAST; + sendMsg(ALL_RTR_MULTICAST_ADDR,RS); + #endif + #ifdef NODE_HOST + call Node.setHost(); + NODESTATE=HOST; + RSSTATE=MULTICAST; + sendMsg(ALL_RTR_MULTICAST_ADDR,RS); + + #endif + //more than one role has been specified + if((call Node.getHostState()&&(call Node.getRouterState()&&NODESTATE!=HOST))||(call Node.getRouterState()&&call Node.getLBRState())||(call Node.getLBRState()&&call Node.getHostState())) + { + call Leds.led0On(); + signal SplitControl.startDone(FAIL); + SplitControlSTATE=SENT; + return FAIL; + } +// call RoutingControl.start(); //starting the rpl + return SUCCESS; + + } + + + command error_t SplitControl.stop() + { + running= FALSE; + call RadioControl.stop(); + //call RoutingControl.stop(); + return SUCCESS; + + } + +/*******************************************EVENTS*************************************************************************/ + + + event void RSTimer.fired() + { + + + if(call Node.getRouterState()&&NODESTATE==ROUTER){ + //this is required when suppose prefix lifetime expires and has to send RS unicastly if no response then they will go for MULTICAST + NODESTATE=HOST; + call Node.setHost(); + } + //NO RA received transmit RS again; + if(numRSSenticmpv6.code!=0)||(len<8)) + return; + + + option=(stlla_opt *)call Option.findoption(packet,LENGTH_RS,SLLAO); + /* If there is no Source Link Layer Option Available */ + if(option==0) + return; + //printf("\n RS Message Received"); + ////printf_buf(option->ll_addr.data,8); + if((call Node.getRouterState()&&NODESTATE==ROUTER)||NODESTATE==LBR) + { + info.isRouter=0; + info.next_ndtime=RETRANS_TIMER; + info.type=TENTATIVE; + info.timer=TENTATIVE_NCE_LIFETIME; + info.state=STALE; + //adding an entry in his neighbor cache + if(call NeighbrCache.addentry(hdr->ip6_src,option->ll_addr,info)==SUCCESS) + { + // printf("\n RS message Receivd added entry in the Neighbor Cache:"); + // printf_in6addr(&hdr->ip6_src); + } + sendRA(hdr->ip6_src); + } + #endif + } + + /* Router Advertisement Received */ + event void IP_RA.recv(struct ip6_hdr *hdr, void *packet, + size_t len, struct ip6_metadata *meta){ + + neighbr_cache *cache; + router_advt *adv; + stlla_opt *opt; + prefix_opt * prefix_option; + neighbr_info info; + abro_opt *abro; + context_opt *ctx; + + prefix_option=(prefix_opt *)call Option.findoption(packet,LENGTH_RA,PREFIX_INFORMATION); + abro=(abro_opt *)call Option.findoption(packet,LENGTH_RA,ABRO); + opt=(stlla_opt *)call Option.findoption(packet,LENGTH_RA,SLLAO); + ctx=(context_opt *)call Option.findoption(packet,LENGTH_RA,CONTEXT_0PTION); + adv=(router_advt *)packet; + + //printf("\n ABRO:version:%d",abro->abro_information.ver_low); + + //printf("\n RA receive function with address"); + /*if(prefix_option) + printf("\n Prefix information option is present"); + else + printf("\n NO Prefix information option present"); + + if(opt) + printf("\n SLLAO Option present"); + else + printf("\n No SLLAO "); + + if(abro) + printf("\n ABRO Present"); + else + printf("\n ABRO Not Present"); + printfflush(); + printf_in6addr(&hdr->ip6_src); + */ + /* Validation of RA message (Section 6.1.2 of RFC 4861) */ + /* If the IP Source Address should be a link-local address so that hosts can uniquely identify routers */ + /* ICMP Code is 0 */ + /*ICMP Length(Derived from the IP length) is 16 or more octets*/ + + //this is to make sure that entries received from LBR should not be discarded + if((!call IPAddress.isLLAddress(&hdr->ip6_src))||(adv->icmpv6.code!=0)||(len<16)) + { + /*if(!(memcmp(&hdr->ip6_src,call RPLRoute.getDodagId(),sizeof(struct in6_addr)))) + { + printf("\n Leaving just LBR entries"); + } + else + return; + */ + } + if(opt==0) //No SLLAO dont process(RFC 6775 Section 5.4) + { + //printf("\n no sllaoo dont process"); + //printfflush(); + return; + } + else + { + RSInterval=RTR_SOLICITATION_INTERVAL; + time=RSInterval; + numRSSent=0; + //stop the timer as RS message is received + call RSTimer.stop(); + cache=call NeighbrCache.findEntry(hdr->ip6_src);//check whether the address is already present in the hosts default router list + if(cache==0) //if not present + { + if(adv->router_lifetime)//advertisement Router Lifetime is non-zero + {//create a new entry and initialize its invalidaton timer value from the advertisements Router Lifetime field + info.isRouter=1; //As the Router Advertisements are received only from Routers + RETRANSMISSION_TIME=adv->retrans_timer; + // printf("retransmission time:%ld\n",RETRANSMISSION_TIME); + // printfflush(); + info.next_ndtime=adv->reachable_time; + info.type=REGISTERED; + info.timer=adv->router_lifetime; + /*Section 6.3.4 of RFC4861 If a Neighbor Cache entry is created for the router,its reachability state should be set to STALE*/ + info.state=STALE; + if(call NeighbrCache.addentry(hdr->ip6_src,opt->ll_addr,info)==SUCCESS) + { + //printf("\n RA message received adding entry in the Neighbor Cache"); + //printf_in6addr(&hdr->ip6_src); + } + if(call RouterList.add(hdr->ip6_src)!=SUCCESS) + { + // printf("\n Router cannot be added due to some reasons"); + // printfflush(); + } + else{ + call NeighbrCache.startNUD(); + // printf("\nRouter Added"); + } + } + else //discarding as the router has zero lifetime + { + return; + } + } + //if address is present in the Default Router List,as a result of previously received advertisement,reset its invalidation timer to the Router Lifetime in the newly received advertisement + /*If a cache entry already exists,the reachability state MUST also be set to STALE*/ + else + { + ////printf("\n Already IP address exists in the cache Update its cache timer %ld",cache->info.timer); + cache->info.state=STALE; + cache->info.timer=adv->router_lifetime; + } + + + /* If the received Cur Hop Limit value is non-zero,the host should set its CurHopLimit Variable to the received value*/ + if(adv->cur_hop_limit!=0) + { + HOP_LIMIT=adv->cur_hop_limit; + } + /* After extracting information from the fixed part of Router Advertisement message,the advertisement is scanned for valid options*/ + + if(abro!=0&&abro->option_header.type==ABRO) + { + if(call NeighbrCache.checkPrefix(prefix_option->prefix_information.prefix,abro->abro_information.lbr_addr, + abro->abro_information.ver_high,abro->abro_information.ver_low)==FAIL) + { + //As the information is already present discard the info + // printf("\n ABRO Information already exists discarding"); + return ; + } + + if(adv->m_bit) //if this bit is set then we have to go for DHCP + { + signal SplitControl.startDone(SUCCESS); //has to use linklocal address because DHCP is to be done later + } + else + { + if(prefix_option!=0&&!prefix_option->prefix_information.l_bit) //address autoconfiguration + { + //printf("\n received.prefix length:%d",prefix_option->prefix_information.prefix_length); + //printf("\n received .valid_lifetime:%ld",prefix_option->prefix_information.valid_lifetime); + //filling the prefix information + call NeighbrCache.addPrefix(prefix_option->prefix_information,abro->abro_information); + memcpy(&TENTATIVE_ADDRESS,&prefix_option->prefix_information.prefix,sizeof(struct in6_addr)); + TENTATIVE_ADDRESS.s6_addr16[7]=htons(call Ieee154Address.getShortAddr()); + memcpy(&global,&TENTATIVE_ADDRESS,sizeof(struct in6_addr)); + call RouterList.getRouterIP(&NS_DEST); + + //store the 6CO Option if present + + if(ctx!=0) + { + + //Section 5.4.2 of RFC 6775 + //store the cid,prefix and lifetime + call NeighbrCache.storeCtx(ctx->prefix,ctx->cid,ctx->valid_lifetime); + + + + } + + + //NSSTATE=NUD; + NSSTATE=ARO; + // printf("\n sending ns"); + sendMsg(NS_DEST,NS); + //call NSTimer.startOneShot(RETRANS_TIMER); + }else{ + // printf("\n l bit not set"); + + } + } + } + else//Either No Prefix Information Option available or No ABRO available.Sending RS message again + { + // printf("no ns"); + //call RSTimer.startOneShot(RSInterval);//for sending task + if(SplitControlSTATE==NOTSENT) + { + SplitControlSTATE=SENT; + call Leds.led2On(); + signal SplitControl.startDone(SUCCESS); //if no prefix information is received node will use link-local address + } + } + } + //printfflush(); +} + + /* Neighbor Advertisement Received */ + event void IP_NA.recv(struct ip6_hdr *hdr, void *packet, + size_t len, struct ip6_metadata *meta) + { + aro_opt *reg; + neighbr_advt *na; + neighbr_cache *cache; + stlla_opt *opt; + struct in6_addr lbr_addr; + na=(neighbr_advt *)packet; + + numNSSent=0; //resetting the variable as we are receiving the NA message + + + /* Validation of NA Message According to RFC 4861 (Section 7.1.2) */ + /*ICMP Code is 0*/ + /*ICMP Length is 24 or more octets */ + /*Target Address is not a Multicast Address*/ + if(na->icmpv6.code!=0 || len<24 ||na->target.s6_addr[0]==0xff) + return; + + /* RFC 4861:7.2.5:When a valid Neighbor Advertisement is received,the Neighbr Cache is searched for the target's entry.If no entry exist,the advertisement should be silently discarded.There is no need to create an entry if none exists*/ + + cache=call NeighbrCache.findEntry(hdr->ip6_src); + if(cache==0){ + call NeighbrCache.getLBRAddress(&lbr_addr); + if(!(memcmp(&hdr->ip6_src,&lbr_addr,sizeof(struct in6_addr)))) + { + // printf("\n Leaving just LBR entries"); + goto done; + } + else{ + + // printf("\n Returning because no entry exist in the cache:"); + // printf_in6addr(&hdr->ip6_src); + return; + } + } + + // printf("\n In NA Receive Function from"); + // printf_in6addr(&hdr->ip6_src); + /* If the override flag is set,or the supplied link-layer address is the same as that in the cache,or no Target Link-Layer address was supplied */ + + if(na->o_bit||opt==0||call NeighbrCache.findIPEUI64(na->target,opt->ll_addr)) + { + /*If the solicited flag is set,the state of the entry MUST be set to REACHABLE*/ + if(na->s_bit) + { + // printf("\n Setting the State to Reachable"); + cache->info.state=REACHABLE; + }else{ + // printf("\n not setting state"); + } + // printfflush(); + //TODO:When the isRouter flag changes from TRUE to FALSE as a result of this update,the node must remve the + //router from the default router list. + if(cache->info.isRouter==TRUE&&cache->info.isRouter!=na->r_bit){ + + call RouterList.remove(na->target); + } + + /*The ISRouter flag in the cache entry MUST be set based on the Router flag in the received advertisement*/ + cache->info.isRouter=na->r_bit; + + + } +done: + call NSTimer.stop(); + reg=(aro_opt *)call Option.findoption(packet,LENGTH_NA,ARO); + if(reg!=0) //this may be reply of ARO registration + { + + /*Section 5.5.2 of RFC6775 */ + /*If the length field is not two the option is silently ignored,If the EUI-64 field does not match the EUI-64 of the interface,the option is silently ignored*/ + if(reg->option_header.length!=2&&(memcmp(®->eui64,&extended_addr,sizeof(struct in6_addr)))) + return; + + if(reg->status==0) + { + /*The host chooses a lifetime of the registration and repeats the ARO periodically(before the lifetime runs out) to maintain the registration */ + //printf("\n the registration lifetime is %d",reg->reg_lifetime); + call AROTimer.startOneShot(reg->reg_lifetime-2); + //printf("\n successfully registered with the router"); + call SetIPAddress.setAddress(&na->target); + //printf("\n The Global IP Address is:"); + call IPAddress.getGlobalAddr(&global); + //printf_in6addr(&global); + + #ifdef NODE_ROUTER + if(call Node.getRouterState()&&NODESTATE==HOST) //now change back to router + { + call Node.unsetHost(); + NODESTATE=ROUTER; + if(call RouterList.removeAll()==SUCCESS){} + //printf("\n Removing all the routers from the router list"); + } + #endif + call NSTimer.stop(); //stop the timer as the NA is received with status=0 + if(SplitControlSTATE==NOTSENT) //this is required so that Signal SplitControl is sent one time only + { + SplitControlSTATE=SENT; + signal SplitControl.startDone(SUCCESS); //if no prefix information is received node will use link-local address + } + } + /*If status=1 then use EUI-64 to generate the IP and send a NS message with ARO to the router*/ + else if(reg->status==1) + { + //printf("\nDuplicate Address"); + //printf_in6addr(&na->target); + //printf("\n Using EUI-64 to generate the IP"); + memcpy(&TENTATIVE_ADDRESS.s6_addr16[4],&extended_addr,sizeof(ieee_eui64_t)); + ////printf("\n The IP Address after using EUI-64 as interface identifier is:"); + ////printf_in6addr(&TENTATIVE_ADDRESS); + sendMsg(NS_DEST,NS); + NSSTATE=ARO; + //call NSTimer.stop(); //TODO:has to remove this thing + } + + } + } + /* Neighbor Solicitation Received */ + event void IP_NS.recv(struct ip6_hdr *hdr, void *packet, + size_t len, struct ip6_metadata *meta) + { + + aro_opt *add_opt; + neighbr_solicit *ns; + stlla_opt *option; + #if defined NODE_ROUTER + neighbr_info info; + #endif + ns=(neighbr_solicit *)packet; + /*A valid Neighbor Solicitation that does not meet any of the following requirements MUST be silently discarded*/ + /* The target address is a valid unicast or anycast address(RFC 4861 Section 7.2.3)*/ + + + if(ns->target.s6_addr[0]==0xff) + return; + + memcpy(&target,&ns->target,sizeof(struct in6_addr)); + memcpy(&NA_DEST,&hdr->ip6_src,sizeof(struct in6_addr)); + memcpy(&NA_SRC,&hdr->ip6_dst,sizeof(struct in6_addr)); + option=(stlla_opt *)call Option.findoption(packet,LENGTH_NS,SLLAO); + add_opt=(aro_opt *)call Option.findoption(packet,LENGTH_NS,ARO); + if(option==0) //section 6.5 dont process ARO + return; + else + { + //call Leds.led0Toggle(); + //printf("\n In NS receive function"); + //checking for valid ARO If present + if(add_opt!=0) + { + if(add_opt->option_header.length!=LENGTH_ARO||add_opt->status!=0) //section 6.5 + { + //printf("\n Discarding the Message as status is not zero"); + return; + } + } + + /*If no entry exist,the node will create an new one and set the ISRouter Flag to FALSE(RFC 4861 Section 7.2.3) */ + if(call IPAddress.isLocalAddress(&ns->target)) + { + //printf("\n i think this message is for NUD"); + sendNA(3,add_opt->eui64,add_opt->reg_lifetime); + return; + }else{ + //printf("Not Local:"); + //printf_in6addr(&ns->target); + } + #if defined NODE_ROUTER + // printf("\n NS Receive: target checking in the entry"); + // printf_in6addr(&ns->target); + memcpy(&NA_EUI,&add_opt->eui64,sizeof(ieee_eui64_t)); + if(!call NeighbrCache.findEntry(ns->target)) + { + if(add_opt->reg_lifetime) + { + //it isn't a duplicate + info.isRouter=0; + info.next_ndtime=RETRANS_TIMER; + info.type=TENTATIVE; + info.timer=TENTATIVE_NCE_LIFETIME; + if(call NeighbrCache.addentry(ns->target,add_opt->eui64,info)==SUCCESS) + { + // printf("\n Adding entry in the Neighbr Cache NS message received:"); + // printf_in6addr(&ns->target); + } + if(*(uint8_t *)add_opt!=0) //if ARO is present then only send the DAR + { + sendDAR(add_opt->reg_lifetime,add_opt->eui64,ns->target); + return; + } + } + else{ //if the registration lifetime is zero dont add the entry and send it to LBR + + sendDAR(add_opt->reg_lifetime,add_opt->eui64,ns->target); + } + + } + else if(call NeighbrCache.findIPEUI64(ns->target,add_opt->eui64)) + { + if(*(uint8_t *)add_opt!=0) //if ARO is present then only send the DAR + { + if(add_opt->reg_lifetime) + { + sendDAR(add_opt->reg_lifetime,add_opt->eui64,ns->target); + return; + } + else //if registration lifetime is zero delete the entry and send it to the LBR + { + call NeighbrCache.removeentry(ns->target); + sendDAR(add_opt->reg_lifetime,add_opt->eui64,ns->target); + } + } + } + else{//it is a duplicate + if(*(uint8_t *)add_opt!=0) //Only when the ARO is present + { + sendNA(1,add_opt->eui64,add_opt->reg_lifetime); + } + } + #endif + + #ifdef NODE_LBR /* This is required because initially there may be router and 6lbr then no need + of DAR,DAC*/ + + // printf("NS Recv:IP Address receive for checking"); + // printf_in6addr(&ns->target); + //If the IPAddress is not found,it returns a NA with status set to zero and updates the lifetime + if(!call NeighbrCache.DADfindEntry(ns->target)) + { + if(add_opt->reg_lifetime) + { + call NeighbrCache.DADaddEntry(ns->target,add_opt->eui64,add_opt->reg_lifetime); + sendNA(0,add_opt->eui64,add_opt->reg_lifetime); + } + else //Delete the entry + { + sendNA(0,add_opt->eui64,add_opt->reg_lifetime); + } + + } + else + { + int i; + i=call NeighbrCache.DADfindIPEUI64(ns->target,add_opt->eui64); + //printf("NS:value of i is %d",i); + if(i!=-1) + { + dad_cache *cache; + cache=call NeighbrCache.getDADEntry(i); + if(!add_opt->reg_lifetime) //if registration lifetime is zero delete the entry + { + call NeighbrCache.DADremoveEntry(ns->target); + } + else + { + if(cache->reg_lifetime==0) + { + call NeighbrCache.DADremoveEntry(ns->target); + call NeighbrCache.DADaddEntry(ns->target,add_opt->eui64,add_opt->reg_lifetime); + } + else + { + cache->reg_lifetime=add_opt->reg_lifetime; + } + } + sendNA(0,add_opt->eui64,add_opt->reg_lifetime); + } + else + { + sendNA(1,add_opt->eui64,add_opt->reg_lifetime); + } + } + #endif + } + } + + event void IP_DAR.recv(struct ip6_hdr *hdr, void *packet, + size_t len, struct ip6_metadata *meta){/* Section 8.2.4 */ + #ifdef NODE_LBR //As the DAR are processed only by the 6LBR + darc *request; + request=(darc *)packet; + + /* Check Whether the DAR is Valid*/ + + /* If the ICMP length is 32 or more bytes,ICMP code is 0 */ + if(lenicmpv6.code!=0) + return; + /* If the registered address is a multicast address*/ + if(request->reg_addr.s6_addr[0]==0xff) + return; + + // printf("\n In SendDAR receive"); + + /* If no entry is found in the DAD Table and the Reg Lifetime is Non-zero,then an entry is created and the EUI-64 + and Registered Address from the DAR are stored in that entry*/ + if(!call NeighbrCache.DADfindEntry(request->reg_addr)) + { + if(request->reg_lifetime!=0) + { + call NeighbrCache.DADaddEntry(request->reg_addr,request->eui64,request->reg_lifetime); + + } + sendDAC(0,hdr,packet); + + } + else/* If the IPAddress is found and EUI-64 in the table is different from the EUI-64 from the DAC message then it is Duplicate and DAC is sent with status set to 1*/ + { + + int i; + i=call NeighbrCache.DADfindIPEUI64(request->reg_addr,request->eui64); + if(i==-1) + { + sendDAC(1,hdr,packet); + } + /*If an entry is found in the DAD Table,the EUI-64 matches,and the Reg Lifetime is zero then the entry is deleted from the table*/ + else + { + dad_cache *cache; + cache=call NeighbrCache.getDADEntry(i); + if(cache->reg_lifetime==0&&request->reg_lifetime) + { + call NeighbrCache.DADremoveEntry(request->reg_addr); + call NeighbrCache.DADaddEntry(request->reg_addr,request->eui64,request->reg_lifetime); + sendDAC(0,hdr,packet); + } + else + { + cache->reg_lifetime=request->reg_lifetime; + sendDAC(0,hdr,packet); + } + } + } + #endif + //call Leds.led2Toggle(); + } + + event void IP_DAC.recv(struct ip6_hdr *hdr, void *packet, + size_t len, struct ip6_metadata *meta){ + #if defined NODE_ROUTER + darc *reply; + uint8_t i; + neighbr_cache *neighbr; + reply=(darc *)packet; + + /* Validation of the DAC message */ + /* If the ICMP length is 32 or more bytes,ICMP code is 0 */ + if(lenicmpv6.code!=0) + return; + /* If the registered address is a multicast address*/ + if(reply->reg_addr.s6_addr[0]==0xff) + return; + + //printf("\n In DAC Receive Event"); + + /* For a valid DAC,if there is no Tentative NCE matching the Registered Address and EUI-64,then the DAC is silently ignored */ + // printf("\n DAC checking Neighbor Exists or not"); + // printf_in6addr(&reply->reg_addr); + neighbr=call NeighbrCache.findEntry(reply->reg_addr); + if(neighbr==0){ + // printf("DAC:Neighbor Not FOund"); + return; + } + /*In the case where the DAC indicates an error(the status in non-zero),the NA is returned to the host and the TENTATIVE NCE for the registered Address is Removed. Otherwise ,it is made into a Registered NCE*/ + if(reply->status!=0) + { + //Generating link local address with EUI-64 to send the NA + NA_DEST.s6_addr16[0] = htons(0xfe80); + for (i=0;i<8;i++) + NA_DEST.s6_addr[8+i] = NA_EUI.data[7-i]; + NA_DEST.s6_addr[8] ^= 0x2; + // printf("\n As it is duplicate we are removing the entry"); + call NeighbrCache.removeentry(neighbr->ip_address); + } + else + { + /* A router must not modify the Neighbor Cache as a result of receiving a DAC,unless there is a Tentative NCE matching the IPv6 address and EUI-64*/ + if(neighbr->info.type==TENTATIVE) + { + neighbr->info.timer=reply->reg_lifetime; + // printf("\n timer after changing state is %ld",neighbr->info.timer); + printf_buf(reply->eui64.data,8); + neighbr->info.type=REGISTERED; + neighbr->info.state=STALE; + } + /* This may be refreshing his entry with the router*/ + if(neighbr->info.type==REGISTERED) + { + neighbr->info.timer=reply->reg_lifetime; + neighbr->info.state=STALE; + } + } + sendNA(reply->status,NA_EUI,reply->reg_lifetime); + #endif + } + + event void NeighbrCache.prefixReg() + { + struct in6_addr def_rtr; + //printf("\n Prefix Registration is going to complete"); + #ifdef NODE_HOST + call RouterList.getRouterIP(&def_rtr); + #endif + #ifdef NODE_ROUTER + call NeighbrCache.getLBRAddress(&def_rtr); + #endif + RSSTATE=UNICAST; + sendMsg(def_rtr,RS); + call RSTimer.startOneShot(RSInterval); + //TODO: Get the Default Router and send a RS message to Him + + } + + event void NeighbrCache.NUD_reminder(struct in6_addr ip_address) + { + neighbr_cache *cache; + + //if(call Node.getHostState()) + //{ + NSSTATE=NUD; + //NODESTATE=HOST; //this is required because NS message will otherwise send the message to 6LBR.Has to chnge + // printf("\n The IP address for which reachability is checked:"); + cache=call NeighbrCache.findEntry(ip_address); + if(cache!=0) + { + cache->info.next_ndtime=RETRANSMISSION_TIME; //TODO:Change this + memcpy(&NS_DEST,&ip_address,sizeof(struct in6_addr)); + //printf_in6addr(&NS_DEST); + sendMsg(NS_DEST,NS); + } + + //} + } + + + default event void SplitControl.startDone(error_t error) + { + + } + + event void RadioControl.startDone(error_t error) + { + + + } + + default event void SplitControl.stopDone(error_t error) + { + } + + event void RadioControl.stopDone(error_t error) + { + signal SplitControl.stopDone(error); + } + + + event void IPAddress.changed(bool valid) + { + } + +/* This event will be signalled whenver the default rtr list is empty*/ + event void NeighbrCache.default_rtrlistempty() + { + #ifdef NODE_HOST + //printf("\nIn default rtr list event"); + RSSTATE=MULTICAST; + sendMsg(ALL_RTR_MULTICAST_ADDR,RS); + #endif + } + event void Ieee154Address.changed() { } +} + diff --git a/tos/lib/net/blip/Neighbr.h b/tos/lib/net/blip/Neighbr.h new file mode 100644 index 0000000000..43aae90280 --- /dev/null +++ b/tos/lib/net/blip/Neighbr.h @@ -0,0 +1,96 @@ + +#ifndef NEIGHBR_H +#define NEIGHBR_H + +#include "ND.h" + +/* Neighbor Cache (RFC 4861 Section 5.1) + + Description: Contains set of entries about individual neighbors to which traffic has been sent recently +*/ + + + +typedef struct neigbr_info_t { + uint8_t isRouter; //flag indicating whether the neighbor is Router or not + uint32_t next_ndtime; //Time after which the next Neighbor Unreachability Detection event is scheduled(millisec) + uint8_t type; //type of the neighbour cache entry such as TENTATIVE,REGISTERED + uint8_t state; //Reachability States such as REACHABLE,STALE,INCOMPLETE,DELAY and PROBE + uint32_t timer; //time upto which the neighbor is valid(secs) + uint8_t reserved; //checking any padding is required +}__attribute__((packed)) neighbr_info; + + +typedef struct neighbr_cache_t { + + struct in6_addr ip_address; //IPv6 address of the neighbour + ieee_eui64_t linklayer_addr; //link layer address of the neighbour + neighbr_info info; +}__attribute__((packed)) neighbr_cache; + +/* Default Router List(RFC 4861 Section 5.1) + + Description: Contains a set of entries of routers to which the packets may be sent.Router list Entries point to the entries in the Neighbor Cache.*/ + +typedef struct default_rtrlist_t { + neighbr_cache *rtr; //pointer to the neighbour cache entry +}__attribute__((packed)) default_rtrlist; + + +/*DAD Table(RFC 4861 Section 8.2.3) + Description: Table Maintained by the 6LBR. Each entry contains an IPv6 address(Registered Address in the DAR) ,EUI-64 and Registration Lifetime of the host */ + + +typedef struct dad_cache_t { + struct in6_addr ip_address; //registered address in the DAR + ieee_eui64_t linklayer_addr; + uint16_t reg_lifetime; +}__attribute__((packed)) dad_cache; + + +/* Storing Prefix Information */ + + +typedef struct { + prefix_info prefix_information; + abro_info abro_information; + uint8_t cid; + uint16_t context_lifetime; +}__attribute__((packed))prefix_list; + + + +#ifndef NEIGHBR_TABLE_SZ +#define NEIGHBR_TABLE_SZ 10 +#endif + + +#ifndef DAD_TABLE_SZ +#define DAD_TABLE_SZ 10 +#endif + +#ifndef PREFIX_TABLE_SZ +#define PREFIX_TABLE_SZ 3 +#endif + +#ifndef ROUTER_TABLE_SZ +#define ROUTER_TABLE_SZ 2 +#endif + +enum +{ + TENTATIVE=1, + REGISTERED=2, + GARBAGE_COLLECTIBLE=3, + NP=4, +}; + +/*TENTATIVE_NCE_LIFETIME: A Tentative NCE should be timed out TENTATIVE_NCE_LIFETIME seconds after it was created in order to +allow for another host to attempt to register the IPv6 Address*/ +#define TENTATIVE_NCE_LIFETIME 2 //2 Minutes +#define MAX_RTRS 2 +#endif + + + + diff --git a/tos/lib/net/blip/NeighbrCacheC.nc b/tos/lib/net/blip/NeighbrCacheC.nc new file mode 100644 index 0000000000..9e1966757f --- /dev/null +++ b/tos/lib/net/blip/NeighbrCacheC.nc @@ -0,0 +1,36 @@ + + +configuration NeighbrCacheC +{ + + provides interface NeighbrCache; + provides interface RouterList; + +} + + +implementation +{ + + components NeighbrCacheP as NP; + NeighbrCache=NP; + RouterList=NP; + + + components NoLedsC as LedsC; + NP.Leds->LedsC; + + + components new TimerMilliC() as Timer; + NP.Timer->Timer; + + components new TimerMilliC() as NUDTimer; + NP.NUDTimer->NUDTimer; + + components NodeC; + NP.Node->NodeC; + + + +} + diff --git a/tos/lib/net/blip/NeighbrCacheP.nc b/tos/lib/net/blip/NeighbrCacheP.nc new file mode 100644 index 0000000000..3736e0eb30 --- /dev/null +++ b/tos/lib/net/blip/NeighbrCacheP.nc @@ -0,0 +1,981 @@ + +#include "Neighbr.h" + +module NeighbrCacheP +{ + + provides interface NeighbrCache; + provides interface RouterList; + uses interface Leds; + uses interface Timer; + uses interface Timer as NUDTimer; + uses interface NeighborDiscovery; + uses interface Node; +} + + + +implementation +{ + + neighbr_cache neighbr_table[NEIGHBR_TABLE_SZ]; //neighbour table which contains entries of the neighbour to whom traffic is recently sent + + struct in6_addr null; + dad_cache dad_table[DAD_TABLE_SZ]; //dad Table which contains the registered entries + + default_rtrlist rtr_table[ROUTER_TABLE_SZ]; //default router list which contains the routers which can acts as default routers + uint8_t started=FALSE; + + uint8_t no_rtr; + + uint16_t count[NEIGHBR_TABLE_SZ]; + uint32_t NUD_REACHBLE_PERIOD; + prefix_list prefix_table[PREFIX_TABLE_SZ]; //list of prefixes + + #define compare_ipv6(node1, node2) (!memcmp((node1), (node2), sizeof(struct in6_addr))) + int alloc_index() + { + uint8_t i; + for(i=0;iip_address,sizeof(struct in6_addr)))) + { + return i; + } + } + return -1; + + } + + int findPrefix(struct in6_addr ip) + { + int i; + for(i=0;ineighbr_table[index].info.timer) + index=i; + } + } + } + return index; + + } + + + int findDAD(struct in6_addr ip) + { + + uint8_t i; + for(i=0;iip_address); + printf("\t\t\t\t"); + printf("%ld\n",rtr_table[i].rtr->info.timer); + } + } + */ + } + + command error_t NeighbrCache.init() + { + + uint8_t i; + + /*clearing the Neighbor Table*/ + for(i=0;iNEIGHBR_TABLE_SZ-1||index==-1) //it means the Neighbour cache is Full + return FAIL; + + if(call NeighbrCache.findIPEUI64(ip,lladdr)) //dont add duplicates + { + //printf("\n Neighbor add entry Returning FAIL because ip and link layer address already exist"); + return FAIL; + } + + if((i=findEUI(lladdr))!=-1&&neighbr_table[i].info.type==TENTATIVE) //overwriting tentative entries + { + + index=i; + } + + if(info.isRouter) //if Router + { + + /* To limit the storage needed for the default router list, a host may choose not to store all of the router addresses discovered via advertisements*/ + if(no_rtr>MAX_RTRS-1) + return FAIL; + no_rtr++; + } + + memcpy(&neighbr_table[index].ip_address,&ip,sizeof(struct in6_addr)); + memcpy(&neighbr_table[index].linklayer_addr,&lladdr,sizeof(ieee_eui64_t)); + memcpy(&neighbr_table[index].info,&info,sizeof(neighbr_info)); + + call NeighbrCache.PrintTable(); + + return SUCCESS; + } + + + command error_t NeighbrCache.removeentry(struct in6_addr ip) //remove after completion + { + int i; + i=find(ip); + + + if(i==-1) + return NP; //entry is not present in the neighbour table + else + { + //printf("\n NeighborCache Removeentry"); + //printf_in6addr(&neighbr_table[i].ip_address); + memset(&neighbr_table[i],0,sizeof(neighbr_cache)); + return SUCCESS; + } + + + + } + + command error_t NeighbrCache.delEntry(uint8_t i) + { + + call NeighbrCache.PrintTable(); + //printf("\n Deleting Neighbor Cache Entry index:%d",i); + memset(&neighbr_table[i].ip_address,0,16); + memset(&neighbr_table[i].linklayer_addr,0,8); + memset(&neighbr_table[i].info,0,sizeof(neighbr_info)); + call NeighbrCache.PrintTable(); + return SUCCESS; + } + + + + command error_t NeighbrCache.resolveIP(struct in6_addr *ip,ieee154_addr_t * linkaddr) + { + int i; + i=find(*ip); + //call Leds.led1Toggle(); + if(i==-1) + return NP; //entry is not present in the neighbour table + else + { + //printf("\n resolving ip"); + memcpy(&linkaddr->i_laddr.data,&neighbr_table[i].linklayer_addr,8); + linkaddr->ieee_mode=IEEE154_ADDR_EXT; + return SUCCESS; + } + } + + /* Returns 0 when no entry is present else returns the address of the entry*/ + command neighbr_cache * NeighbrCache.getEntryLL(ieee_eui64_t link_addr) + { + int i; + i=findEUI(link_addr); + if(i!=-1) + return &neighbr_table[i]; + else + return 0; + } + + + /* Returns 0 when no entry is present else returns the address of the entry */ + + command neighbr_cache * NeighbrCache.findEntry(struct in6_addr ip) + { + + int i; + i=find(ip); + if(i==-1) + return 0; + else + return &neighbr_table[i]; + } + //returns 1 when ip and link layer address are found else returns 0 + command int NeighbrCache.findIPEUI64(struct in6_addr ip,ieee_eui64_t link_addr) + { + int i,j; + i=find(ip); + j=findEUI(link_addr); + if(i==j&&i!=-1) + return 1; + else + return 0; + } + + + command void NeighbrCache.PrintTable() + { + + /*uint8_t i; + + printf("\n NeighborCache of the Node"); + + printf("\n State\t\t\tTime Left\t\t IPAddress:\t\t\t\t LinkLayerAddress \n"); + for(i=0;iDAD_TABLE_SZ-1) + return FAIL; + + if(call NeighbrCache.DADfindIPEUI64(ip,lladdr)!=-1) //dont add duplicates + { + //printf("\n DAD addentry Returning FAIL because ip and link layer address already exist"); + return FAIL; + } + + if((i=DADfindEUI(lladdr))!=-1) //overwriting tentative entries + { + index=i; + } + + + memcpy(&dad_table[index].ip_address,&ip,sizeof(struct in6_addr)); + memcpy(&dad_table[index].linklayer_addr,&lladdr,sizeof(ieee_eui64_t)); + dad_table[index].reg_lifetime=reg_lifetime; + + //printf("\n IPAddress registered in the DAD"); + //printf_in6addr(&ip); + return SUCCESS; + + } + + command error_t NeighbrCache.DADremoveEntry(struct in6_addr ip) + { + + int index=findDAD(ip); + if(index==-1) + return NP; + else{ + //printf("\n DAD Removing entry"); + //printf_in6addr(&dad_table[index].ip_address); + memset(&dad_table[index],0,sizeof(dad_table[index])); + return SUCCESS; + } + } + + /* Returns 0 when the entry is not found or else returns 1 */ + + command int NeighbrCache.DADfindEntry(struct in6_addr ip) + { + + int index; + index=findDAD(ip); + //printf("\n findDAD index is %d",index); + if(index==-1) + return 0; + else + return 1; + + } + + + /*return i when both IP and EUI-64 are present else returns -1 */ + command int NeighbrCache.DADfindIPEUI64(struct in6_addr ip,ieee_eui64_t link_addr) + { + + int i; + if(call NeighbrCache.DADfindEntry(ip)) + { + i=findDAD(ip); //to get the index of the ip + //printf("\n Source Comparison Link Layer Address"); + //printf_buf(link_addr.data,8); + //printf("\n Destination Comparison Link Layer Address"); + //printf_buf(dad_table[i].linklayer_addr.data,8); + if(!memcmp(&link_addr,&dad_table[i].linklayer_addr,sizeof(link_addr))) + { + return i; + } + else + return -1; + } + else + { + return -1; + } + + } + + command dad_cache * NeighbrCache.getDADEntry(uint8_t index) + { + return &dad_table[index]; + + } + + event void Timer.fired() //working in minutes only + { + uint8_t i; + if(no_rtr==0) + { + //printf("\n Signalling the node that routers are zero"); + #ifndef NODE_LBR //LBR should not receive this event ... + signal NeighbrCache.default_rtrlistempty(); + #endif + + } + for(i=0;i0;i++) + { + prefix_table[i].prefix_information.preferrd_lifetime-=1; + prefix_table[i].abro_information.valid_lifetime-=1; + if(prefix_table[i].prefix_information.preferrd_lifetime<4 && + prefix_table[i].prefix_information.preferrd_lifetime>2) + signal NeighbrCache.prefixReg(); + + /*when the prefix information times out ,the information of the prefix should be discarded + */ + if(prefix_table[i].prefix_information.preferrd_lifetime<=0) + { + memset(&prefix_table[i].prefix_information,0,sizeof(prefix_info)); + + } + /*When the ABRO valid lifetime associated with a 6lbr times out,all information related to that 6LBR Must be removed*/ + if(prefix_table[i].abro_information.valid_lifetime<=0) + { + memset(&prefix_table[i],0,sizeof(prefix_list)); + } + } + } + command error_t NeighbrCache.startNUD() + { + struct in6_addr def_rtr_ip; + int i; + if(!call NUDTimer.isRunning()) + { + call NUDTimer.stop(); + + } + + if(call Node.getLBRState()) + { + NUD_REACHBLE_PERIOD=RTR_REACHABLE_TIME; + call NUDTimer.startPeriodic(1000); + return SUCCESS; + } + else + { + if(call RouterList.getRouterIP(&def_rtr_ip)==SUCCESS) + { + i=find(def_rtr_ip); + if(NUD_REACHBLE_PERIOD==neighbr_table[i].info.next_ndtime*60) + { + //printf("\nNUD Mechanism has not been started as it is the same ip"); + } + else + { + NUD_REACHBLE_PERIOD=neighbr_table[i].info.next_ndtime*60;//converting into seconds + //printf("\nNUD Mechanism has been started"); + call NUDTimer.startPeriodic(1000); //1 Second + } + + return SUCCESS; + } + } + + return FAIL; + } + + + event void NUDTimer.fired() + { + + uint8_t i; + for(i=0;i0;i++) + { + count[i]++; + if(neighbr_table[i].info.state==PROBE) + { + //after Maximum unicast solicitation delete entry + if(count[i]*1000==MAX_UNICAST_SOLICIT*RETRANS_TIMER){ + call NeighbrCache.delEntry(i); + //printf("\n Deleting entry because neighbor is not reachable"); + count[i]=0; + } + } + if(neighbr_table[i].info.state==DELAY) + { + neighbr_table[i].info.state=PROBE; + //printf("\n Changing state of %d to PROBE",i); + signal NeighbrCache.NUD_reminder(neighbr_table[i].ip_address); + count[i]=0; + } + if(neighbr_table[i].info.state==STALE) + { + //printf("comparing count:%ld and DElAY:%ld",count[i],DELAY_FIRST_PROBE_TIME); + if(count[i]*1000==DELAY_FIRST_PROBE_TIME) + { + //printf("\n changing state of %d to DELAY",i); + neighbr_table[i].info.state=DELAY; + count[i]=0; + } + } + if(neighbr_table[i].info.state==REACHABLE) + { + if(NUD_REACHBLE_PERIOD==count[i]) + { + //printf("\n changing the state of %d to STALE",i); + neighbr_table[i].info.state=STALE; + count[i]=0; + } + } + + + + } + //call NeighbrCache.PrintTable(); + + } + + + command error_t NeighbrCache.storeCtx(struct in6_addr prefix,uint8_t cid,uint16_t lifetime) + { + + int i=findPrefixIndex(prefix); + if(i!=-1) + { + //printf("\n storing the context in index:%d",i); + prefix_table[i].cid=cid; + prefix_table[i].context_lifetime=lifetime; + return SUCCESS; + } + return FAIL; + } + + //get the ip address based on the context + command int NeighbrCache.getContext(uint8_t context,struct in6_addr *ctx) + { + + /* if (!(call IPAddress.getGlobalAddr(&me))) return 0; + if (context == 0) { + // memset(ctx->s6_addr, 0, 8); + // ctx->s6_addr16[0] = htons(0xaaaa); + memcpy(ctx->s6_addr, me.s6_addr, 8); + return 64; + } else { + return 0; + }*/ + int i = findCtx(context); + if(i!=-1) + { + memcpy(ctx->s6_addr,prefix_table[i].prefix_information.prefix.s6_addr,8); + return 64; + }else{ + return 0; + } + + + } + + + //get the LBR Address + + command error_t NeighbrCache.getLBRAddress(struct in6_addr *lbr) + { + + memcpy(lbr,&prefix_table[0].abro_information.lbr_addr,sizeof(struct in6_addr)); + return SUCCESS; + + + } + + //used to get the context based on the ip address + command int NeighbrCache.matchContext(struct in6_addr *ctx,uint8_t *context) + { + + int i=findPrefixIndex(*ctx); + if(i!=-1) + { + *context=prefix_table[i].cid; + return 64; + } + return 0; + + + + } + + command error_t NeighbrCache.addPrefix(prefix_info prefix_information,abro_info info) + { + + int i; + //check whether we have to update it + i=findPrefix(info.lbr_addr); + if(i==-1) + { + for(i=0;iPREFIX_TABLE_SZ-1) + return FAIL; + } + memcpy(&prefix_table[i].prefix_information,&prefix_information,sizeof(prefix_info)); + memcpy(&prefix_table[i].abro_information,&info,sizeof(abro_info)); + //printf("\n Prefix successfully added"); + return SUCCESS; + + + } + +/* Return Success When no entry exist with the same info or returns FAIL*/ +command error_t NeighbrCache.checkPrefix(struct in6_addr prefix,struct in6_addr lbr_addr,uint16_t ver_high,uint16_t ver_low) +{ + uint8_t i; + for(i=0;i<=PREFIX_TABLE_SZ-1;i++) + { + + if(!(memcmp(&prefix,&prefix_table[i].prefix_information.prefix,sizeof(struct in6_addr))) && + !(memcmp(&lbr_addr,&prefix_table[i].abro_information.lbr_addr,sizeof(struct in6_addr))) && + (ver_high==prefix_table[i].abro_information.ver_high) &&(ver_low==prefix_table[i].abro_information.ver_low)) + { + break; + } + + + } + + if(i>PREFIX_TABLE_SZ-1) + { + //printf("\n Return SUCCESS"); + return SUCCESS; + } + //printf("\n Return FAIL"); + //check whether the prefix lifetime is going to complete if so then update it + if((prefix_table[i].prefix_information.preferrd_lifetime>0 && prefix_table[i].prefix_information.preferrd_lifetime<=4)|| + (prefix_table[i].abro_information.valid_lifetime>0&&prefix_table[i].abro_information.valid_lifetime<=4)) + return SUCCESS; + else + return FAIL; + +} + + + + command uint8_t NeighbrCache.prefixes_count() + { + uint8_t i,prefix_count=0; + for(i=0;iPREFIX_TABLE_SZ-1) + return FAIL; + else + { + memset(&prefix_table[i],0,sizeof(prefix_list)); + return SUCCESS; + } + + } + + + command prefix_list * NeighbrCache.getPrefixIndex(uint8_t index) + { + + if(index>PREFIX_TABLE_SZ-1) + return 0; + else return &prefix_table[index]; + } + +/************************************RouterList Commands and Interfaces*********************************************************/ + + + command error_t RouterList.add(struct in6_addr ip) + { + int i,j; + i=router_index(); + if(i!=-1) + { + j=find(ip); + if(j==-1) + { + //printf("\n Cannot be added to the default router list as no entry exists in the neighbor cache");printfflush(); + return FAIL; + } + else + { + rtr_table[i].rtr=&neighbr_table[j]; + return SUCCESS; + } + } + else + return FAIL; + + } + + command error_t RouterList.remove(struct in6_addr rtr_ip) + { + int i; + //printf("\n Removing the router ip:"); + //printf_in6addr(&rtr_ip); + i=findRouter(rtr_ip); + if(i==-1||i>MAX_RTRS){ + return FAIL; + } + memset(&rtr_table[i],0,sizeof(default_rtrlist)); + no_rtr--; + //printf("\n No. of Routers present are:%d",no_rtr); + return SUCCESS; + } + + command error_t RouterList.getRouterIP(struct in6_addr *ip) + { + //printf("\n Router IP"); + if(rtr_table[0].rtr->info.timer!=0) + { + *ip=rtr_table[0].rtr->ip_address; + //printf_in6addr(ip); + return SUCCESS; + } + if(!compare_ipv6(&rtr_table[1].rtr->ip_address,&null)) + { + *ip=rtr_table[1].rtr->ip_address; + return SUCCESS; + } + return FAIL; + + } + + + command error_t RouterList.removeAll() + { + memset(&rtr_table,0 ,sizeof(rtr_table[ROUTER_TABLE_SZ])); + no_rtr=0; + return SUCCESS; + } + +} + diff --git a/tos/lib/net/blip/OptionC.nc b/tos/lib/net/blip/OptionC.nc new file mode 100644 index 0000000000..a431d1444d --- /dev/null +++ b/tos/lib/net/blip/OptionC.nc @@ -0,0 +1,60 @@ + +module OptionC{ + +provides interface Option; + +} + + +implementation +{ + command int Option.length_opt(uint8_t search_type) + { + if(search_type==SLLAO||search_type==TLLAO) + return sizeof(stlla_opt); + else if(search_type==PREFIX_INFORMATION) + return sizeof(prefix_opt); + else if(search_type==ARO) + return sizeof(aro_opt); + else if(search_type==CONTEXT_0PTION) + return sizeof(context_opt); + else if(search_type==ABRO) + return sizeof(abro_opt); + return 0; + + + } + + + + command uint8_t * Option.findoption(void *payload,uint8_t first_type,uint8_t search_type) + { //first_type contains the length of the message in which option is present + uint8_t *ptr=(uint8_t *)payload+first_type+LENGTH_ICMPHEADER; + + first_type=*ptr; + while(search_type!=first_type) + { + uint8_t length=call Option.length_opt(first_type); + if(length==0) + break; + ptr=ptr+length; + first_type=*ptr; + + } + if(search_type==*ptr) + { + payload=ptr; + return ptr; + } + else + return 0; + + } + + command uint8_t * Option.ptrMsg(void *payload) + { + uint8_t *ptr=(uint8_t *)payload;//+LENGTH_ICMPHEADER; + return ptr; + } + } + diff --git a/tos/lib/net/blip/interfaces/IPAddress.nc b/tos/lib/net/blip/interfaces/IPAddress.nc index 40bc2f6a8b..0082549100 100644 --- a/tos/lib/net/blip/interfaces/IPAddress.nc +++ b/tos/lib/net/blip/interfaces/IPAddress.nc @@ -51,6 +51,10 @@ interface IPAddress { command error_t removeAddress(); + /* Get the link-local Address of the node with the interface identifier be taken from the EUI-64 */ + + command bool getEUILLAddress(struct in6_addr *addr); + event void changed(bool valid); } diff --git a/tos/lib/net/blip/interfaces/MinuteTimer.nc b/tos/lib/net/blip/interfaces/MinuteTimer.nc new file mode 100644 index 0000000000..fc0289d21a --- /dev/null +++ b/tos/lib/net/blip/interfaces/MinuteTimer.nc @@ -0,0 +1,12 @@ +/*Interface File*/ + + +interface MinuteTimer +{ + + command error_t startOneShot(uint16_t minutes); + + event void fired(); + +} + diff --git a/tos/lib/net/blip/interfaces/NeighbrCache.nc b/tos/lib/net/blip/interfaces/NeighbrCache.nc new file mode 100644 index 0000000000..1bfd664f55 --- /dev/null +++ b/tos/lib/net/blip/interfaces/NeighbrCache.nc @@ -0,0 +1,73 @@ + +#include "Neighbr.h" +interface NeighbrCache +{ + + command error_t init(); + + + command error_t getLBRAddress(struct in6_addr *lbr); + + command error_t storeCtx(struct in6_addr prefix,uint8_t cid,uint16_t lifetime); + + command int getContext(uint8_t context,struct in6_addr *ctx); + + command int matchContext(struct in6_addr *ctx,uint8_t *context); + + command error_t addentry(struct in6_addr ip,ieee_eui64_t lladdr,neighbr_info info); + + command error_t removeentry(struct in6_addr ip); + + command error_t delEntry(uint8_t i); + + command error_t resolveIP(struct in6_addr *ip,ieee154_addr_t * linkaddr); + + command neighbr_cache * findEntry(struct in6_addr ip); + + command neighbr_cache * getEntryLL(ieee_eui64_t link_addr); + + + command int findIPEUI64(struct in6_addr ip,ieee_eui64_t link_addr); + + command void PrintTable(); + + command void PrintDADTable(); + + command error_t updateEntry(struct in6_addr ip,ieee_eui64_t lladdr,neighbr_info info); + + command neighbr_cache * getEntry(uint8_t index); + + command error_t DADaddEntry(struct in6_addr ip,ieee_eui64_t lladdr,uint16_t reg_lifetime); + + command error_t DADremoveEntry(struct in6_addr ip); + + command int DADfindEntry(struct in6_addr ip); + + command int DADfindIPEUI64(struct in6_addr ip,ieee_eui64_t link_addr); + + command dad_cache * getDADEntry(uint8_t index); + + command error_t checkPrefix(struct in6_addr prefix,struct in6_addr lbr_addr,uint16_t ver_high,uint16_t ver_low); + + command error_t addPrefix(prefix_info prefix_information,abro_info info); + + command error_t removePrefix(struct in6_addr prefix); + + event void prefixReg(); + + command uint8_t prefixes_count(); + + command prefix_list * getPrefixIndex(uint8_t index); + + + + event void default_rtrlistempty(); + + event void NUD_reminder(struct in6_addr ip_address); + + command error_t startNUD(); + + + +} + diff --git a/tos/lib/net/blip/interfaces/Option.nc b/tos/lib/net/blip/interfaces/Option.nc new file mode 100644 index 0000000000..587b8c1e76 --- /dev/null +++ b/tos/lib/net/blip/interfaces/Option.nc @@ -0,0 +1,14 @@ + + +interface Option{ + + + + +command int length_opt(uint8_t search_type); //gives the length of each option + +command uint8_t * findoption(void *payload,uint8_t first_type,uint8_t search_type); + +command uint8_t * ptrMsg(void *payload); + +} diff --git a/tos/lib/net/blip/interfaces/RouterList.nc b/tos/lib/net/blip/interfaces/RouterList.nc new file mode 100644 index 0000000000..2b7337820c --- /dev/null +++ b/tos/lib/net/blip/interfaces/RouterList.nc @@ -0,0 +1,18 @@ + + +interface RouterList +{ + + + /* Add an entry into the Router List*/ + command error_t add(struct in6_addr ip); + + command error_t remove(struct in6_addr ip); + + command error_t getRouterIP(struct in6_addr *ip); + + command error_t removeAll(); + + + +} diff --git a/tos/system/NodeC.nc b/tos/system/NodeC.nc new file mode 100755 index 0000000000..a4baa96b35 --- /dev/null +++ b/tos/system/NodeC.nc @@ -0,0 +1,17 @@ +/* +@author Md.Jamal +@version $Revision: 1.0 + +*/ + +configuration NodeC +{ + + provides interface Node; +} + +implementation { + + components NodeP; + Node=NodeP; +} diff --git a/tos/system/NodeP.nc b/tos/system/NodeP.nc new file mode 100755 index 0000000000..28f5cecd69 --- /dev/null +++ b/tos/system/NodeP.nc @@ -0,0 +1,60 @@ +/* +@author Md.Jamal +@version $Revision: 1.0 + +*/ +//#include "printf.h" +module NodeP +{ + + provides interface Node; + +} + + +implementation +{ + bool Router=FALSE; + bool LBR=FALSE; + bool HOST=FALSE; + command void Node.setHost() + { + //printf("\n Node is set as Host"); + HOST=TRUE; + } + + command bool Node.getHostState() + { + return HOST; + + } + + command void Node.unsetHost() + { + //printf("\n Not a HOST now"); + HOST=FALSE; + } + command void Node.setRouter() + { + //printf("\n Node is set as Router"); + Router=TRUE; + } + + command bool Node.getRouterState() + { + + return Router; + } + + command void Node.setLBR() + { + //printf("\n Node is set as LBR"); + LBR=TRUE; + } + + command bool Node.getLBRState() + { + return LBR; + } + +} From 746b935ab87818edd384e7dcd0dcd46f6c50bfd3 Mon Sep 17 00:00:00 2001 From: "md.jamal" Date: Wed, 20 Aug 2014 13:01:09 +0530 Subject: [PATCH 2/2] Closing brace error --- tos/lib/net/blip/IPAddressP.nc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tos/lib/net/blip/IPAddressP.nc b/tos/lib/net/blip/IPAddressP.nc index 101a1893ce..7b1de868de 100644 --- a/tos/lib/net/blip/IPAddressP.nc +++ b/tos/lib/net/blip/IPAddressP.nc @@ -177,10 +177,10 @@ module IPAddressP { event void Ieee154Address.changed() {} -} -command bool IPAddress.getEUILLAddress(struct in6_addr *addr) -{ + + command bool IPAddress.getEUILLAddress(struct in6_addr *addr) + { int i; ieee154_laddr_t laddr = call Ieee154Address.getExtAddr();//getting the Extended Address @@ -191,4 +191,5 @@ command bool IPAddress.getEUILLAddress(struct in6_addr *addr) addr->s6_addr[8+i] = laddr.data[7-i]; addr->s6_addr[8] ^= 0x2; /* toggle U/L bit */ return TRUE; + } }