Ejemplo n.º 1
0
    def _trySendingFrame(self):
        """Only send if no carrier is sensed and we are not in backoff."""
        if self._transmitting or self._outstandingFrame:
            # Another frame is currently being transmitted. Wait for next call.
            return
        if not self._transmitQueue:
            # Nothing to transmit.
            return
        if self._backingOff:
            # Still waiting backoff
            return

        if self._device.phy.carrierSense():
            # Channel is occupied. Do backoff. *** COLLISION AVOIDANCE ***
            self._backingOff = True
            SCHEDULE(self._computeBackoff(), self._endBackoff)
            ACTIVITY_INDICATION(self, "tx", "CA backoff", "darkblue", 1, 2)
            return

        type, dstAddr, bitstream = self._transmitQueue.pop(0)
        if type == self.ACK:
            # Create a new Ack frame and send it.
            ACTIVITY_INDICATION(self, "tx", "ACK/NAK", "grey", 0, 0)
            self._phySendFrame(dstAddr=dstAddr, data="")
        else:
            if type == self.RETR:
                self.packetRetransmissions += 1
                ACTIVITY_INDICATION(self, "tx", "Resend", "orange", 0, 0)
            else:
                ACTIVITY_INDICATION(self, "tx", "Send", "yellow", 0, 0)
                self._resetBackoff()
                self.packetsSent += 1
            self._retransmissionTimer = SCHEDULE(self.retransmissionTimeout,
                                                 self._timeout)
            self._outstandingFrame = self._phySendFrame(dstAddr, bitstream)
Ejemplo n.º 2
0
    def _checkData(self, frame):
        """Look if the frame contains payload data and handle it."""
        if len(frame.data) != 0:
            # If frame is inside the reception window, then accept it
            if (frame.SN - self._VR) % self._SN_MOD < self._winSize:
                ACTIVITY_INDICATION(self, "rx", "Rcv OK SN=%s" % str(frame.SN))
                self._receiveBuffer[frame.SN] = frame.data

                # If it is the next expected sequence number, then we can
                # pass some data to the upper layers
                bitstream = self._receiveBuffer.pop(self._VR, None)
                while bitstream != None:
                    for upperLayer in self._upperLayers:
                        upperLayer.receive(bitstream)
                    self._VR = (self._VR + 1) % self._SN_MOD
                    bitstream = self._receiveBuffer.pop(self._VR, None)

                # Send an Ack for _this_ frame
                self._sendACK(self.ACK, frame.SN)
            else:
                # Frame contains a wrong sequence number.
                # If it is and old packet, acknowledge it, otherwise
                # send a SREJ for the first missing packet
                if (self._VR - frame.SN) % self._SN_MOD < self._winSize + 1:
                    self._sendACK(self.ACK, frame.SN)
                    ACTIVITY_INDICATION(self, "rx",
                                        "Send old ACK RN=%s" % str(frame.SN))
                else:
                    ACTIVITY_INDICATION(self, "rx",
                                        "Rcv wrong RN=%s" % str(frame.SN))
                    self.sequenceErrors += 1
                    self._sendACK(self.SREJ, self._VR)
Ejemplo n.º 3
0
    def _trySendingFrame(self):
        """Send the next frame waiting in the transmitQ, if there is any."""
        if self._transmitting or self._outstandingFrame:
            # Another frame is currently being transmitted. Wait for next call.
            return
        if not self._transmitQueue:
            # Nothing to transmit.
            return

        type, dstAddr, bitstream = self._transmitQueue.pop(0)
        if type == self.ACK:
            # Create a new Ack frame and send it.
            ACTIVITY_INDICATION(self, "tx", "ACK/NAK", "grey", 0, 0)
            self._phySendFrame(dstAddr=dstAddr, data="")
        else:
            if type == self.RETR:
                self.packetRetransmissions += 1
                ACTIVITY_INDICATION(self, "tx", "Resend", "orange", 0, 0)
            else:
                ACTIVITY_INDICATION(self, "tx", "Send", "yellow", 0, 0)
                self._resetBackoff()
                self.packetsSent += 1
            self._retransmissionTimer = SCHEDULE(self.retransmissionTimeout,
                                                 self._timeout)
            self._outstandingFrame = self._phySendFrame(dstAddr, bitstream)
