📄 nwk.c
字号:
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = (BYTE) (a_nwk_tx_data.dstSADDR);
//frame control
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = a_nwk_tx_data.fcfmsb;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = a_nwk_tx_data.fcflsb;
//network header is fixed size
phy_pib.currentTxFlen += 8;
nwkTxData_addmac:
//fill in the MAC fields. For now, we don't support inter-PAN
// so the PANID has to be our mac PANID
a_mac_tx_data.DestPANID = mac_pib.macPANID;
a_mac_tx_data.SrcPANID = mac_pib.macPANID;
if (a_nwk_tx_data.dstSADDR == LRWPAN_SADDR_USE_LADDR ){
//long address is specified from above. We assume they know where
//they are going no routing necessary
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_LADDR|LRWPAN_FCF_SRCMODE_LADDR;
//copy in the long address
halUtilMemCopy(&a_mac_tx_data.DestAddr.laddr.bytes[0], a_nwk_tx_data.dstLADDR, 8);
} else {
//lets do some routing
#ifdef LRWPAN_RFD
//RFD's are easy. Always send to parent, our SRC address is always long
//so that parent can confirm that the RFD is still in their neighbor table
//will use the parent short address
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
a_mac_tx_data.DestAddr.saddr = mac_pib.macCoordShortAddress;
#else
{
SADDR newDstSADDR;
//this is router. need to determine the new dstSADDR
newDstSADDR = a_nwk_tx_data.dstSADDR; //default
DEBUG_STRING(DBG_INFO,"Routing pkt to: ");
DEBUG_UINT16(DBG_INFO,newDstSADDR);
if (a_nwk_tx_data.dstSADDR != LRWPAN_BCAST_SADDR) {
//not broadcast address
newDstSADDR = ntFindNewDst(a_nwk_tx_data.dstSADDR);
DEBUG_STRING(DBG_INFO," through: ");
DEBUG_UINT16(DBG_INFO,newDstSADDR);
if (newDstSADDR == LRWPAN_BCAST_SADDR) {
DEBUG_STRING(DBG_INFO,", UNROUTABLE, error!\n ");
//error indicator. An unroutable packet from here.
a_mac_service.args.error.status = LRWPAN_STATUS_NWK_PACKET_UNROUTABLE;
a_mac_service.cmd = LRWPAN_SVC_MAC_ERROR;
goto nwkTxData_sendit;
}
DEBUG_STRING(DBG_INFO,"\n");
}
//fill it in.
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
a_mac_tx_data.DestAddr.saddr = newDstSADDR;
}
#endif
}
//for data frames, we want a MAC level ACK, unless it is a broadcast.
if ( ((LRWPAN_GET_DST_ADDR(a_mac_tx_data.fcfmsb)) == LRWPAN_ADDRMODE_SADDR) &&
a_mac_tx_data.DestAddr.saddr == LRWPAN_BCAST_SADDR) {
//no MAC ACK
a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_DATA|LRWPAN_FCF_INTRAPAN_MASK ;
}else {
a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_DATA|LRWPAN_FCF_INTRAPAN_MASK |LRWPAN_FCF_ACKREQ_MASK;
}
//send it.
a_mac_service.cmd = LRWPAN_SVC_MAC_GENERIC_TX;
nwkTxData_sendit:
macDoService();
}
static void nwkRxFSM(void) {
BYTE *ptr;
nwkRxFSM_start:
switch(nwkRxState) {
case NWK_RXSTATE_IDLE:
break;
case NWK_RXSTATE_START:
//we have a packet, lets check it out.
ptr = a_nwk_rx_data.orgpkt.data + a_nwk_rx_data.nwkOffset;
if (NWK_IS_CMD(*ptr)) {
//currently don't handle CMD packets. Discard.
DEBUG_STRING(DBG_INFO,"NWK: Received NWK CMD packet, discarding.\n");
//MAC resource already free; need to free the MEM resource
MemFree(a_nwk_rx_data.orgpkt.data);
nwkRxState = NWK_RXSTATE_IDLE;
break;
}
//this is a data packet. do more parsing.
nwkParseHdr(ptr);
//see if this is for us.
if ((a_nwk_rx_data.dstSADDR == LRWPAN_BCAST_SADDR) ||
(a_nwk_rx_data.dstSADDR == LRWPAN_SADDR_USE_LADDR) ||
(a_nwk_rx_data.dstSADDR == macGetShortAddr())) {
//hand this off to the APS layer
nwkRxState = NWK_RXSTATE_APS_HANDOFF;
} else {
//have to route this packet
nwkRxState = NWK_RXSTATE_DOROUTE;
}
goto nwkRxFSM_start;
case NWK_RXSTATE_APS_HANDOFF:
if (apsRxBusy()) break; //apsRX is still busy
//handoff the current packet
apsRxHandoff();
//we are finished with this packet.
//we don't need to do anything to free this resource other
// than to change state
nwkRxState = NWK_RXSTATE_IDLE;
break;
case NWK_RXSTATE_DOROUTE:
#ifdef LRWPAN_RFD
//RFD somehow got a data packet not intended for it.
//should never happen, but put code here anyway to discard it.
DEBUG_STRING(DBG_INFO,"NWK: RFD received spurious datapacket, discarding.\n");
MemFree(a_nwk_rx_data.orgpkt.data);
nwkRxState = NWK_RXSTATE_IDLE;
#else
//first, check the radius, if zero, then discard.
if (!(*(ptr+6))) {
DEBUG_STRING(DBG_INFO,"NWK: Data packet is out of hops for dest: ");
DEBUG_UINT16(DBG_INFO,a_nwk_rx_data.dstSADDR);
DEBUG_STRING(DBG_INFO,", discarding...\n");
MemFree(a_nwk_rx_data.orgpkt.data);
nwkRxState = NWK_RXSTATE_IDLE;
break;
}
DEBUG_STRING(DBG_INFO,"NWK: Routing NWK Packet to: ");
DEBUG_UINT16(DBG_INFO,a_nwk_rx_data.dstSADDR);
DEBUG_STRING(DBG_INFO,"\n");
//this packet requires routing, not destined for us.
if (nwkRxBuffFull()) {
//no more room. discard this packet
DEBUG_STRING(DBG_INFO,"NWK: FWD buffer full, discarding pkt.\n");
DEBUG_STRING(DBG_INFO,"NWK state: ");
DEBUG_UINT8(DBG_INFO,nwkState);
DEBUG_STRING(DBG_INFO,"MAC state: ");
DEBUG_UINT8(DBG_INFO,macState);
DEBUG_STRING(DBG_INFO,"\n");
MemFree(a_nwk_rx_data.orgpkt.data);
nwkRxState = NWK_RXSTATE_IDLE;
}else {
//ok, add this pkt to the buffer
nwk_pib.rxHead++;
if (nwk_pib.rxHead == NWK_RXBUFF_SIZE) nwk_pib.rxHead = 0;
//save it.
nwk_pib.rxBuff[nwk_pib.rxHead].data = a_nwk_rx_data.orgpkt.data;
nwk_pib.rxBuff[nwk_pib.rxHead].nwkOffset = a_nwk_rx_data.nwkOffset;
nwkRxState = NWK_RXSTATE_IDLE;
//this packet will be retransmitted by nwkFSM
}
#endif
break;
default:
break;
}
}
//Callback from MAC Layer
//Returns TRUE if nwk is still busy with last RX packet.
BOOL nwkRxBusy(void){
return(nwkRxState != NWK_RXSTATE_IDLE);
}
//Callback from MAC Layer
//Hands off parsed packet from MAC layer, frees MAC for parsing
//next packet.
void nwkRxHandoff(void){
a_nwk_rx_data.orgpkt.data = a_mac_rx_data.orgpkt->data;
a_nwk_rx_data.orgpkt.rssi = a_mac_rx_data.orgpkt->rssi;
a_nwk_rx_data.nwkOffset = a_mac_rx_data.pload_offset;
nwkRxState = NWK_RXSTATE_START;
}
static void nwkParseHdr(BYTE *ptr) {
//ptr is pointing at nwk header. Get the SRC/DST nodes.
ptr= ptr+2;
//get Dst SADDR
a_nwk_rx_data.dstSADDR = *ptr;
ptr++;
a_nwk_rx_data.dstSADDR += (((UINT16)*ptr) << 8);
ptr++;
//get Src SADDR
a_nwk_rx_data.srcSADDR = *ptr;
ptr++;
a_nwk_rx_data.srcSADDR += (((UINT16)*ptr) << 8);
ptr++;
}
#ifdef LRWPAN_FFD
//copies packet to forward from heap space to TXbuffer space
void nwkCopyFwdPkt(void){
BYTE *srcptr, len;
NWK_FWD_PKT *pkt;
phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];
//get next PKT
pkt = nwkGetRxPacket();
srcptr = pkt->data; //points at original packet in heapspace
//compute bytes to copy.
//nwkoffset is the offset of the nwkheader in the original packet
len = *(srcptr) - pkt->nwkOffset - PACKET_FOOTER_SIZE + 1 ;
//point this one byte past the end of the packet
srcptr = srcptr
+ *(srcptr) //length of original packet, not including this byte
+ 1 //add one for first byte which contains packet length
- PACKET_FOOTER_SIZE; //subtract footer bytes, don't want to copy these.
//save length
phy_pib.currentTxFlen = len;
//copy from heap space to TXBuffer space
do {
srcptr--; phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = *srcptr;
len--;
}while(len);
nwkFreeRxPacket(TRUE); //free this packet
//some final steps
//get the dstSADDR, needed for routing.
a_nwk_tx_data.dstSADDR = *(phy_pib.currentTxFrm+2);
a_nwk_tx_data.dstSADDR += (((UINT16)*(phy_pib.currentTxFrm+3)) << 8);
//decrement the radius before sending it on.
*(phy_pib.currentTxFrm+6)= *(phy_pib.currentTxFrm+6)- 1;
a_nwk_tx_data.radius = *(phy_pib.currentTxFrm+6);
//leave the SADDR unchanged as we want to know where this originated from!
#if 0
//replace the SADDR with our SADDR
*(phy_pib.currentTxFrm+4) = (BYTE) macGetShortAddr();
*(phy_pib.currentTxFrm+5) = (BYTE) (macGetShortAddr() >>8);
#endif
}
static BOOL nwkRxBuffFull(void){
BYTE tmp;
//if next write would go to where Tail is, then buffer is full
tmp = nwk_pib.rxHead+1;
if (tmp == NWK_RXBUFF_SIZE) tmp = 0;
return(tmp == nwk_pib.rxTail);
}
static BOOL nwkRxBuffEmpty(void){
return(nwk_pib.rxTail == nwk_pib.rxHead);
}
//this does NOT remove the packet from the buffer
static NWK_FWD_PKT *nwkGetRxPacket(void) {
BYTE tmp;
if (nwk_pib.rxTail == nwk_pib.rxHead) return(NULL);
tmp = nwk_pib.rxTail+1;
if (tmp == NWK_RXBUFF_SIZE) tmp = 0;
return(&nwk_pib.rxBuff[tmp]);
}
//frees the first packet in the buffer.
static void nwkFreeRxPacket(BOOL freemem) {
nwk_pib.rxTail++;
if (nwk_pib.rxTail == NWK_RXBUFF_SIZE) nwk_pib.rxTail = 0;
if (freemem) MemFree(nwk_pib.rxBuff[nwk_pib.rxTail].data);
}
#endif
//given a router child SADDR, find the parent router SADDR
UINT16 nwkFindParentSADDR(SADDR childSADDR) {
UINT8 currentDepth;
SADDR currentParent;
SADDR currentRouter;
SADDR maxSADDR;
UINT8 i;
currentDepth = 1;
currentParent = 0;
do {
for (i=0; i<LRWPAN_MAX_ROUTERS_PER_PARENT; i++) {
if (i==0) currentRouter = currentParent+1;
else currentRouter += ntGetCskip(currentDepth);
if (childSADDR == currentRouter) return(currentRouter);
maxSADDR = ntGetMaxSADDR(currentRouter,currentDepth+1);
if ((childSADDR > currentRouter) && (childSADDR <= maxSADDR))
break; //must go further down the tree
}
currentDepth++;
currentParent = currentRouter;
}
while (currentDepth < LRWPAN_MAX_DEPTH-1);
//if we reach here, could not find an address. Return 0 as an error
return(0);
}
UINT16 nwkGetHopsToDest(SADDR dstSADDR){
UINT16 numHops;
SADDR currentParent, maxSADDR;
UINT8 currentDepth;
UINT8 i;
SADDR currentRouter;
numHops = 1; //return a minimum value of 1
currentDepth = 0;
//first compute hops up the tree then down the tree
if ( macGetShortAddr() == 0) goto nwkGetHopsToDest_down; //this is the coordinator
if (macGetShortAddr() == dstSADDR) return(1); //to myself, should not happen, but return min value
currentParent = mac_pib.macCoordShortAddress; //start with my parent address
currentDepth = mac_pib.depth - 1; //depth of my parent.
do {
if (currentParent == dstSADDR) return(numHops); //destination is one of my parent nodes.
if (currentParent == 0) break; //at coordinator.
//compute the max SADDR address range of parent
maxSADDR = ntGetMaxSADDR(currentParent,currentDepth+1); //depth of parent's children
if ((dstSADDR > currentParent) && (dstSADDR <= maxSADDR)) {
//this address is in this router's range, stop going up.
break;
}
//go up a level
currentDepth--;
numHops++;
if (currentDepth == 0 ) currentParent =0;
else { currentParent = nwkFindParentSADDR(currentParent);
if (!currentParent) {
//could not find, set numHops to maximum and return
return(LRWPAN_MAX_DEPTH<<1);
}
}
}while(1);
nwkGetHopsToDest_down:
currentDepth++; //increment depth, as this should reflect my current children
//now search going down.
do {
//destination is in the current parent's range
//see if it is one of the routers or children.
//first see if it is one of the children of current parent
numHops++;
maxSADDR = ntGetMaxSADDR(currentParent,currentDepth);
if (dstSADDR > (maxSADDR-LRWPAN_MAX_NON_ROUTER_CHILDREN) &&
dstSADDR <= maxSADDR) break; //it is one of the children nodes
for (i=0; i<LRWPAN_MAX_ROUTERS_PER_PARENT; i++) {
if (i==0) currentRouter = currentParent+1;
else currentRouter += ntGetCskip(currentDepth);
if (dstSADDR == currentRouter) return(currentRouter);
maxSADDR = ntGetMaxSADDR(currentRouter,currentDepth+1);
if ((dstSADDR > currentRouter) && (dstSADDR <= maxSADDR))
break; //must go further down the tree
}
if (i == LRWPAN_MAX_ROUTERS_PER_PARENT) {
//must be one of my non-router children, increment hops, return
return(numHops);
}
currentDepth++;
currentParent = currentRouter;
}while(currentDepth < LRWPAN_MAX_DEPTH-1);
if (numHops > LRWPAN_NWK_MAX_RADIUS) {
DEBUG_STRING(DBG_ERR,"nwkGetHopsToDest: Error in hop calculation: ");
DEBUG_UINT8(DBG_ERR,numHops);
DEBUG_STRING(DBG_ERR,"\n");
numHops = LRWPAN_NWK_MAX_RADIUS-1;
}
return(numHops);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -