1 / 52

#4 : Wireless Forwarding Ad-hoc Network with Flooding, Gossiping, LEACH Protocols

Ubiquitous Sensor Networks. Ubiquitous Sensor Networks. #4 : Wireless Forwarding Ad-hoc Network with Flooding, Gossiping, LEACH Protocols (Hanback’s zigbeX & TinyOS ver.1.1.7). 2007. 3. 23. DoHyun. Ji. Contents. 2. 3. 1. Gossiping Protocol. LEACH Protocol. Flooding Protocol.

candy
Download Presentation

#4 : Wireless Forwarding Ad-hoc Network with Flooding, Gossiping, LEACH Protocols

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ubiquitous Sensor Networks Ubiquitous Sensor Networks #4 : Wireless Forwarding Ad-hoc Network with Flooding, Gossiping, LEACH Protocols (Hanback’s zigbeX & TinyOS ver.1.1.7) 2007. 3. 23 DoHyun. Ji

  2. Contents 2 3 1 Gossiping Protocol LEACH Protocol Flooding Protocol

  3. 1. Flooding Protocol • Ad-hoc Network • 특정 목적지로 데이터 전송을 위해 각 노드가 자유로운 망을 형성 • 형성된 망을 통해 목적지 노드로 데이터 포워딩, 멀티홉 통신의 구현 • 특정 AP나 기지국이 불필요하여 설치 및 운영이 간편 • Flooding Protocol • 패킷 전송은 항상 Broadcast 형태로 진행 • Implosion – Sequence Number for each Packet • TTL(Time to Live) – Hop Limit • 실제 사용은 최초 라우팅 경로 설정용(RIP와 유사) • 같은 패킷을 두 번 이상 수신할 수 있음(Overlap) • 각 노드의 RF 출력에 의존 • 목적 노드가 데이터를 수신했음에도 계속 포워딩될 수 있음 • 많은 전력 소모

  4. 1. Flooding Protocol • Configuration – TempMon.nc • Makefile includes TempMon; includes MH; configuration TempMon{ } Implementation { components Main, TempMonM, TimerC, Temp, GenericComm as Comm,QueuedSend, SimpleTime, #ifdef FLOODING // FLOODING 이 define 된 경우 MHFloodingRouter as Router; #endif #ifdef GOSSIPING MHGossipingRouter as Router; #endif #ifdef LEACH MHLeachRouter as Router; #endif COMPONENT=TempMon SENSORBOARD=basicsb PFLAGS= -I. -I./Queue -DFLOODING -DSIM=10 include ../../../../apps/Makerules

  5. 1. Flooding Protocol • Configuration – TempMon.nc (con’d) & headers Main.StdControl -> TempMonM.StdControl; Main.StdControl -> Router.StdControl; // 라우팅 프로토콜 연결 Main.StdControl -> Comm.Control; Main.StdControl -> QueuedSend.StdControl; Main.StdControl -> Temp.StdControl; Main.StdControl -> TimerC.StdControl; Main.StdControl -> SimpleTime.StdControl; TempMonM.ADC -> Temp.TempADC; TempMonM.Timer -> TimerC.Timer[unique("Timer")]; TempMonM.Send -> Router.Send[AM_TEMPMONMSG]; // 전송 컴포넌트 연결 TempMonM.GlobalTime -> Router.GlobalTime; Router.ReceiveMsg[AM_TEMPMONMSG] -> Comm.ReceiveMsg[AM_TEMPMONMSG]; } /* tempMon.h */ enum { TIMER_RATE = 5000, // Send a message every 5 seconds AM_TEMPMONMSG = 10, }; typedef struct TempMonMsg { uint16_t address; uint32_t timestamp; uint16_t reading; } __attribute__ ((packed)) TempMonMsg; /* MH.h */ ... FLOODING_MAX_HOP_COUNT = 100, FLOODING_LOG_LENGTH = 250, ... /* MH.h */ typedef struct MHMessage { uint16_t sendingNode; uint16_t originNode; uint16_t seqNo; uint16_t hopCount; uint8_t data[(TOSH_DATA_LENGTH - 8)]; } __attribute__ ((packed)) MHMessage;

  6. 1. Flooding Protocol • Module – TempMonM.nc includes TempMon; module TempMonM { provides { interface StdControl; } uses { interface Send; interface ADC; interface Timer; interface GlobalTime; } } implementation { norace uint16_t sensorReading; // 각 센싱 프로세스를 고정 bool sendBusy; // 전송 상태 변수 TOS_Msg mhMsg; // 전송될 데이터의 메시지 타잎 command result_t StdControl.init(){ ... } command result_t StdControl.start() { call ADC.getData(); // ADC 읽어오기 return call Timer.start(TIMER_REPEAT, TIMER_RATE); } event result_t Timer.fired(){ call ADC.getData(); // ADC 읽어오기 // 모든 노드의 글로벌 시간이 동기화 되었을때만 전송 if (call GlobalTime.isSynchronised() == SUCCESS) { post sendData(); } return SUCCESS; }

  7. 1. Flooding Protocol • Module – TempMonM.nc (con’d) task void sendData() { uint16_t length; TempMonMsg *pDataMsg = (TempMonMsg *) call Send.getBuffer(&mhMsg, &length); // 전송중에는 보내지 않음 if (sendBusy == TRUE) { return; } // 전송용 메시지에 데이터 담기 pDataMsg->address = TOS_LOCAL_ADDRESS; pDataMsg->timestamp = call GlobalTime.getGlobalTime(); pDataMsg->reading = sensorReading; // 실제 전송 if ((call Send.send(&mhMsg, sizeof(TempMonMsg))) == SUCCESS) { atomic sendBusy = TRUE; dbg(DBG_TEMP, "TempMonM - Message sent successfully\n"); } else { dbg(DBG_TEMP, "TempMonM - Message not sent\n"); } }

  8. 1. Flooding Protocol • Configuration – MHFloodingRouter.nc includes MH; configuration MHFloodingRouter{ provides { interface StdControl; interface Receive[uint8_t id]; // 수신용 인터페이스 interface Send[uint8_t id]; interface Intercept[uint8_t id]; interface GlobalTime; // 각 모트가 sync 해야할 글로벌 타임 } uses { interface ReceiveMsg[uint8_t id]; } } implementation { components MHEngineM, MHFloodingPSM, GenericComm as Comm, QueuedSend, TimerC, SimpleTime, TimeSyncM, LedsC; StdControl = MHEngineM.StdControl; // 멀티홉에 필수적인 MHEngine, 기타 컴포넌트들 Receive = MHEngineM.Receive; // 모든 인터페이스를 멀티홉 처리를 담당하는 MHEngine에 연결 Send = MHEngineM.Send; ReceiveMsg = MHEngineM.ReceiveMsg; Intercept = MHEngineM.Intercept; GlobalTime = TimeSyncM.GlobalTime; MHEngineM.CommStdControl -> Comm.Control;

  9. 1. Flooding Protocol • Configuration – MHFloodingRouter.nc (con’d) #ifdef SIM MHEngineM.SimTimer -> TimerC.Timer[unique("Timer")]; #endif MHEngineM.SubControl -> QueuedSend.StdControl; MHEngineM.SendMsg -> QueuedSend.SendMsg; MHEngineM.SubControl -> MHFloodingPSM.StdControl; MHEngineM.RouteSelect -> MHFloodingPSM.RouteSelect; // Flooding 프로토콜이 구현된 MHFlooingPSM 에 연결 MHEngineM.Leds -> LedsC.Leds; TimeSyncM.Leds -> LedsC.Leds; // LED MHEngineM.SubControl -> TimeSyncM.StdControl; TimeSyncM.Timer -> TimerC.Timer[unique("Timer")]; // Timer TimeSyncM.Time -> SimpleTime.Time; TimeSyncM.ReceiveMsg -> Comm.ReceiveMsg[AM_TIMESYNC]; // 수신한 메시지 큐 TimeSyncM.SendMsg -> QueuedSend.SendMsg[AM_TIMESYNC]; // 보낼 메시지 큐 MHEngineM.GlobalTime -> TimeSyncM.GlobalTime; // 노드간의 sync를 위한 변수 }

  10. 1. Flooding Protocol • Module – MHFloodingPSM.nc (con’d) includes AM; includes MH; module MHFloodingPSM{ provides { interface StdControl; interface RouteSelect; } } // RouteSelect 인터페이스 사용 implementation{ typedef struct LogEntry{ uint16_t id; // 로그 기록용 구조체 uint16_t seqno; // seq 번호 } LogEntry; enum{ MAX_HOP_COUNT = FLOODING_MAX_HOP_COUNT, // 최대 Hop count 설정 MAX_SEQ_NO = 30000, // 최대 Sequence 번호 설정 LOG_LENGTH = FLOODING_LOG_LENGTH // 최대 Log 길이 설정 }; uint16_t seqNo; // Sequence 번호 변수 LogEntry messageLog[LOG_LENGTH]; // 로그 기록용 구조체 배열 uint16_t entries; // 로그 엔트리 개수 기록 변수 uint16_t index; // 로그 기록용 인덱스 변수

  11. 1. Flooding Protocol • Module – MHFloodingPSM.nc (con’d) static uint16_t getSeqNo() { // 다음 Sequence 번호 가져오기 uint16_t temp = seqNo++; seqNo = seqNo % MAX_SEQ_NO; return temp; } static void addLogEntry(uint16_t id, uint16_t seqno) { // 새로운 로그 기록 if (entries < LOG_LENGTH) { entries++; } messageLog[index].id = id; messageLog[index++].seqno = seqno; index = index % LOG_LENGTH; } static bool inLog(uint16_t id, uint16_t seqno) { // 로그 검색, 기존에 전송한 패킷인지 검사 int i; for (i = 0; i < entries; i++) { if ((messageLog[i].id == id) && (messageLog[i].seqno == seqno)) { return TRUE; } } return FALSE; }

  12. 1. Flooding Protocol • Module – MHFloodingPSM.nc (con’d) command result_t StdControl.init() { seqNo = 0; entries = 0; index = 0; // 각 변수 초기화 return SUCCESS; } command result_t StdControl.start() { return SUCCESS; } command result_t StdControl.stop() { return SUCCESS; } command bool RouteSelect.isActive() { return TRUE; // Flooding 이 진행중일때는 항상 True 리턴 } command result_t RouteSelect.initializeFields(TOS_MsgPtr msg, uint8_t id) { // 새로운 패킷의 초기화 ( 목적지 주소, 홉 Count 기록) MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; pMHMsg->originNode = pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; pMHMsg->hopCount = 0; return SUCCESS; }

  13. 1. Flooding Protocol • Module – MHFloodingPSM.nc (con’d) command result_t RouteSelect.selectRoute(TOS_MsgPtr msg, uint8_t id){ MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; // 데이터를 메시지 구조체에 저장 if ((pMHMsg->originNode == TOS_LOCAL_ADDRESS) && (pMHMsg->hopCount == 0)) { pMHMsg->seqNo = getSeqNo(); // 패킷이 local 노드에서 생성된 경우 } else if (inLog(pMHMsg->originNode, pMHMsg->seqNo) == FALSE) { pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; // 패킷이 다른 노드에서 전달 되어온 경우 pMHMsg->hopCount++; /// 홉 증가 } else { // 비정상 패킷 dbg(DBG_TEMP, "MHFloodingPSM - Failed to select route for duplicate packet\n"); return FAIL; } if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) { msg->addr = TOS_UART_ADDR; // 자신이 sink(수집) 노드인경우 메시지의 목적지 주소를 UART(Serial)로 변경 } else { msg->addr = TOS_BCAST_ADDR; // 그 외는 Broadcast } if (pMHMsg->hopCount < MAX_HOP_COUNT || msg->addr == TOS_UART_ADDR) { addLogEntry(pMHMsg->originNode, pMHMsg->seqNo); // TTL이 유효하거나, 자신이 sink노드인경우 로그에 추가 dbg(DBG_TEMP, "MHFloodingPSM - Route selected\n"); return SUCCESS; } dbg(DBG_TEMP, "MHFloodingPSM - Failed to select route\n"); // 위의 경우에 속하지 않으면(TTL이 만료) return FAIL; // 패킷 폐기 }

  14. 1. Flooding Protocol • Result – Run TinyViz using double cygwin windows • On first cygwin window • On Second cygwin window (after executing #1)

  15. 1. Flooding Protocol • Result (con’d) - TinyViz

  16. 2. Gossiping Protocol • Gossiping Protocol • Many Problems in Flooding Protocol • 확률적 패킷 전송 • 1Hop 이내에 Advertise 패킷 전송 • Unicast Packet Forwarding • Best Case : 최소 노드를 거쳐서 패킷 전송 • Worst Case : 패킷의 손실 • Multi-Advertise 패킷 기법 • Delivery Ratio 고려(Flooding ≥ Gossiping)

  17. 2. Gossiping Protocol • Configuration – TempMon.nc • Makefile includes TempMon; includes MH; configuration TempMon{ } Implementation { components Main, TempMonM, TimerC, Temp, GenericComm as Comm,QueuedSend, SimpleTime, #ifdef FLOODING MHFloodingRouter as Router; #endif #ifdef GOSSIPING // GOSSIPING 이 define 된 경우 MHGossipingRouter as Router; #endif #ifdef LEACH MHLeachRouter as Router; #endif COMPONENT=TempMon SENSORBOARD=basicsb PFLAGS= -I. -I./Queue -DGOSSIPING -DSIM=10 include ../../../../apps/Makerules

  18. 2. Gossiping Protocol • Configuration – TempMon.nc (con’d) & headers Main.StdControl -> TempMonM.StdControl; Main.StdControl -> Router.StdControl; // 라우팅 프로토콜 연결 Main.StdControl -> Comm.Control; Main.StdControl -> QueuedSend.StdControl; Main.StdControl -> Temp.StdControl; Main.StdControl -> TimerC.StdControl; Main.StdControl -> SimpleTime.StdControl; TempMonM.ADC -> Temp.TempADC; TempMonM.Timer -> TimerC.Timer[unique("Timer")]; TempMonM.Send -> Router.Send[AM_TEMPMONMSG]; // 전송 컴포넌트 연결 TempMonM.GlobalTime -> Router.GlobalTime; Router.ReceiveMsg[AM_TEMPMONMSG] -> Comm.ReceiveMsg[AM_TEMPMONMSG]; } /* tempMon.h */ enum { TIMER_RATE = 5000, // Send a message every 5 seconds AM_TEMPMONMSG = 10, }; typedef struct TempMonMsg { uint16_t address; uint32_t timestamp; uint16_t reading; } __attribute__ ((packed)) TempMonMsg; /* MH.h */ ... GOSSIPING_MAX_HOP_COUNT = 250, GOSSIPING_NEIGHBOUR_TABLE_SIZE = 32, GOSSIPING_ROUTE_UPDATE_RATE = 10000, ... /* MH.h */ typedef struct MHMessage { uint16_t sendingNode; uint16_t originNode; uint16_t seqNo; uint16_t hopCount; uint8_t data[(TOSH_DATA_LENGTH - 8)]; } __attribute__ ((packed)) MHMessage;

  19. 2. Gossiping Protocol • Configuration – MHGossipingRouter.nc includes MH; configuration MHGossipingRouter{ provides { interface StdControl; interface Receive[uint8_t id]; interface Send[uint8_t id]; interface Intercept[uint8_t id]; interface GlobalTime; } uses { interface ReceiveMsg[uint8_t id]; } } implementation{ components MHEngineM, MHGossipingPSM, GenericComm as Comm, QueuedSend, TimerC, RandomLFSR, SimpleTime, TimeSyncM, LedsC; StdControl = MHEngineM.StdControl; Receive = MHEngineM.Receive; Send = MHEngineM.Send; ReceiveMsg = MHEngineM.ReceiveMsg; Intercept = MHEngineM.Intercept; GlobalTime = TimeSyncM.GlobalTime; MHEngineM.CommStdControl -> Comm.Control;

  20. 2. Gossiping Protocol • Configuration – MHGossipingRouter.nc (con’d) #ifdef SIM MHEngineM.SimTimer -> TimerC.Timer[unique("Timer")]; #endif MHEngineM.SubControl -> QueuedSend.StdControl; MHEngineM.SendMsg -> QueuedSend.SendMsg; MHEngineM.SubControl -> MHGossipingPSM.StdControl; MHEngineM.RouteSelect -> MHGossipingPSM.RouteSelect; // Gossiping 프로토콜 컴포넌트에 연결 MHEngineM.Leds -> LedsC.Leds; MHEngineM.SubControl -> TimeSyncM.StdControl; MHEngineM.GlobalTime -> TimeSyncM.GlobalTime; MHGossipingPSM.Timer -> TimerC.Timer[unique("Timer")]; MHGossipingPSM.ReceiveMsg -> Comm.ReceiveMsg[AM_MHMESSAGE]; MHGossipingPSM.SendMsg -> QueuedSend.SendMsg[AM_MHMESSAGE]; MHGossipingPSM.Random -> RandomLFSR.Random; MHGossipingPSM.Leds -> LedsC.Leds; TimeSyncM.Leds -> LedsC.Leds; TimeSyncM.Timer -> TimerC.Timer[unique("Timer")]; TimeSyncM.Time -> SimpleTime.Time; TimeSyncM.ReceiveMsg -> Comm.ReceiveMsg[AM_TIMESYNC]; TimeSyncM.SendMsg -> QueuedSend.SendMsg[AM_TIMESYNC]; }

  21. 2. Gossiping Protocol • Module – MHGossipingPSM.nc includes AM; includes MH; module MHGossipingPSM { provides { interface StdControl; interface RouteSelect; } uses { interface Timer; interface ReceiveMsg; interface SendMsg; interface Random; interface Leds; } }

  22. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) implementation{ typedef struct RoutePacket { uint16_t nodeID; } __attribute__ ((packed)) RoutePacket; typedef struct NeighbourTable { // 이웃들의 정보를 기록할 구조체 uint16_t nodeID; // 노드 ID uint16_t receivedCount; // 수신한 메시지 카운트 uint16_t timerTicks; // 최종 패킷을 받은 후 경과한 시간(Tick) bool nodeAlive; // 노드의 상태(Alive or Dead) uint16_t strength; // 연결(Link) 강도 } NeighbourTable; enum { MAX_HOP_COUNT = GOSSIPING_MAX_HOP_COUNT, // 최대 Hop count 설정 NEIGHBOUR_TABLE_SIZE = GOSSIPING_NEIGHBOUR_TABLE_SIZE, // 이웃 노드 Table 크기 NEIGHBOUR_DEAD_TICKS = 5, // 죽은 이웃 노드 감지 시간 ROUTE_UPDATE_RATE = GOSSIPING_ROUTE_UPDATE_RATE // 라우팅 테이블 갱신률 }; TOS_Msg routeMsg; // 라우팅될 메시지를 담을 구조체 bool sendRouteBusy; // 전송 플래그(Busy or Not) NeighbourTable neighbourTable[NEIGHBOUR_TABLE_SIZE]; // 이웃 노드 기록 Table 구조체 배열 uint16_t entries; // 현재 기록된 이웃 수

  23. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) static void updateTableEntry(uint16_t id, uint16_t strength) { int entryIndex, lowestStrengthIndex, nodeDeadIndex; uint16_t lowestStrength = 0; lowestStrengthIndex = nodeDeadIndex = entries; for (entryIndex = 0; entryIndex < entries; entryIndex++) { // 테이블 검색 if (neighbourTable[entryIndex].nodeID == id) { // 이미 존재하는 경우 break; } else if ((neighbourTable[entryIndex].nodeAlive == FALSE) && (nodeDeadIndex == entries)) { nodeDeadIndex = entryIndex; // 해당 이웃 노드가 죽은 경우 } else if ((neighbourTable[entryIndex].strength < lowestStrength) || (lowestStrengthIndex == entries)) { lowestStrengthIndex = entryIndex; // 가장 신호가 약한 노드 골라내기 lowestStrength = neighbourTable[entryIndex].strength; } }

  24. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) if (entryIndex < entries) { // 이웃 테이블의 엔트리 갱신 dbg(DBG_TEMP, "MHGossipingPSM - Updating entry for node %i in neighbour table\n", id); neighbourTable[entryIndex].receivedCount++; neighbourTable[entryIndex].timerTicks = 0; neighbourTable[entryIndex].nodeAlive = TRUE; neighbourTable[entryIndex].strength = strength; } else if (nodeDeadIndex != entries) { // 죽은 노드는 다른 노드로 대체 dbg(DBG_TEMP, "MHGossipingPSM - Replacing dead node %i for node %i in neighbour table\n", neighbourTable[nodeDeadIndex].nodeID, id); neighbourTable[nodeDeadIndex].nodeID = id; neighbourTable[nodeDeadIndex].receivedCount = 1; ………………………………... } else if (entries < NEIGHBOUR_TABLE_SIZE) { // 아직 테이블이 가득차지 않았다면 새로운 엔트리 추가 dbg(DBG_TEMP, "MHGossipingPSM - Adding entry for node %i in neighbour table\n", id); neighbourTable[entries].nodeID = id; ……………………………….. } else if (strength > lowestStrength) { // 신호 세기가 약한 노드는 다른 노드로 대체 { dbg(DBG_TEMP, "MHGossipingPSM - Replacing node %i for node %i in neighbour table\n", ………………………………… } }

  25. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) task void updateTable() { // 테이블 갱신 int i; for (i = 0; i < entries; i++) { if (neighbourTable[i].nodeAlive == TRUE) {// 무한 Tick 현상을 제거하기 위해 살아있는 노드만 갱신 neighbourTable[i].timerTicks++; if (neighbourTable[i].timerTicks >= NEIGHBOUR_DEAD_TICKS) { dbg(DBG_TEMP, "MHGossipingPSM - Setting node %i as dead in neighbour table\n", neighbourTable[i].nodeID); neighbourTable[i].nodeAlive = FALSE; } } } } task void advertise() { // 주기적 advertise 패킷 전송 RoutePacket *pRP = (RoutePacket *) &routeMsg.data[0]; uint8_t length = sizeof(RoutePacket); if (sendRouteBusy == TRUE) { return; } // 채널이 사용중일때는 전송 중지 pRP->nodeID = TOS_LOCAL_ADDRESS; if (call SendMsg.send(TOS_BCAST_ADDR, length, &routeMsg) == SUCCESS) { // 전송하기 atomic { call Leds.redToggle(); } // 전송중일때는 빨간 LED 깜빡이기 dbg(DBG_TEMP, "MHGossipingPSM - Advertising presence\n"); atomic sendRouteBusy = TRUE; } }

  26. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) command result_t StdControl.init() { entries = 0; sendRouteBusy = FALSE; call Random.init(); // 각 변수 초기화 return SUCCESS; } command result_t StdControl.start() { return call Timer.start(TIMER_REPEAT, ROUTE_UPDATE_RATE); } command result_t StdControl.stop() { return call Timer.stop(); } command bool RouteSelect.isActive() { // 이웃에서 작동중인 노드의 존재 유무 검사 int i; bool alive = FALSE; for (i = 0; i < entries; i++) { if (neighbourTable[i].nodeAlive == TRUE) { alive = TRUE; break; } } return alive; }

  27. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) command result_t RouteSelect.selectRoute(TOS_MsgPtr msg, uint8_t id) { MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; if (pMHMsg->sendingNode != TOS_LOCAL_ADDRESS) { pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; pMHMsg->hopCount++; // 다른 노드로부터 패킷을 수신한 경우 } if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) { msg->addr = TOS_UART_ADDR; // 패킷이 local 노드에서 생성된 경우, 목적지 주소를 UART(Serial)로 설정 } else if (entries > 0) { // 외부의 패킷이면 이웃 entry 에서 한 노드를 랜덤하게 선택한다 uint16_t num = call Random.rand() % entries; int i; for (i = 0; i < entries; i++) { // 살아있는 노드인경우 현재 메시지의 다음 경로로 지정 if (neighbourTable[num].nodeAlive == TRUE) { msg->addr = neighbourTable[num].nodeID; break; } else { num++; num = num % entries; } } // 엔트리 검색에서 라우팅이 가능한 어떤 노드도 발견하지 못한 경우 if (i == entries) { dbg(DBG_TEMP, "MHGossipingPSM - Failed to select route\n"); return FAIL; } } else { dbg(DBG_TEMP, "MHGossipingPSM - Failed to select route\n"); return FAIL; } if (pMHMsg->hopCount < MAX_HOP_COUNT || msg->addr == TOS_UART_ADDR) { // TTL 유효 or UART dbg(DBG_TEMP, "MHGossipingPSM - Route selected\n"); // 라우팅 성공 return SUCCESS; } dbg(DBG_TEMP, "MHGossipingPSM - Failed to select route - hop count exceeded\n"); return FAIL; // 패킷 폐기 }

  28. 2. Gossiping Protocol • Module – MHGossipingPSM.nc (con’d) command result_t RouteSelect.initializeFields(TOS_MsgPtr msg, uint8_t id) { MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; pMHMsg->originNode = pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; pMHMsg->hopCount = 0; // 메시지의 각 필드 초기화 return SUCCESS; } event result_t Timer.fired() { // 타이머 만료시 post updateTable(); //이웃 테이블 갱신 post advertise(); return SUCCESS; } event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr m) { // 메시지를 수신했을 때 (Advertise) RoutePacket *pRP = (RoutePacket *) m->data; atomic { call Leds.redToggle(); } // 빨간 LED 깜빡이기 dbg(DBG_TEMP, "MHGossipingPSM - Advertisment received from node %i\n", pRP->nodeID); updateTableEntry(pRP->nodeID, m->strength); return m; } event result_t SendMsg.sendDone(TOS_MsgPtr msg, result_t success) { // 라우팅 메시지가 본내진 경우 atomic sendRouteBusy = FALSE; return SUCCESS; }

  29. 2. Gossiping Protocol • Result - TinyViz

  30. 3. LEACH Protocol • LEACH Protocol • Low-Energy Adaptive Clustering Hierarchy • 인접 노드들끼리 대표 노드(coordinator) 선출 • 센싱 데이터는 대표 노드를 통해서만 전송 • 모든 노드들이 전송에 참여하지 않아도 됨 • Best Case : 높은 Delivery Ratio • 대표 노드는 전력 소모가 심하므로 주기적으로 대표 노드 변경 • Worst Case : 대표 노드가 Sink 노드와 전송이 불가능한 상황 • 모든 노드가 전송 전력을 최대로 설정한다는 가정의 한계 • 대표 노드간의 MH 구성 또는 대표노드와 Sink 노드간 Topology 구성이 요구됨.

  31. 3. LEACH Protocol • Configuration – TempMon.nc • Makefile includes TempMon; includes MH; configuration TempMon{ } Implementation { components Main, TempMonM, TimerC, Temp, GenericComm as Comm,QueuedSend, SimpleTime, #ifdef FLOODING MHFloodingRouter as Router; #endif #ifdef GOSSIPING MHGossipingRouter as Router; #endif #ifdef LEACH // LEACH 가 define 된 경우 MHLeachRouter as Router; #endif COMPONENT=TempMon SENSORBOARD=basicsb PFLAGS= -I. -I./Queue -DLEACH -DLEACH_PROBABILITY=25 -DSIM=10 include ../../../../apps/Makerules

  32. 3. LEACH Protocol • Configuration – TempMon.nc (con’d) & headers Main.StdControl -> TempMonM.StdControl; Main.StdControl -> Router.StdControl; // 라우팅 프로토콜 연결 Main.StdControl -> Comm.Control; Main.StdControl -> QueuedSend.StdControl; Main.StdControl -> Temp.StdControl; Main.StdControl -> TimerC.StdControl; Main.StdControl -> SimpleTime.StdControl; TempMonM.ADC -> Temp.TempADC; TempMonM.Timer -> TimerC.Timer[unique("Timer")]; TempMonM.Send -> Router.Send[AM_TEMPMONMSG]; // 전송 컴포넌트 연결 TempMonM.GlobalTime -> Router.GlobalTime; Router.ReceiveMsg[AM_TEMPMONMSG] -> Comm.ReceiveMsg[AM_TEMPMONMSG]; } /* tempMon.h */ enum { TIMER_RATE = 5000, // Send a message every 5 seconds AM_TEMPMONMSG = 10, }; typedef struct TempMonMsg { uint16_t address; uint32_t timestamp; uint16_t reading; } __attribute__ ((packed)) TempMonMsg; /* MH.h */ ... LEACH_ROUTE_UPDATE_RATE = 10000, // 10 sec LEACH_ROUND_LENGTH = 600000, // 10 min LEACH_NEIGHBOUR_TABLE_SIZE = 32 ... /* MH.h */ typedef struct MHMessage { uint16_t sendingNode; uint16_t originNode; uint16_t seqNo; uint16_t hopCount; uint8_t data[(TOSH_DATA_LENGTH - 8)]; } __attribute__ ((packed)) MHMessage;

  33. 3. LEACH Protocol • Configuration – MHLeachRouter.nc includes MH; configuration MHLeachRouter{ provides { interface StdControl; interface Receive[uint8_t id]; interface Send[uint8_t id]; interface Intercept[uint8_t id]; interface GlobalTime; } uses { interface ReceiveMsg[uint8_t id]; } } Implementation{ components MHEngineM, MHLeachPSM, GenericComm as Comm, QueuedSend, TimerC, RandomLFSR, SimpleTime, TimeSyncM, LedsC;// MHEngine, MHLeachPSM 컴포넌트 연결 StdControl = MHEngineM.StdControl; Receive = MHEngineM.Receive; Send = MHEngineM.Send; ReceiveMsg = MHEngineM.ReceiveMsg; Intercept = MHEngineM.Intercept; GlobalTime = TimeSyncM.GlobalTime; MHEngineM.CommStdControl -> Comm.Control;

  34. 3. LEACH Protocol • Configuration – MHLeachRouter.nc (con’d) #ifdef SIM MHEngineM.SimTimer -> TimerC.Timer[unique("Timer")]; #endif MHEngineM.SubControl -> QueuedSend.StdControl; MHEngineM.SendMsg -> QueuedSend.SendMsg; MHEngineM.SubControl -> MHLeachPSM.StdControl; MHEngineM.RouteSelect -> MHLeachPSM.RouteSelect; // Leach 프로토콜이 구현된 MHLeachPSM 에 연결 MHLeachPSM.StatusTimer -> TimerC.Timer[unique("Timer")]; MHLeachPSM.RoundTimer -> TimerC.Timer[unique("Timer")]; MHLeachPSM.ReceiveMsg -> Comm.ReceiveMsg[AM_MHMESSAGE]; MHLeachPSM.SendMsg -> QueuedSend.SendMsg[AM_MHMESSAGE]; // 메시지 큐 MHLeachPSM.Random -> RandomLFSR.Random; // 랜덤값 발생 MHEngineM.Leds -> LedsC.Leds; TimeSyncM.Leds -> LedsC.Leds; MHLeachPSM.Leds -> LedsC.Leds; MHEngineM.SubControl -> TimeSyncM.StdControl; TimeSyncM.Timer -> TimerC.Timer[unique("Timer")]; TimeSyncM.Time -> SimpleTime.Time; TimeSyncM.ReceiveMsg -> Comm.ReceiveMsg[AM_TIMESYNC]; TimeSyncM.SendMsg -> QueuedSend.SendMsg[AM_TIMESYNC]; // 메시지 큐 MHEngineM.GlobalTime -> TimeSyncM.GlobalTime; }

  35. 3. LEACH Protocol • Module – MHLeachPSM.nc includes AM; includes MH; module MHLeachPSM { provides { interface StdControl; interface RouteSelect; // Leach 프로토콜 Router 인터페이스 } uses { interface Timer as RoundTimer; interface Timer as StatusTimer; interface ReceiveMsg; interface SendMsg; interface Random; interface Leds; } }

  36. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) implementation { typedef struct RoutePacket { // 라우팅할 패킷 구조체 uint16_t addr; // Broadcast 주소로 지정된 패킷은 상태 구분 메시지로 간주 uint16_t nodeID; // 특적 목적지가 지정된 패킷은 Fowarding 요청으로 간주 uint16_t depth; uint8_t round; bool isClusterHead; // cluster coordinator 여부를 가지는 플래그 bool becomeClusterHead; // cluster coordinator 가 되는 노드가 가지는 플래그 } __attribute__ ((packed)) RoutePacket; typedef struct NeighbourTable { uint16_t nodeID; bool isClusterHead; // 이웃 노드 라우팅 테이블 uint16_t depth; // 라우팅 계층의 깊이 uint8_t timerTicks; bool nodeAlive; // 노드가 살아있는지 여부 uint16_t strength; // 신호의 세기 } NeighbourTable;

  37. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) enum { ROUND_LENGTH = LEACH_ROUND_LENGTH, ROUTE_UPDATE_RATE = LEACH_ROUTE_UPDATE_RATE, NEIGHBOUR_TABLE_SIZE = LEACH_NEIGHBOUR_TABLE_SIZE, NEIGHBOUR_DEAD_TICKS = 5, TIMEOUT_TICKS = 5, // cluster coordinator 가 되기전까지의 대기시간(Tick 단위) PARENT_INVALID = 0xeeee, INFINITY = 0xffff, ROUND_INVALID = 0xff, PROBABILITY = LEACH_PROBABILITY // 확률 설정 }; uint8_t round; // Current LEACH round uint16_t parentID; bool isClusterHead; uint16_t depth; // 라우팅 트리에서의 깊이 uint8_t ticks; // cluster coordinator 없이 전송한 시간(누적) TOS_Msg routeMsg; // 라우팅 정보를 저장할 메시지 구조체 bool sendRouteBusy; // 노드의 전송 상태 플래그(Busy or not) uint16_t addr; NeighbourTable neighbours[NEIGHBOUR_TABLE_SIZE]; // 이웃 노드의 라우팅 정보를 저장하는 테이블 배열 uint16_t tableEntries;

  38. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void updateTable() { // 라우팅 테이블 업데이트 int i; for (i = 0; i < tableEntries; i++) { // 노드가 살아있는 경우만 테이블 갱신, 무한 tick 현상 예방 if (neighbours[i].nodeAlive == TRUE) { neighbours[i].timerTicks++; if (neighbours[i].timerTicks >= NEIGHBOUR_DEAD_TICKS) dbg(DBG_TEMP, "MHLeachPSM - Setting node %i as dead in neighbour table\n", neighbours[i].nodeID); neighbours[i].nodeAlive = FALSE; } } }

  39. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void updateTableEntry(uint16_t id, uint16_t treeDepth, bool isHead, uint16_t strength) { int i; // 테이블에서 엔트리를 검색, 죽은 노드와 가장 높은 Hop 노드는 걸러냄 uint16_t maxLeafDepth, maxHeadDepth; int maxLeafIndex, maxHeadIndex, nodeDead; maxLeafDepth = maxHeadDepth = 0; // sink 노드( ID = 0 ) 만이 Depth 가 0 maxLeafIndex = maxHeadIndex = nodeDead = tableEntries; for (i = 0; i < tableEntries; i++) { if (neighbours[i].nodeID == id) { break; }// 노드가 엔트리를 가진경우 else if ((neighbours[i].nodeAlive == FALSE) && (nodeDead == tableEntries)) { nodeDead = i; // 노드가 죽은경우 } else if ((neighbours[i].isClusterHead == TRUE) && (neighbours[i].depth > maxHeadDepth)) { maxHeadDepth = neighbours[i].depth;// 노드가 cluster coordinator 인 동시에 Depth가 가장 큰 경우 maxHeadIndex = i; } else if (neighbours[i].depth > maxLeafDepth) { // 노드가 leaf 노드인 동시에 Depth가 가장 큰 경우 maxLeafDepth = neighbours[i].depth; maxLeafIndex = i; } }

  40. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) if (i < tableEntries) { // 테이블 업데이트 dbg(DBG_TEMP, "MHLeachPSM - Updating node %i in neighbour table\n", id); neighbours[i].isClusterHead = isHead; neighbours[i].depth = treeDepth; neighbours[i].timerTicks = 0; neighbours[i].nodeAlive = TRUE; neighbours[i].strength = strength; } else if (nodeDead != tableEntries) { // 죽은 노드 엔트리 교체 neighbours[nodeDead].nodeID, id); } else if (tableEntries < NEIGHBOUR_TABLE_SIZE) { // 테이블에 여유 공간이 있는 경우 neighbours[tableEntries].nodeID = id; } else if ((isHead == TRUE) && (maxLeafIndex != tableEntries)) { // leaf 노드와 cluster coordinator 교체 neighbours[maxLeafIndex].nodeID, id); } else if ((maxLeafIndex != tableEntries) && (maxLeafDepth > treeDepth)) { // leaf 노드중 더 낮은 깊이의 노드로 교체 neighbours[maxLeafIndex].nodeID, id); } else if ((isHead == TRUE) && (maxHeadIndex != tableEntries) && (maxHeadDepth > treeDepth)) { neighbours[maxHeadIndex].nodeID = id // cluster coordinator 노드를 sink 노드에 더 가까운 노드로 교체 } }

  41. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void selectParent() { // 각 노드의 부모노드 선택 int i; uint16_t minLeafDepth, minHeadDepth; int minLeafIndex, minHeadIndex; ticks++; minLeafDepth = minHeadDepth = INFINITY; minLeafIndex = minHeadIndex = tableEntries; for (i = 0; i < tableEntries; i++) { if ((neighbours[i].isClusterHead == TRUE) && (neighbours[i].depth < minHeadDepth)) { minHeadDepth = neighbours[i].depth; // 노드가 cluster coordinator 인 동시에 가장 낮은 깊이일 때 minHeadIndex = i; } else if (neighbours[i].depth < minLeafDepth) { // 노드가 leaf 노드인 동시에 가장 낮은 깊이일 때 minLeafDepth = neighbours[i].depth; minLeafIndex = i; } }

  42. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) if (minHeadIndex != tableEntries) { // 가장 낮은 깊이의 cluster coordinator parentID = neighbours[minHeadIndex].nodeID; depth = neighbours[minHeadIndex].depth + 1; ticks = 0; dbg(DBG_TEMP, "MHLeachPSM - New parent selected (ID: %i)\n", parentID); return; } else if (ticks >= TIMEOUT_TICKS) { // leaf 노드로부터의 연결이 timeout 된 경우 if (minLeafIndex != tableEntries) { atomic addr = neighbours[minLeafIndex].nodeID; // 매 time tick 마다 대표가 될 적절한 노드가 있는지 검사 } ticks = 0; // timeout reset } parentID = PARENT_INVALID; dbg(DBG_TEMP, "MHLeachPSM - Could not select new parent\n"); depth = INFINITY; }

  43. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void nextRound() { round = (round + 1) % ROUND_INVALID; } // 다음 노드 찾기 static bool isNewRound(uint8_t r) { // 비정상적인 노드 advertising if (r == ROUND_INVALID) { return FALSE; } // 아직 round 배정을 받지 못한 경우 else if (round == ROUND_INVALID) { return TRUE; } else { uint8_t previous; if (round == 0) { previous = ROUND_INVALID - 1; } else { previous = round--; } if ((r != round) && (r != previous)) { return TRUE; } else { return FALSE; } } }

  44. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) task void advertise() { RoutePacket *pRP = (RoutePacket *) &routeMsg.data[0]; // 라우팅 정보 저장용 패킷 구조체 포인팅 uint8_t length = sizeof(RoutePacket); if (sendRouteBusy == TRUE) { return; } // 노드가 전송중일때는 전종 작업 중단 pRP->addr = addr; atomic addr = TOS_BCAST_ADDR; // broadcast pRP->nodeID = TOS_LOCAL_ADDRESS; // local 주소 지정 pRP->depth = depth; pRP->round = round; pRP->isClusterHead = isClusterHead; if (pRP->addr != TOS_BCAST_ADDR) { // forwarding 요청에 대한 필드 설정 dbg(DBG_TEMP, "MHLeachPSM - Requesting node %i become a cluster head\n", pRP->addr); pRP->becomeClusterHead = TRUE; } else { pRP->becomeClusterHead = FALSE; } // 포워딩 되므로 cluster coordinator 가 아님 if (call SendMsg.send(TOS_BCAST_ADDR, length, &routeMsg) == SUCCESS) { atomic { call Leds.redToggle(); } // RF 전송중에는 빨간 LED 깜박이기 dbg(DBG_TEMP, "MHLeachPSM - Advertising presence (Cluster Head: %i)\n", (int) isClusterHead); atomic sendRouteBusy = TRUE; // 전송중 플래그 활성화 } }

  45. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void init() { tableEntries = 0; ticks = 0; addr = TOS_BCAST_ADDR; // Normal route packet - no forwarding request if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) { round = 0; parentID = TOS_UART_ADDR; // 메시지의 목적지가 자기자신(Local)인 경우 UART(Serial) 전송 isClusterHead = TRUE; depth = 0; } else { round = ROUND_INVALID; parentID = PARENT_INVALID; isClusterHead = FALSE; depth = INFINITY; } }

  46. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) static void startNewRound(uint8_t r) { // 새로운 round[cluster coordinator 변경] 시작 // 노드 상태에 따라 결정, (확률, 난수) uint16_t probability = ((uint16_t) PROBABILITY) * (0xffff / 100); uint16_t randNo = call Random.rand(); bool clusterStatus = randNo < probability; dbg(DBG_TEMP, "MHLeachPSM - Round %i started (Cluster Head: %i)\n", r, (int) clusterStatus); atomic { round = r; ticks = 0; tableEntries = 0; parentID = PARENT_INVALID; // 대표 노드이므로 depth = INFINITY; addr = TOS_BCAST_ADDR; isClusterHead = clusterStatus; } }

  47. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) command result_t StdControl.init() { init(); return call Random.init(); // 초기화 } command result_t StdControl.start() { // sink 노드부터 cluster coordinator round 시작 if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) { call RoundTimer.start(TIMER_REPEAT, ROUND_LENGTH); // sink 노드인경우 } return call StatusTimer.start(TIMER_REPEAT, ROUTE_UPDATE_RATE); } command result_t StdControl.stop() { call RoundTimer.stop(); return call StatusTimer.stop(); } command bool RouteSelect.isActive() { if (parentID != PARENT_INVALID) { return TRUE; } return FALSE; }

  48. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) command result_t RouteSelect.selectRoute(TOS_MsgPtr msg, uint8_t id) { MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; // MH 메시지 전송용 구조체 포인터 // 패킷이 자기 자신으로부터 생겨난 경우 ↓ if ((pMHMsg->originNode == TOS_LOCAL_ADDRESS) && (pMHMsg->hopCount == 0)) { if (parentID != PARENT_INVALID) { // 부모노드는 없음 dbg(DBG_TEMP, "MHLeachPSM - Routing to node %i\n", parentID); msg->addr = parentID; return SUCCESS; } } else { // 자신이 아닌 다른 곳에서 온 패킷인 경우 if ((isClusterHead == TRUE) && (parentID != PARENT_INVALID)) { // 대표노드일때만 pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; pMHMsg->hopCount++; // hop count 올리기 dbg(DBG_TEMP, "MHLeachPSM - Routing to node %i\n", parentID); msg->addr = parentID; return SUCCESS; } dbg(DBG_TEMP, "MHLeachPSM - Could not select route\n"); return FAIL; } }

  49. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) command result_t RouteSelect.initializeFields(TOS_MsgPtr msg, uint8_t id) { MHMessage *pMHMsg = (MHMessage *) &msg->data[0]; // MH 메시지용 자료 형변환 pMHMsg->originNode = pMHMsg->sendingNode = TOS_LOCAL_ADDRESS; pMHMsg->hopCount = 0; // 메시지에 기본값들 부여, TTL =0 return SUCCESS; } event result_t RoundTimer.fired() { // 라우팅 타이머 만료시 dbg(DBG_TEMP, "MHLeachPSM - Round Timer fired\n"); nextRound(); // 새로운 대표노드 선택 return SUCCESS; } event result_t StatusTimer.fired() { // 노드 상태 타이머 만료시 if ((TOS_LOCAL_ADDRESS != BASE_STATION_ADDRESS) && (round != ROUND_INVALID)) { updateTable(); selectParent(); } post advertise(); return SUCCESS; } event result_t SendMsg.sendDone(TOS_MsgPtr msg, result_t success) { atomic sendRouteBusy = FALSE; // 전송 완료시 return SUCCESS; }

  50. 3. LEACH Protocol • Module – MHLeachPSM.nc (con’d) event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr m) { atomic { call Leds.redToggle(); } // 전송중에는 빨간 LED 깜박이기 if (TOS_LOCAL_ADDRESS != BASE_STATION_ADDRESS) { // sink 노드는 다른 노드의 정보가 불필요 RoutePacket *pRP = (RoutePacket *) m->data; if (pRP->round != ROUND_INVALID) { // 비정상적인 round 인 경우 if (isNewRound(pRP->round) == TRUE) { startNewRound(pRP->round); // 새로운 round 시작 } else if (pRP->addr == TOS_LOCAL_ADDRESS) { // 패킷이 현재 노드에 forwarding 요청을 하는경우 isClusterHead = pRP->becomeClusterHead; if (pRP->becomeClusterHead == TRUE) { // cluster coordinator 로 설정되었을 때 dbg(DBG_TEMP, "MHLeachPSM - Becoming cluster head at request of node %i\n", pRP->nodeID); } } dbg(DBG_TEMP, "MHLeachPSM - Received advert (Origin ID: %i, Cluster Head: %i,Depth: %i)\n", pRP->nodeID, (int) pRP->isClusterHead, pRP->depth); updateTableEntry(pRP->nodeID, pRP->depth, pRP->isClusterHead, m->strength); } } return m; }

More Related