Ejemplo n.º 4
0
 def _timeout(self):
     """Called when a retransmission timeout occurs."""
     ACTIVITY_INDICATION(self, "tx", "TIMEOUT")
     self._retransmissionTimer = None
     self._consecutiveCollisions += 1
     self._backingOff = True
     ACTIVITY_INDICATION(self, "tx", "Retr backoff", "blue", 1, 2)
     SCHEDULE(self._computeBackoff(), self._endBackoff)
Ejemplo n.º 5
0
    def _trySendingFrame(self):
        """Send the next frame waiting in the sendBuffer, if there is any."""
        if self._transmitting:
            # Another frame is currently being transmitted. Wait for next call.
            return
        if not self._transmitQueue:
            # Nothing to transmit.
            return

        type, sn = self._transmitQueue.pop(0)
        if type == self.ACK or type == self.SREJ:
            # Create a new Ack frame and send it.
            ack = self._newFrame()
            ack.SN = self._SNmax  # Allowed since payload is empty
            ack.RN = sn
            if type == self.SREJ:
                ack.SREJ = 1
                ACTIVITY_INDICATION(self, "tx",
                                    "Send SREJ RN=%s" % str(ack.RN), "red", 0,
                                    0)
            else:
                ACTIVITY_INDICATION(self, "tx", "Send ACK RN=%s" % str(ack.RN),
                                    "grey", 0, 0)
            checksum = crc32(ack.serialize()[:-4]) & ((1L << 32) - 1)
            ack.FCS = checksum
            self._transmitting = True
            self._device.phy.send(ack.serialize())

        else:
            assert (type == self.FIRSTTR or type == self.RETR)
            # Create a new data packet and send it
            bitstream = self._sendBuffer[sn]
            frame = self._newFrame()
            frame.SN = sn
            frame.RN = self._VR
            frame.data = bitstream
            checksum = crc32(frame.serialize()[:-4]) & ((1L << 32) - 1)
            frame.FCS = checksum

            # Set the retransmission timer
            if sn in self._retransmissionTimer:
                timer = self._retransmissionTimer.pop(sn)
                CANCEL(timer)
            self._retransmissionTimer[sn] = SCHEDULE(
                self.retransmissionTimeout, self._timeout, (sn, ))

            # Send the frame and update the statistics
            if type == self.RETR:
                self.packetRetransmissions += 1
                ACTIVITY_INDICATION(self, "tx", "Retr SN=%s" % str(frame.SN),
                                    "orange", 0, 0)

            else:
                ACTIVITY_INDICATION(self, "tx", "Send SN=%s" % str(frame.SN),
                                    "yellow", 0, 0)
            self.packetsSent += 1
            self._transmitting = True
            self._device.phy.send(frame.serialize())
Ejemplo n.º 6
0
    def _checkAck(self, frame):
        """Look if the frame contains an ACK or SREJ and handle it."""

        if self._SNmin == self._SNmax:
            # We do not expect a new ack.
            return

        RN = frame.RN
        if frame.SREJ:
            # This is a selective repeat request. Retransmit RN
            # if the window allows it
            if ((RN - self._SNmin) % self._SN_MOD <
                (self._SNmax - self._SNmin) % self._SN_MOD):
                ACTIVITY_INDICATION(self, "rx", "SREJ RN=%s" % str(RN))
                self._retransmit(RN)
                return

        if ((RN - self._SNmin) % self._SN_MOD >
            (self._SNmax - self._SNmin) % self._SN_MOD):
            # ACK outside window. Do nothing
            ACTIVITY_INDICATION(self, "rx", "DupACK RN=%s" % str(RN))
            return

        # RN is inside the window. In contrast to Go-back-n, it only
        # acknowledges one packet, not all packets before RN
        ACTIVITY_INDICATION(self, "rx", "Rcv ACK RN=%s" % str(RN))
        bitstream = self._sendBuffer.pop(RN, None)
        if bitstream:
            if (self.RETR, RN) in self._transmitQueue:
                self._transmitQueue.remove((self.RETR, RN))
            timer = self._retransmissionTimer.pop(RN, None)
            if timer:
                CANCEL(timer)

            # Let's see if we can move the window. Move it up to the first non
            # acknowledged packet.
            while (self._SNmin != self._SNmax
                   and self._SNmin not in self._sendBuffer):
                assert ((self.FIRSTTR, self._SNmin) not in self._transmitQueue)
                # Move the left window edge and see if we can accept new frames
                self._SNmin = (self._SNmin + 1) % self._SN_MOD
                if (self._SNmax - self._SNmin) % self._SN_MOD < self._winSize:
                    self._device.XOFF = False

            # Inform the upper layer that it can sent the next packet
            # @@@ FIXME: this is not clean. Better provide a queue
            for upperLayer in self._upperLayers:
                upperLayer.sendStatus(0, bitstream)
