Ejemplo n.º 1
0
    def retry(self, count=None):
        """Update retry count and set backoff parameters.

        :param count: If specified, `retrycount` will be set to this value;
                      otherwise, increment `retrycount`.

        Slot value `cslot` is set to a random integer between [0, CW), where
        the contention window CW is defined as:

            CW = CWmin + 2^`retrycount`
        """
        if count is None: count = self.retrycount + 1
        cwsize = min(self.cwmax, self.cwmin * (2**count) )
        self.cslot = random.randint(cwsize)
        self.retrycount = count
        # update RETRY flag if first retry
        if ((count==1) and self.isdot11data(self.datatosend)):
            pkt = self.get_dot11data(self.datatosend)
            dst = pkt.addr1
            errmsg = "[DCF]: Cannot retry() with broadcast packet!"
            assert (dst != self.broadcast), errmsg
            # update retry field
            pkt.FCfield |= DOT11_FC_RETRY
            self.datatosend = crcupdate(pkt)
        if count>0:
            self.log("retry%d"%(count), self.datatosend, retrycount=count, retrylimit=self.retrylimit)
Ejemplo n.º 2
0
 def TXRSH(self, fsm):
     """TXRSH state; overloaded to send RSH prior to DATA."""
     assert DCF.isdot11data(self, self.datatosend), \
             "[RBAR]: Cannot determine 'datatosend' in TXUCAST!"
     assert not (self.datatosend.addr1==self.broadcast), \
             "[RBAR]: Cannot send broadcast 'datatosend' in TXUCAST!"
     # update rate annotation
     data = self.get_dot11data(self.datatosend)
     dst, src = data.addr1, data.addr2
     rate = self.ra.get_rate(dst)
     data.setanno('phy-rate', rate)
     if not self.usecsma:
         # send RSH before sending DATA
         rsh = self.dot11rsh(addr1=dst, addr2=src)
         self.send_rsh(rsh, self.datatosend)
         # recalculate NAV from new rate information
         nav = self.rshnav(self.datatosend)
         rsh.ID = nav
         pkt = crcupdate(rsh)
         # send and hold for duration
         rate, length = pkt[RAI].rate, pkt[RAI].length
         self.log("RSH", pkt, nav=nav, rate=rate, length=length)
         duration = self.duration(pkt)
         self.log_send(pkt, nav=nav)
         yield self.TXD.send(fsm, [pkt])
         yield hold, fsm, duration
         # pause for SIFS before continuing
         yield hold, fsm, self.sifs
     # go to DCF.TXUCAST state
     OLDSTATE = lambda *args, **kwargs: DCF.TXUCAST(self, *args, **kwargs)
     yield fsm.goto(OLDSTATE)
Ejemplo n.º 3
0
    def get_rshduration(self, force=False):
        """Calculate duration of RSH message.

        :param force: If true, ignore any cached value.
        """
        if force or (self._rshduration is None):
            rsh = self.dot11rsh()
            pkt = crcupdate(rsh)
            self._rshduration = self.duration(pkt)
        return self._rshduration
Ejemplo n.º 4
0
    def get_ackduration(self, force=False):
        """Calculate duration of ack message.

        :param force: If true, ignore any cached value.
        """
        if force or (self._ackduration is None):
            ack = self.dot11ack()
            pkt = crcupdate(ack)
            self._ackduration = self.duration(pkt)
        return self._ackduration
Ejemplo n.º 5
0
    def get_ctsduration(self, force=False):
        """Calculate duration of CTS message.

        :param force: If true, ignore any cached value.
        """
        if force or (self._ctsduration is None):
            cts = self.dot11cts()
            pkt = crcupdate(cts)
            self._ctsduration = self.duration(pkt)
        return self._ctsduration
Ejemplo n.º 6
0
 def TXCTS(self, fsm, rts):
     """TXCTS state; send CTS response message."""
     assert self.isdot11rts(rts), "[DCF]: Cannot find RTS in TXCTS!"
     addr, addr1 = self.address, rts.addr2
     # create CTS
     pkt = self.dot11cts(addr1=addr1)
     cts = crcupdate(pkt)
     # update nav
     self.send_cts(cts, rts)
     nav = self.ctsnav(rts)
     cts.ID = nav
     pkt = crcupdate(cts)
     # pause for SIFS
     yield hold, fsm, self.sifs
     # send and hold duration
     duration = self.duration(pkt)
     self.log_send(pkt, addr=addr, addr1=addr1, nav=nav)
     yield self.TXD.send(fsm, [pkt])
     yield hold, fsm, duration
     # set NAV and resume
     yield self.navupdate(fsm, nav*1e-6)
     yield fsm.goto(self.RESUME)
Ejemplo n.º 7
0
 def TXACK(self, fsm, pkt):
     """TXACK state; transmit ACK message in response to `data`."""
     assert self.isdot11data(pkt), "[DCF]: Cannot find Dot11Data in TXACK!"
     data = self.get_dot11data(pkt)
     assert not (data.addr1==self.broadcast), \
             "[DCF]: Cannot send ACK for broadcast data!"
     addr1 = data.addr2
     ack = self.dot11ack(addr1=addr1)
     self.send_ack(ack)
     pkt = crcupdate(ack)
     # pause for SIFS
     yield hold, fsm, self.sifs
     # send and hold duration
     duration = self.duration(pkt)
     self.log_send(pkt, addr1=addr1, duration=duration)
     yield self.TXD.send(fsm, [pkt])
     yield hold, fsm, duration
     yield fsm.goto(self.RESUME)
