I left off last time explaining the transmit data path side of the Zigbee networking layer. The receive data path is fairly similar, but there are some minor complications.
When a frame arrives over the air, the radio driver will take it out of the buffer and store it somewhere. It should then signal the next higher layer (in this case the MAC) to retrieve the frame.
Incidentally, this part of incoming data handling is common to just about every protocol stack. I refer to it as the “launch” although I don’t know what the formal term is. I call it the launch because it’s the entry point of data into your stack. In general, most stacks that I’ve encountered handle things the same way where the hardware signals data arrival with an interrupt, the data is read out of the hardware buffers by the driver, it’s put into a holding area (list, queue, circular buffer), and then the next layer is signaled to pick it up when it can. This way, the ISR is kept short and frame dropping is minimized in the case of heavy traffic.
Anyways, back to the story. After the launch, the MAC layer would pick the frame up from its holding area, strip off and decode the MAC header, and then if it’s a MAC data frame, pass it up to the NWK layer.
The frame reaches the NWK layer via the MAC’s “Data Indication” service. Once in the network layer, the network header will get stripped off and processed. This is kind of the generic way to handle an incoming Zigbee frame and I think most stacks will do something fairly similar. From here, it pretty much depends on the implementation so I’ll describe how I handle the network frame processing in the FreakZ stack.
After I have the network header parsed and tucked away neatly inside a structure, the first thing that happens is that the frame needs to be decoded according to its type. There are only two frame types at the network layer: data frames and command frames. The frame type is contained in the header information so it’s easy to figure out what it is. In the case of a data frame, there are three cases that need to be handled:
The first case is the easiest one where the frame is meant for us. To determine this, you need to check the destination network address and see if it matches the device’s network address. As I mentioned in part 1, the destination address in the network header is absolute. So if the destination network address matches our network address, then we can be sure that we’re the final destination for this frame and just send it up to the next layer.
If the destination address doesn’t match our address, then the next thing I do is check to see if it’s a broadcast. If it’s a broadcast, then we need to initiate a special sequence of events because broadcasts need to be handled carefully. The dangerous thing about them is that broadcasts can grow exponentially if they’re not handled properly and they’ll quickly overwhelm the memory of your devices, causing your network to crash. I’ll be discussing broadcasts in more detail in the later parts where I examine each of the network services. Also, since a broadcast hop is still considered a hop, we need to decrement the frame's radius value. If you remember from part 1, the radius is used to limit the max number of hops a frame can travel. Basically any time a frame needs to be re-transmitted, the radius value will be decremented.
And finally, if we’re not the final destination for the frame, and it’s not a broadcast frame, that means that we’re just a hop on it’s way to the final destination. From there, the sequence of events is similar to the transmit data path discussed in part 1. We need to find the next hop address to send the frame, forward it there, and decrement the radius counter.
Since we have a commonality like this, I made a simple optimization where both the transmit and the receive side share the same forwarding function.
In the case that the incoming frame is a command frame, then I just decode it based on the command ID. This will always be the first byte of the payload so its fairly easy to get this value. From there, it’s just handled according to the management function that it needs to accomplish. The command frames in the network layer handle common network maintenance tasks like mesh route discovery, link maintenance, and rejoining and leaving the network. I’ll be going into this in more detail later on as well.
Hmmm…that went by a lot quicker than I expected. That's disappointing because it seemed much more difficult when I was writing it...Updated 2009-05-13: Thanks to some of the feedback from the readers as well as certain Zigbee spec authors, I changed how I discussed the radius handling. I previously had the radius decremented and checked at the entry point of the NWK rx function. However I changed it so that the radius is only checked if the frame will be re-transmitted. This is in compliance with the wording in the Zigbee specification on how the radius should be handled. The code was modified as well to reflect this.