Ejemplo n.º 7
0
    def _checkAck(self, frame):
        """Look if the frame contains an ACK and handle it."""
        if self._outstandingFrame != None:  # We are waiting for an ACK
            if frame.RN == (self._VS[frame.SrcAddr] + 1) % 2:
                # POSITIVE ACKNOWLEDGEMENT
                ACTIVITY_INDICATION(self, "rx", "ACK ok")
                self._outstandingFrame = None
                if self._retransmissionTimer:
                    CANCEL(self._retransmissionTimer)
                self._retransmissionTimer = None
                self._VS[frame.SrcAddr] = frame.RN

                # Do a backoff. *** COLLISION AVOIDANCE ***
                self._backingOff = True
                SCHEDULE(self._computeBackoff(), self._endBackoff)
                ACTIVITY_INDICATION(self, "tx", "CA backoff", "darkblue", 1, 2)
Ejemplo n.º 8
0
    def _backoff(self):
        """Compute backoff and schedule retransmission.

        This method is called after the end of the jam transmission. In half
        duplex mode, it does the following:
        - compute a backoff
        - enter backoff mode
        - schedule the retransmission of the frame.
        If the maximum number of collisions is already reached, abandon the
        frame and signal an error to the upper layer.
        """

        ACTIVITY_INDICATION(self, "tx", "backoff", "blue", 1, 2)
        self._jamming = False
        if self._transmissionAttemps >= 16:
            # Transmission failed. Update statistics, inform dl and clean up
            SCHEDULE(0.0, self._niu.dl.sendStatus,
                     (_EXCESSIVE_COLLISION_ERROR, self._sendBuffer))
            self.excessiveCollisions += 1
            print "Excessive collisions"
            self._transmissionAttemps = 0
            self._sendBuffer = None
            self._niu.XOFF = False
            return

        k = min(10, self._transmissionAttemps)
        r = int(random() * (1 << k))
        if self._niu.phy.getDataRate() == 1000e6:
            backoff = r * self._GIGA_SLOTTIME * self._niu.phy.bittime()
        else:
            backoff = r * self._SLOTTIME * self._niu.phy.bittime()
        SCHEDULE(backoff, self._mediumAccess)
Ejemplo n.º 9
0
    def send(self, bitstream):
        """Encapsulate the data into a frame and send it to the phy layer.

        May only be called if self._device.XOFF is False, i.e. if the
        device is ready to accept a new data packet from the higher layer.
        """

        # Make sure there is no other packet already in transit.
        assert (self._device.XOFF == False and not self._sendBuffer)

        # Block any new transmission until this packet has been acknowledged
        self._device.XOFF = True

        # Create a new frame with CRC and sequence numbers.
        frame = self._newFrame()
        frame.SN = self._VS
        self._VS = (self._VS + 1) % 2
        frame.RN = self._VR
        frame.data = bitstream
        checksum = crc32(frame.serialize()[:-4]) & ((1L << 32) - 1)
        frame.FCS = checksum

        # Set the retransmission timer
        self._sendBuffer = frame
        self._retransmissionTimer = SCHEDULE(self.retransmissionTimeout,
                                             self._timeout)

        # Sent the frame
        ACTIVITY_INDICATION(self, "tx", "Send", "yellow", 0, 0)
        self.packetsSent += 1
        self._device.phy.send(frame.serialize())
        return 0
Ejemplo n.º 10
0
 def sendStatus(self, status, bitstream):
     """Called by the phy layer when a transmission is completed.
     """
     assert (status == 0)  # Make sure the packet has been sent correctly
     ACTIVITY_INDICATION(self, "tx")
     self._device.phy.transmitting(False)
     self._transmitting = False
     self._trySendingFrame()
