예제 #1
0
        private static void OnSendStatus(IMAC macInstance, DateTime time, SendPacketStatus ACKStatus, uint transmitDestination, ushort index)
        {
            var pipe = macInstance as MACPipe;

            switch (ACKStatus)
            {
            case SendPacketStatus.SendACKed:
#if DBG_DIAGNOSTIC
                Debug.Print("\t\tNet Manager: Retry queue length = " + _retriedPackets.Count);
#endif
#if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " ACKed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumReceivedInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numReceivedInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumReceivedInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumReceivedInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numReceivedInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumReceivedInCurrentWindow());
#endif
                    }
                }

                if (_retriedPackets.Contains(index))     // If this was a re-try, remove packet from queue
                {
                    _retriedPackets.Remove(index);
                }
                break;

            case SendPacketStatus.SendNACKed:
                    #if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " NACKed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                    }
                }
                break;

            case SendPacketStatus.SendFailed:
#if DBG_DIAGNOSTIC
                Debug.Print("\t\tNet Manager: Retry queue length = " + _retriedPackets.Count);
#endif

#if !DBG_LOGIC
                Debug.Print("Heartbeat to " + transmitDestination.ToString() + " failed");
#endif
                // Update link metrics
                if ((ushort)transmitDestination == RoutingGlobal.Parent)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for parent " + transmitDestination + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                }
                else
                {
                    byte cindex = CandidateTable.findIndex((ushort)transmitDestination);
                    if (cindex < byte.MaxValue)
                    {
                        CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for candidate " + transmitDestination + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                    }
                }

                // Retry
                if (!_retriedPackets.Contains(index) && RoutingGlobal._color == Color.Green)     // If packet not there, enqueue it and retry it once
                {
                    RoutingGlobal.CleanseCandidateTable(pipe);
                    Candidate tmpBst = CandidateTable.GetBestCandidate(false);
                    NetManagerGlobal.TempParent = tmpBst.GetMacID();
                    byte[] msg = new byte[NetManagerGlobal.HeartbeatMessageSize];
                    if (pipe.GetMsgWithMsgID(ref msg, index) == DeviceStatus.Success)
                    {
                        NetManagerGlobal.SendToTempParent(pipe, msg, msg.Length);
                        tmpBst.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for TempParent " + transmitDestination + "; new value = " + tmpBst.GetNumTriesInCurrentWindow());
#endif
                        _retriedPackets.Add(index);
                    }
                }
                else     // Retried once; drop packet
                {
                    _retriedPackets.Remove(index);
                }
                break;

            default:
                break;
            }
        }
        /*CAUTION: Any change in the advanced heartbeat structure should be accounted for in variables
         * NetManagerGlobal.AdvHeartbeatFixedSize and NetManagerGlobal.EachNeighborInfoSize
         */
        private static void Send_AdvancedHeartbeat(object state)
        {
            ushort[] neighbors = MACBase.NeighborListArray();
            _neighborInfoManagerPipe.MACBase.MACNeighborList(neighbors);

            // Find the number of neighbors
            byte num_nbrs = 0;

            for (int i = 0; i < neighbors.Length; i++)
            {
                if (neighbors[i] == 0) // At the end
                {
                    break;
                }
                num_nbrs++;
            }

            if (num_nbrs == 0)
            {
                return;
            }

            _numBeat++;

            ushort[] valid_nbrs;
            byte[]   nbrStatus;
            ushort[] numSamplesRec;
            ushort[] numSyncSent;
            byte[]   avgRSSI;
            byte[]   ewrnp;
            byte[]   isAvailableForUpperLayers;

            // TODO: Make this if-else more compact
            if (num_nbrs <= NetManagerGlobal.MaxNeighborsPerHeartbeat) // Send all information
            {
                valid_nbrs                = new ushort[num_nbrs];
                nbrStatus                 = new byte[num_nbrs];
                numSamplesRec             = new ushort[num_nbrs];
                numSyncSent               = new ushort[num_nbrs];
                avgRSSI                   = new byte[num_nbrs];
                ewrnp                     = new byte[num_nbrs];
                isAvailableForUpperLayers = new byte[num_nbrs];

                // Initialize ewrnp array with maxEtx
                for (int i = 0; i < ewrnp.Length; i++)
                {
                    ewrnp[i] = RoutingGlobal.MaxEtx;
                }

                for (int i = 0; i < num_nbrs; i++)
                {
                    var      nbr_name = neighbors[i];
                    Neighbor nbr      = _neighborInfoManagerPipe.NeighborStatus(nbr_name);

                    valid_nbrs[i]    = nbr_name;
                    nbrStatus[i]     = (byte)nbr.NeighborStatus;
                    numSamplesRec[i] = nbr.NumOfTimeSamplesRecorded;
                    numSyncSent[i]   = nbr.NumTimeSyncMessagesSent;
                    avgRSSI[i]       = (byte)((nbr.ReceiveLink.AverageRSSI + nbr.SendLink.AverageRSSI)); // * 0.5;

                    int index = CandidateTable.findIndex(nbr_name);
                    if (RoutingGlobal.Parent == nbr_name)
                    {
                        ewrnp[i] = RoutingGlobal.GetPathEWRNP();
                    }
                    else if (index < byte.MaxValue)
                    {
                        ewrnp[i] = (byte)CandidateTable._candidateList[index].GetPathEWRNP();
                    }

                    isAvailableForUpperLayers[i] = nbr.IsAvailableForUpperLayers ? (byte)1 : (byte)0;
                }
            }
            else // Starting with the current head pointer, use neighbor list as a circular array to send out info for NetManagerGlobal.MaxNeighborsPerHeartbeat consecutive neighbors
            {
                valid_nbrs                = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                nbrStatus                 = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                numSamplesRec             = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                numSyncSent               = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                avgRSSI                   = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                ewrnp                     = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                isAvailableForUpperLayers = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];

                // Initialize ewrnp array with maxEtx
                for (int i = 0; i < ewrnp.Length; i++)
                {
                    ewrnp[i] = RoutingGlobal.MaxEtx;
                }

                for (int i = 0; i < NetManagerGlobal.MaxNeighborsPerHeartbeat; i++)
                {
                    // If current head pointer has a higher index than number of neighbors (owing to loss), restart at index 0; otherwise, start at current head pointer
                    circ_headptr = (circ_headptr < num_nbrs) ? (byte)(circ_headptr % num_nbrs) : (byte)0;
                    var      nbr_name = neighbors[circ_headptr];
                    Neighbor nbr      = _neighborInfoManagerPipe.NeighborStatus(nbr_name);

                    valid_nbrs[i]    = nbr_name;
                    nbrStatus[i]     = (byte)nbr.NeighborStatus;
                    numSamplesRec[i] = nbr.NumOfTimeSamplesRecorded;
                    numSyncSent[i]   = nbr.NumTimeSyncMessagesSent;
                    avgRSSI[i]       = (byte)((nbr.ReceiveLink.AverageRSSI + nbr.SendLink.AverageRSSI)); // * 0.5;

                    int index = CandidateTable.findIndex(nbr_name);
                    if (RoutingGlobal.Parent == nbr_name)
                    {
                        ewrnp[i] = RoutingGlobal.GetPathEWRNP();
                    }
                    else if (index < byte.MaxValue)
                    {
                        ewrnp[i] = (byte)CandidateTable._candidateList[index].GetPathEWRNP();
                    }

                    isAvailableForUpperLayers[i] = nbr.IsAvailableForUpperLayers ? (byte)1 : (byte)0;

                    circ_headptr = (byte)((circ_headptr + 1) % num_nbrs);
                }

                // Adjust circular buffer head pointer at the end
                circ_headptr = (byte)((circ_headptr + 1) % num_nbrs);
            }