Ejemplo n.º 8
0
 def TXDATA(self, fsm, pkt):
     """TXDATA state; initialize `datatosend` and associated parameters
     before transitioning to `BACKOFF`."""
     assert (self.datatosend is None), \
             "[DCF]: 'datatosend' already set in TXDATA!"
     assert (self.htype==const.ARP_HTYPE_ETHERNET), \
             "[DCF]: Unsupported hardware type (%s)!"%(self.htype)
     assert isinstance(pkt, Ether) and pkt.haslayer(Ether), \
             "[DCF]: Got non-Ether packet in TXDATA!"
     # process Ethernet frame
     eth = pkt[Ether]
     addr, src, dst = self.addr, eth.src, eth.dst
     pkt = crcupdate(eth)
     # initialize datatosend and other parameters
     self.datatosend = self.encapsulate(pkt, src=src, dst=dst)
     isbroadcast = (dst==self.broadcast)
     self.retry(count=0)
     if isbroadcast: self.retrycount = self.retrylimit
     self.datatosend.setanno('mac-txts', now())
     # go to BACKOFF
     yield fsm.goto(self.BACKOFF)
Ejemplo n.º 9
0
    def encapsulate(self, p, src=None, dst=None, **kwargs):
        """Convenience method to encapsulate an packet in an IEEE 802.11 data
        header (i.e. `Dot11Data`).

        :param p: Packet to encapsulate.
        :param src: Source address [default=`address`]
        :param dst: Destination address [default=`broadcast`]
        :param kwargs: Additional keywords passed to `Dot11Data` constructor.
        :return: Newly created `Dot11Data` packet.

        :note: This method adds/updates a CRC using `crcupdate()`.
        """
        if src is None: src = self.address
        if dst is None: dst = self.broadcast
        addr1, addr2 = dst, src
        pargs = {'addr1': addr1, 'addr2': addr2}
        kwargs.update(pargs)
        data = self.dot11data(**kwargs)
        data.add_payload(p)
        pkt = crcupdate(data)
        return pkt
Ejemplo n.º 10
0
    def ETHSEND(self, fsm, p):
        """ETHSEND state; send ethernet frame.

        :param p: Ethernet packet to transmit.

        By default, this state appends a crc to packet `p` and sends it to
        `Port` 'TXD' without any address checking. After simulating the duration
        of the packet as reported by `duration()`, this state execution method
        returns to `SEND`.
        """
        assert (self.htype==const.ARP_HTYPE_ETHERNET), "[ALOHA]: In ETHSEND," + \
                " non-Ethernet hardware type (%s) not allowed!"%(self.htype)
        assert isinstance(p, Packet) and p.haslayer(Ether), \
                "[ALOHA]: ETHSEND cannot handle non-Ether packet!"
        eth = p[Ether]
        addr, src, dst, etype = self.address, eth.src, eth.dst, eth.type
        pkt = crcupdate(eth)
        duration = self.duration(pkt)
        self.log_send(pkt, addr=addr, src=src, dst=dst, type=etype, \
                      duration=time2usec(duration) )
        yield self.TXD.send(fsm, [pkt])
        yield hold, fsm, duration
        yield fsm.goto(self.SEND)
Ejemplo n.º 11
0
 def TXRTS(self, fsm):
     """TXRTS state; send RTS for `datatosend`."""
     assert self.isdot11data(self.datatosend), \
             "[DCF]: Cannot determine 'datatosend' in TXRTS!"
     assert not (self.datatosend.addr1==self.broadcast), \
             "[DCF]: Cannot send broadcast 'datatosend' in TXRTS!"
     # create RTS
     src, dst = self.datatosend.addr2, self.datatosend.addr1
     rts = self.dot11rts(addr1=dst, addr2=src)
     if (self.retrycount>0):
         rts.FCfield |= DOT11_FC_RETRY
     # calculate NAV
     self.send_rts(rts, self.datatosend)
     nav = self.rtsnav(self.datatosend)
     rts.ID = nav
     pkt = crcupdate(rts)
     # send and hold for duration
     duration = self.duration(pkt)
     self.log_send(pkt, src=src, dst=dst, nav=nav, \
                   duration=time2usec(duration), retry=self.retrycount)
     yield self.TXD.send(fsm, [pkt])
     yield hold, fsm, duration
     # go to RXCTS
     yield fsm.goto(self.RXCTS)
Ejemplo n.º 12
0
    def ETHSEND(self, fsm, net, mac, p, dst=None):
        """ETHSEND state; Encapsulate `p` in Ethernet frame and send to `mac`.

        :param net: Associated `NET`.
        :param mac: Associated `MAC`.
        :param p: Ethernet packet to send.
        :param dst: Ethernet address of destination [default=`MAC.broadcast`]

        Upon completion this method returns to `returnstate` with the parameters
        `net` and `mac`.
        """
        # get parameters for Ethernet packet
        src, htype = mac.addr, mac.htype
        if dst is None: dst = mac.broadcast
        ethertype = self.get_ethertype(p)
        eth = Ether(src=src, dst=dst, type=ethertype)
        eth.add_payload(p)
        # update CRC
        pkt = eth
        if USE_CRC32: pkt = crcupdate(eth)
        # send to TX port
        self.log_send(pkt, src=src, dst=dst, type=ethertype)
        txport = self.getport((mac, "TX"))
        yield txport.send(fsm, [pkt])