Ejemplo n.º 11
0
 def _checkData(self, frame):
     """Look if the frame contains payload data and handle it."""
     if len(frame.data) != 0:
         if frame.SN == self._VR.get(frame.SrcAddr, 0):
             # Frame contains the next expected SN
             ACTIVITY_INDICATION(self, "rx", "Data OK")
             self.packetsReceivedOK += 1
             # Sent an acknowledgement
             self._VR[frame.SrcAddr] = (frame.SN + 1) % 2
             self._sendACK(frame.SrcAddr)
             # Pass it to the upper layer
             for upperLayer in self._upperLayers:
                 upperLayer.receive(frame.data)
         else:
             # Frame contains a wrong sequence number. Resent last ack.
             ACTIVITY_INDICATION(self, "rx", "Wrong SN")
             self.sequenceErrors += 1
             self._sendACK(frame.SrcAddr)
Ejemplo n.º 12
0
    def sendStatus(self, status, bitstream):
        """Called by the phy layer when a transmission is completed.
        """
        assert (status == 0)  # Make sure the packet has been sent correctly
        ACTIVITY_INDICATION(self, "tx")
        self._transmitting = False

        # See if there are another frame waiting for transmission
        self._trySendingFrame()
Ejemplo n.º 13
0
 def _checkAck(self, frame):
     """Look if the frame contains an ACK and handle it."""
     if self._sendBuffer != None:  # We are waiting for an ACK
         if frame.RN == self._VS:
             # POSITIVE ACKNOWLEDGEMENT
             ACTIVITY_INDICATION(self, "rx", "ACK")
             bitstream = self._sendBuffer.data
             self._sendBuffer = None
             CANCEL(self._retransmissionTimer)
             self._retransmissionTimer = None
             self._device.XOFF = False  # Allow the next packet to be sent
             # Inform the upper layer that it can sent the next packet
             # @@@ FIXME: this is not clean. Better provide a queuing layer
             for upperLayer in self._upperLayers:
                 upperLayer.sendStatus(0, bitstream)
         else:
             # NEGATIVE ACKNOWLEDGEMENT. Retransmit the packet.
             ACTIVITY_INDICATION(self, "rx", "NAK")
             self._retransmit()
Ejemplo n.º 14
0
 def _checkData(self, frame):
     """Look if the frame contains payload data and handle it."""
     if len(frame.data) != 0:
         if frame.SN == self._VR:
             # Frame contains the next expected SN
             ACTIVITY_INDICATION(self, "rx", "Rcv OK SN=%s" % str(frame.SN))
             self.packetsReceivedOK += 1
             # Sent an acknowledgement
             self._VR = (self._VR + 1) % self._SN_MOD
             self._sendACK()
             # Pass it to the upper layer
             for upperLayer in self._upperLayers:
                 upperLayer.receive(frame.data)
         else:
             # Frame contains a wrong sequence number. Request missing pkt.
             ACTIVITY_INDICATION(self, "rx",
                                 "Rcv wrong SN=%s" % str(frame.SN))
             self.sequenceErrors += 1
             self._sendACK()
Ejemplo n.º 15
0
    def _sendACK(self):
        """Send an acknowledgement with the next RN to be received."""
        # Create a new frame with CRC and sequence numbers.
        ack = self._newFrame()
        ack.SN = self._VS
        ack.RN = self._VR  # This decides whether it is an ACK or a NAK
        checksum = crc32(ack.serialize()[:-4]) & ((1L << 32) - 1)
        ack.FCS = checksum

        # Sent the acknowledgement
        ACTIVITY_INDICATION(self, "tx", "ACK/NAK", "grey", 0, 0)
        self._device.phy.send(ack.serialize())
Ejemplo n.º 16
0
 def _checkAck(self, frame):
     """Look if the frame contains an ACK and handle it."""
     if self._outstandingFrame != None:  # We are waiting for an ACK
         if frame.RN == (self._VS[frame.SrcAddr] + 1) % 2:
             # POSITIVE ACKNOWLEDGEMENT
             ACTIVITY_INDICATION(self, "rx", "ACK ok")
             self._outstandingFrame = None
             if self._retransmissionTimer:
                 CANCEL(self._retransmissionTimer)
             self._retransmissionTimer = None
             self._VS[frame.SrcAddr] = frame.RN
             self._trySendingFrame()
