reliability를 높이기 위해 retransmission 기능을 사용하고자 할 때는 다음과 같이 설정한다.
0. 설정
- /opt/tinyos-1.x/tos/lib/CC2420Radio/CC2420RadioM.nc에서 bAckEnable = TRUE;로 설정
- /tos/system/AMPromiscuous.nc에서 crc_check = TRUE;로 설정
- /tos/lib/Queue/QueueSendM.nc에서 retransmit = TRUE;로 설정
1. Application에서 MacControl Component를 wiring
configuration Test {
}
implementation {
component CC2420RadioC;
...
TestM.MacControl -> CC2420RadioC;
}
2. StdControl.start() 에 MacControl.enableAck() 을 추가
module TestM {
provides {
...
}
uses {
interface MacControl;
...
}
implementation {
...
command result_t StdControl.start() {
call MacControl.enableAck();
}
...
}
3. tos/lib/CC2420Radio/CC2420RadioM.nc
- BackoffTimerJiffy.fired() 에서 case TIMER_ACK 의 if (!post PacketSent()) 를 주석처리. 이것 때문에 ACK이 오지 않더라도 ack timeout 시 sendDone에 SUCCESS가 return된다.
- sendDone event callback에서 success == FAIL 인 경우 바로 msg ptr을 retransmission. 필요에 따라 retransmission counter를 두고 max_retransmission을 초과할 경우 drop
- opt/tinyos-1.x/lib/Queue/QueuedSendM.nc 는 TinyOS의 메시지 전송 큐를 관리한다. 재전송 기능도 QueuedSendM 에서 수행된다.
event result_t SerialSendMsg.sendDone[uint8_t id](TOS_MsgPtr msg, result_t success) {
...
if (!retransmit \\ msg->ack != 0 \\ msgqueue[dequeue_next].address == TOS_UART_ADDR) {
// 재전송이 필요 없는 경우 큐의 포인터를 다음 패킷으로 이동시키고,
// 상위 컴포넌트로 메시지 전송 성공 이벤트 발생 (signal, SUCCESS)
...
} else {
...
if ((++(msgqueue[dequeue_next].xmit_count) > MAX_RETRANSMIT_COUNT)) {
// 최대 재전송횟수를 초과했을 경우 큐의 포인터를 다음 패킷으로 이동시키고,
// 상위 컴포넌트로 메시지 전송 실패 이벤트 발생 (signal, FAIL)
...
}
}
// 데이터 전송 Task 실행
post QueueServiceTask();
return SUCCESS;
}
테스트는 멀티홉 라우팅 기능을 사용하며, 라우팅 경로를 빨리 설정하기 위해 라우팅 메시지 전송 주기를 짧게 설정하였다. 그리고 모트 3개 정도에 프로그램을 올리고 테스트 한 결과 재전송이 계속 발생하지만 Base Node에 패킷이 수신되지 않는 현상이 발생하였다. 문제의 원인을 파악한 결과, 라우팅 메시지는 Broadcast 를 사용하며 Broadcast도 이 QueuedSend 의 큐를 통해 전송이 일어나고, Broadcast에 대해서도 재전송을 수행하기 때문이었다.
따라서 위 소스를 그대로 사용하여 재전송 기능을 사용할 경우, Broadcast 하는 패킷에 대한 Ack 가 없을 경우에도 계속 재전송을 하게 되어 Breadcast가 많을 경우 Queue Overflow가 발생할 수 있으며, 쓸데 없이 계속 재전송을 수행하게 된다.
(※ 수신 노드에서는 unicast 일 경우에만 ack 메시지를 전송한다)
이 문제를 해결하기 위해서 위 소스의 if 문 조건을 다음과 같이 변경하여야 한다.
if ((!retransmit) \\ (msg->ack != 0) \\ (msgqueue[dequeue_next].address == TOS_UART_ADDR) \\ (msgqueue[dequeue_next].address == TOS_BCAST_ADDR)) {
...
}
댓글 없음:
댓글 쓰기