I had to deal with this problem when I added support for protocols like PPP MP with a single sequence number that increments each fragment instead of separate sequence numbers and fragment numbers. (See Appendix A of RFC 4623 (PWE3 Fragmentation and Reassembly) for a list of protocols that use this style, including PPP MP (RFC 1990), PWE3 MPLS (RFC 4385), L2TPv2 (RFC 2661), L2TPv3 (RFC 3931), ATM, and Frame Relay.)
The problem happened in some long captures I had with some dropped packets and where the "short sequence number" variant was used for MLPPP, which is 12 bits (so a little bit bigger than the 8 bits with ZigBee, but not having separate fragment sequence numbers effectively costs a couple bits.) See in particular fragment_add_seq_single_aging(), and all the fragment_add_seq_single_* functions in general. My approach, which may not have been optimal, used a REASSEMBLE_FLAGS_AGING flag and a max_age parameter to discard partially reassembled fragments. When wireshark gets a new fragment and looks in the table of partially reassembled fragments to add it to, if the partially reassembled fragment comes from a frame number that is very old, that partially reassembled fragment is discarded. I ended up using the previously unused frame field of the partially reassembled fragment head for this (fh->frame), storing the frame number of most recently added fragment in this as well.
Take a look at those functions, as it may provide some help for your approach. It worked for me on those files that I had.