Ejemplo n.º 17
0
    def sendStatus(self, status, bitstream):
        """Terminate the transmission, inform dl, and clean up.

        This method is called from the phy layer, when a transmission
        previously initiated with PHY.send terminates.
        First check if we are sending a jam. In this case, the jam
        transmission has completed. Switch of the transmission and call the
        backoff method.
        If not jamming, terminate the transmission, update the statistics,
        clean up and inform the upper layer.

        A status==0 indicates success. Any other status indicates an error.
        """
        self._latestTransmitActivity = TIME()

        if self._jamming:
            ACTIVITY_INDICATION(self, "tx")
            self._niu.phy.transmitting(False)
            self._backoff()
            return

        ACTIVITY_INDICATION(self, "tx")
        self._niu.phy.transmitting(False)  # Terminate the transmission
        if not status:
            self.framesTransmittedOK += 1
            self.octetsTransmittedOK += len(self._sendBuffer.data)
            if self._transmissionAttemps > 2:
                self.multipleCollisionFrames += 1
            if self._transmissionAttemps == 2:
                self.singleCollisionFrames += 1
        else:
            # Discard the frame and inform DL (LLC)
            self.octetsTransmittedError += len(self._sendBuffer.data)
            status = _UNKNOWN_TRANSMISSION_ERROR

        SCHEDULE(0.0, self._niu.dl.sendStatus, (status, self._sendBuffer))
        self._transmissionAttemps = 0
        self._sendBuffer = None
        self._niu.XOFF = False
Ejemplo n.º 18
0
    def _retransmit(self):
        """Retransmits the current frame.

        Called either because of a negative ack or by a retransmission timeout.
        """
        ACTIVITY_INDICATION(self, "tx", "Retransmit", "orange", 0, 0)
        if self._retransmissionTimer:
            CANCEL(self._retransmissionTimer)
        self._retransmissionTimer = SCHEDULE(self.retransmissionTimeout,
                                             self._timeout)
        self.packetRetransmissions += 1
        self.packetsSent += 1
        self._device.phy.send(self._sendBuffer.serialize())
Ejemplo n.º 19
0
    def receive(self, bitstream):
        """Receive a bitstream from the PHY layer, test it and pass it upwards.

        According to the standard, Section 4.2.4, this function has to
        - eliminate collision fragments (smaller than the minimum size)
        - discard carrierExtension in 1000 Mb/s mode
        - disassemble frame
        - check if destination address has to be accepted
        - check FCS sequence
        - if everything OK, pass the fields to the data link layer (LLC).
        """

        self._latestReceiveActivity = TIME()

        # Discard collision fragments that are shorter than a minimum frame
        if len(bitstream) < self._MIN_FRAMESIZE + 8:
            return

        # Chop of carrier extension in 1000 Mb/s mode.
        # Carrier extension is modeled as '\x00' octets.
        # @@@ FIXME FCS could be confused with carrier extension
        if (len(bitstream) == self._GIGA_SLOTTIME / 8 + 8
                and self._niu.phy.getDataRate() == 1000e6
                and self._niu.phy.getDuplexMode() == HALF_DUPLEX):
            bitstream = bitstream.rstrip('\x00')

        # Parse the bitstream into a PDU format
        frame = self._PDU()
        frame.fill(bitstream)

        # Check if the frame shall be accepted
        destAddr = frame.destAddr
        if destAddr != self.address and destAddr not in self._addressFilter:
            return

        # Check FCS. Exclude preamble, SFD and FCS field
        checksum = crc32(bitstream[8:-4]) & (
            (1L << 32) - 1)  # take lower 32 bit
        if checksum != frame.FCS:
            print "FCS error"
            self.frameCheckSequenceErrors += 1
            return

        ACTIVITY_INDICATION(self, "rx", "receive")
        # All is correct. Deliver the frame content to the data link layer
        self.framesReceivedOK += 1
        self.octetsReceivedOK += len(frame.data)
        self._niu.dl.receive(destAddr, frame.srcAddr, frame.typeOrLength,
                             frame.data)