#if DBG_DIAGNOSTIC
            SystemGlobal.PrintNumericVals("Neighbor names: ", valid_nbrs);
            SystemGlobal.PrintNumericVals("Neighbor status: ", nbrStatus);
            SystemGlobal.PrintNumericVals("Avg RSSI: ", avgRSSI);
            SystemGlobal.PrintNumericVals("Routing EWRNP: ", ewrnp);
            SystemGlobal.PrintNumericVals("# samples rcvd: ", numSamplesRec);
            SystemGlobal.PrintNumericVals("# timesync sent: ", numSyncSent);
            SystemGlobal.PrintNumericVals("Available for upper layers: ", isAvailableForUpperLayers);
            Debug.Print("Parent: " + RoutingGlobal.Parent);
            Debug.Print("");
#endif

            var size = NetManagerGlobal.MoteMessages.Compose.Heartbeat(NetManagerGlobal.MsgBytes, _neighborInfoManagerPipe.MACRadioObj.RadioAddress, (ushort)_numBeat, SystemGlobal.NodeType, RoutingGlobal.Parent, (byte)RoutingGlobal.GetPathEWRNP(), valid_nbrs, nbrStatus, numSamplesRec, numSyncSent, avgRSSI, ewrnp, isAvailableForUpperLayers, RoutingGlobal.Infinity);
            //var size = NetManagerGlobal.MoteMessages.Compose.Heartbeat(NetManagerGlobal.MsgBytes, _neighborInfoManagerPipe.MACRadioObj.RadioAddress, (ushort)_numBeat, SystemGlobal.NodeType, RoutingGlobal.Parent, (byte)RoutingGlobal.BestEtx, neighbors, nbrStatus, avgRSSI, ewrnp);
#if !DBG_LOGIC
            Debug.Print("NeighborInfo#" + _numBeat + " size: " + size);
#endif

            #region Uncomment when not using scheduler
            // If in a reset, do not forward TODO: Change this to "spray"
            if (RoutingGlobal._color == Color.Red)
            {
#if DBG_VERBOSE
                Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                return;
            }

            // If parent is available, pass it on
            if (RoutingGlobal.IsParent)
            {
                var status = RoutingGlobal.SendToParent(_neighborInfoManagerPipe, NetManagerGlobal.MsgBytes, size);
                if (status != 999)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                    if (!_sentPacketSizes.Contains(status))
                    {
                        _sentPacketSizes.Add(status, size);
                    }
                }
                else //Retry once
                {
#if !DBG_LOGIC
                    Debug.Print("Retrying packet");
#endif
                    RoutingGlobal.CleanseCandidateTable(_neighborInfoManagerPipe);
                    Candidate tmpBest = CandidateTable.GetBestCandidate(false);
                    NetManagerGlobal.TempParent = tmpBest.GetMacID();
                    status = NetManagerGlobal.SendToTempParent(_neighborInfoManagerPipe, NetManagerGlobal.MsgBytes, size);
                    if (status != 999)
                    {
                        tmpBest.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for TempParent " + NetManagerGlobal.TempParent + "; new value = " + tmpBest.GetNumTriesInCurrentWindow());
#endif
                        if (!_sentPacketSizes.Contains(status))
                        {
                            _sentPacketSizes.Add(status, size);
                        }
                    }
                }
            }
            #endregion
        }