Ejemplo n.º 20
0
    def _checkAck(self, frame):
        """Look if the frame contains an ACK and handle it."""
        RN = frame.RN

        # Test if the RN is inside the window
        if self._SNmin == self._SNmax:
            # We do not expect a new ack.
            return

        if ((RN - self._SNmin) % self._SN_MOD >
            (self._SNmax - self._SNmin) % self._SN_MOD):
            # ACK outside window. Do nothing
            ACTIVITY_INDICATION(self, "rx", "DupACK RN=%s" % str(RN))
            return

        # RN is inside the window and acknowledges all frames before RN.
        # Remove the acknowledged frames from the window, transmission
        # queue and cancel the timers.
        ACTIVITY_INDICATION(self, "rx", "Rcv ACK RN=%s" % str(RN))
        while self._SNmin != RN:
            assert ((self.FIRSTTR, self._SNmin) not in self._transmitQueue)
            if (self.RETR, self._SNmin) in self._transmitQueue:
                self._transmitQueue.remove((self.RETR, self._SNmin))
            bitstream = self._sendBuffer.pop(self._SNmin)
            timer = self._retransmissionTimer.pop(self._SNmin, None)
            if timer:
                CANCEL(timer)
            # Move the left window edge and see if we can accept new frames.
            self._SNmin = (self._SNmin + 1) % self._SN_MOD
            if (self._SNmax - self._SNmin) % self._SN_MOD < self._winSize:
                self._device.XOFF = False

            # Inform the upper layer that it can sent the next packet
            # @@@ FIXME: this is not clean. Better provide a queue
            for upperLayer in self._upperLayers:
                upperLayer.sendStatus(0, bitstream)
Ejemplo n.º 21
0
 def _endBackoff(self):
     """Called at the end of a backoff, either because of a collision
     or for collision avoidance.
     """
     ACTIVITY_INDICATION(self, "tx")
     self._backingOff = False
     if self._outstandingFrame:
         # There is an outstanding frame. The backoff was therefore because
         # of a collision of this frame and we have to retransmit this
         # frame
         self._retransmit()
     else:
         # The backoff was because of collision avoidance, either
         # because the channel was found occupied or after a successful
         # transmission. See if we can transmit the next frame.
         self._trySendingFrame()
Ejemplo n.º 22
0
    def receive(self, bitstream):
        """Receive a frame from the phy layer.

        The frame can contain payload data and/or and acknowledgement.
        """
        # Parse the bit stream, fill it into a PDU and test the CRC
        frame = self._newFrame()
        frame.fill(bitstream)
        checksum = crc32(frame.serialize()[:-4]) & ((1L << 32) - 1)
        if frame.FCS != checksum:
            # CRC ERROR. Discard the packet and do nothing.
            ACTIVITY_INDICATION(self, "rx", "CRC error")
            self.crcErrors += 1
            return

        self._checkAck(frame)
        self._checkData(frame)
Ejemplo n.º 23
0
    def collisionDetect(self):
        """In half duplex, send jam, compute backoff and schedule retransmit.

        This method is called from the PHY layer to indicate a collision.
        It implements the behavior described in the standard, Sec. 4.2.3.2.4
        (collision detection and enforcement).
        
        First check if we are already sending a jam. In this case do nothing.
        Otherwise, if we are in half duplex mode, enter jamming mode and
        send jam to enforce the collision.
        """

        if self._jamming or self._niu.phy.getDuplexMode() == FULL_DUPLEX:
            return

        ACTIVITY_INDICATION(self, "tx", "JAM", "red", 0, 2)
        self._jamming = True
        self._niu.phy.send('\x00' * self._JAMSIZE)
Ejemplo n.º 24
0
    def receive(self, bitstream):
        """Receive a frame from the phy layer.

        The frame can contain payload data and/or and acknowledgement.
        """
        # Parse the bit stream, fill it into a PDU and test the CRC
        if ord(bitstream[0]) != self._srcAddress:
            # This is dirty but fast!
            return

        frame = self._newFrame()
        frame.fill(bitstream)
        checksum = crc32(frame.serialize()[:-4]) & ((1L << 32) - 1)
        if frame.FCS != checksum:
            # CRC ERROR. Discard the packet and do nothing.
            ACTIVITY_INDICATION(self, "rx", "CRC error")
            self.crcErrors += 1
            return
        if frame.DstAddr != self._srcAddress:
            # Frame is not for me. Ignore it.
            return
        self._checkAck(frame)
        self._checkData(frame)
Ejemplo n.º 25
0
    def _timeout(self, sn):
        """Called when a retransmission timeout occurs."""

        ACTIVITY_INDICATION(self, "tx", "TIMEOUT SN=%s" % str(sn))
        del self._retransmissionTimer[sn]
        self._retransmit(sn)
Ejemplo n.º 26
0
 def sendStatus(self, status, bitstream):
     """Called by the phy layer when a transmission is completed.
     """
     assert (status == 0)  # Make sure the packet has been sent correctly
     ACTIVITY_INDICATION(self, "tx")
Ejemplo n.º 27
0
 def _timeout(self):
     """Called when a retransmission timeout occurs."""
     ACTIVITY_INDICATION(self, "tx", "TIMEOUT")
     self._retransmissionTimer = None
     self._retransmit()
Ejemplo n.º 28
0
 def _timeout(self):
     """Called when a retransmission timeout occurs."""
     ACTIVITY_INDICATION(self, "tx", "TIMEOUT")
     self._retransmissionTimer = None
     self._consecutiveCollisions += 1
     SCHEDULE(self._computeBackoff(), self._retransmit)
Ejemplo n.º 29
0
    def _mediumAccess(self):
        """Acquire the transmit medium, transmit the frame and inform dl.

        This function tries to transmit a current frame according to the
        CSMA/CD algorithm, as described in the standard, Section 4.2.3.2.
        The following elements of the standard are implemented:
          - Half duplex transmission: CSMA/CD
          - Full duplex transmission
          - Carrier sense (in half duplex)
          - Interframe spacing (in half and full duplex)
          - Collision detection and enforcement through jam (in half duplex)
          - Exponential backoff and retransmission (half duplex)
          - Carrier extension (in half duplex for data rate > 100 Mb/s
        The following elements are not implemented:
          - Frame bursting (used for data rates > 100 Mb/s).
        """

        assert (self._sendBuffer != None)

        if self._niu.phy.getDuplexMode() == FULL_DUPLEX:

            # Transmission without contention. Only respect interframe gap
            gaptime = self._INTERFRAME_GAP * self._niu.phy.bittime()
            currentgap = TIME() - self._latestTransmitActivity
            if currentgap < gaptime:
                ACTIVITY_INDICATION(self, "tx", "gaptime", "grey", 3, 2)
                SCHEDULE(gaptime - currentgap, self._mediumAccess)
                return
            self._transmissionAttemps += 1
            ACTIVITY_INDICATION(self, "tx", "send FD", "green", 0, 0)
            self._niu.phy.transmitting(activate=True)
            self._niu.phy.send(self._sendBuffer.serialize())
            return

        else:  # Transmission in half duplex mode

            # 1. Carrier sense
            if self._niu.phy.carrierSense():
                ACTIVITY_INDICATION(self, "tx", "carrierSense", "blue", 3, 2)
                self._waitingForIdleChannel = True
                # Wait until channel activities end. The MAC.channelIdle
                # method will call us then
                return
            self._waitingForIdleChannel = False

            # 2. Interframe gap
            gaptime = self._INTERFRAME_GAP * self._niu.phy.bittime()
            currentgap = TIME() - max(self._latestTransmitActivity,
                                      self._latestReceiveActivity)
            if gaptime - currentgap > self._niu.phy.bittime() / 100:
                ACTIVITY_INDICATION(self, "tx", "gaptime", "grey", 3, 2)
                gapjitter = gaptime * random() / 100  # Avoid dicrete synchro.
                SCHEDULE(gaptime - currentgap + gapjitter, self._mediumAccess)
                return
            # 3. Here we go. Initiate the transmission. Wait for the
            #    transmissionCompleted or collisionDetect signal
            self._transmissionAttemps += 1
            ACTIVITY_INDICATION(self, "tx", "send HD", "green", 0, 0)
            self._niu.phy.transmitting(activate=True)
            self._niu.phy.send(self._sendBuffer.serialize())
            return