Beispiel #1
0
 def CAPTURE(self, fsm, p):
     """Simulate capture process for a Packet `p`."""
     self.log("CAPSTART", p)
     errmsg = "[CHANNELIF]: Cannot capture packet that doesn't support ANNO!"
     assert ANNO.supported(p), errmsg
     duration = const.EPSILON
     self.rxbuffer.append(p)                 # add to rxbuffer
     if self.intransmit: self.drop("all")    # drop all packet in rxbuffer
     # mark/use other annotations
     self.set_recvanno(p)
     if p.hasanno('cif-duration'): duration = p.getanno('cif-duration')
     assert not(duration<const.EPSILON), \
             "[CHANNELIF]: Invlaid duration in CAPTURE! (t=%s)"%(duration)
     # resume operation
     self.log("rxdata.sig", p)
     self.rxdata.signal(p)                   # signal rxdata
     yield hold, fsm, duration               # simulate duration
     if self.intransmit: self.drop("all")    # drop all packet in rxbuffer
     self.rxbuffer.remove(p)                 # remove from rxbuffer
     # drop or forward to upper layer
     if p.hasanno('cif-drp') and p.getanno('cif-drp'):
         self.log_drop( p, halfduplex="%s"%(self.halfduplex) )
         self.cleananno(p)
     else:
         pargs = {'cif-duration':time2usec(duration) }
         self.log_recv(p, **pargs)
         yield self.TXU.send(fsm, [p])
     # signal rxdone
     self.log("rxdone.sig", p)
     self.rxdone.signal(p)
     yield fsm.stop()
     assert False, "stop failed!"
Beispiel #2
0
    def SEND(self, fsm):
        """SEND state; simulate encoding and send process.

        This state performs the following tasks:

            1. Get packet from 'RXU' port.
            2. Call `encode()` to generate waveform for outgoing packet.
            3. Mark 'cif-duration' annotation with value returned by `duration()`.
            4. Simulate `txproctime` for outgoing packet.
            5. Send outgoing waveform to 'TXD'.
            6. Simulate `duration` of waveform.
        """
        while fsm.active():
            yield self.RXU.recv(fsm, 1)
            assert fsm.acquired(self.RXU) and (
                len(fsm.got) == 1
            ), "[DOT11APHY]: Error receiving from RXU port in SEND()!"
            p = fsm.got[0]
            # simulate encoding and Tx processing time
            w = self.encode(p)
            duration = self.duration(p)
            if ANNO.supported(w):
                w.setanno("cif-duration", duration)
            yield hold, fsm, self.txproctime(p)
            # send waveform and simulate duration
            self.log_send(w, duration=time2usec(duration))
            yield self.TXD.send(fsm, [w])
            assert fsm.stored(self.TXD), "[DOT11APHY]: Error sending to TXD in SEND!"
            yield hold, fsm, duration
        return
Beispiel #3
0
 def HALT(self, fsm, force=True):
     """Overload `HALT` state to signal `kill` if needed."""
     if (force or (self.timeleft>0)):
         timepassed = self.timepassed
         if self.verbose>TIMER_VERBOSE:
             self.log("CANCEL", timepassed=time2usec(timepassed, fmt="%.4g"), \
                                timeleft=self.timeleft, force=force)
         self.kill.signal(timepassed)
     yield hold, fsm, 0
Beispiel #4
0
 def log_send(self, p, *args, **kwargs):
     """Convenience method for logging send event."""
     if self.verbose>DOT11_VERBOSE:
         kwargs['addr'] = self.address
         kwargs['retrycount'] = self.retrycount
         kwargs['retrylimit'] = self.retrylimit
         if p.hasanno('cif-duration'):
             kwargs['cif-duration'] = time2usec(p.getanno('cif-duration') )
         if p.hasanno('phy-rate'):
             kwargs['phy-rate'] = p.getanno('phy-rate')
         self.log("snd", p, *args, **kwargs)
Beispiel #5
0
 def log_send(self, p, *args, **kwargs):
     """Convenience method for logging send event."""
     if self.verbose > DOT11A_VERBOSE:
         if isinstance(p, Dot11A):
             kwargs["phy-rate"] = p.rate
             kwargs["length"] = p.length
         if p.hasanno("cif-txpower"):
             kwargs["cif-txpower"] = "%.2f dBm" % (p.getanno("cif-txpower"))
         if p.hasanno("cif-duration"):
             kwargs["cif-duration"] = time2usec(p.getanno("cif-duration"))
         self.log("snd", p, *args, **kwargs)
Beispiel #6
0
 def get_cif_anno(self, p):
     """Convenience method to extract annotations and convert to strings."""
     kwargs = {}
     if not isinstance(p, Packet): return kwargs
     if p.hasanno('cif-collision'):
         kwargs['cif-collision'] = strcollision(p)
     if p.hasanno('cif-duration'):
         kwargs['cif-duration'] = time2usec(p.getanno('cif-duration') )
     if p.hasanno('cif-src'):
         kwargs['cif-src'] = "%s"%(p.getanno('cif-src').traceid)
     if p.hasanno('cif-dst'):
         kwargs['cif-dst'] = "%s"%(p.getanno('cif-dst').traceid)
     return kwargs
Beispiel #7
0
 def BACKOFF(self, fsm):
     """BACKOFF state; perform backoff operation."""
     assert self.isdot11data(self.datatosend), \
             "[DCF]: Cannot determine 'datatosend' in BACKOFF!"
     # retry limit exceeded -> DROP PACKET! -> go to IDLE
     if self.retrycount>self.retrylimit:
         self.log_drop(self.datatosend, drop="retry limit exceeded")
         pkt = self.datatosend.payload
         self.datatosend.remove_payload()
         p = crcremove(pkt)
         self.drpdata.signal(p)
         yield fsm.goto(self.IDLE)
     # csbusy -> go to RXBUSY
     if self.isbusy:
         yield fsm.goto(self.RXBUSY)
     # check for nav timer -> start nav backoff
     if self.navbusy: yield fsm.goto(self.NAVBACKOFF)
     # start backoff timer
     backoff = self.difs + self.cslot*self.slottime
     timer = self.newchild("backofftimer", Timer, backoff, start=True, \
                           tracename=self.tracename+".BACKOFF")
     self.log("BACKOFF", self.datatosend, backoff=time2usec(backoff), cslot=self.cslot)
     yield waitevent, fsm, (timer.done, timer.kill, self.csbusy, self.rxdata)
     csbusy = (self.csbusy in fsm.eventsFired)
     rxdata = (self.rxdata in fsm.eventsFired)
     # timer done -> go to TXRTS or TXBCAST
     if (timer.done in fsm.eventsFired):
         isbroadcast = (self.datatosend.addr1==self.broadcast)
         if isbroadcast:    ns = self.TXBCAST
         elif self.usecsma: ns = self.TXUCAST
         else:              ns = self.TXRTS
         yield fsm.goto(ns)
     # timer kill -> raise exception
     elif (timer.kill in fsm.eventsFired):
         raise RuntimeError, "[DCF]: Unexpected kill signal " + \
                             "from timer in BACKOFF!"
     # csbusy/rxdata -> halt timer -> update cslot -> go to RXBUSY/RXPKT
     elif csbusy or rxdata:
         yield timer.pause(fsm)
         if timer.timepassed>self.difs:
             rslot = int(timer.timeleft/self.slottime)
             self.cslot = rslot      # update cslot
         timer.halt()
         if rxdata:
             p = self.rxdata.signalparam
             yield fsm.goto(self.RXPKT, p)
         else:
             yield fsm.goto(self.RXBUSY)
     # otherwise -> raise error!
     else:
         raise RuntimeError, "[DCF]: Unexpected interruption in BACKOFF!"
Beispiel #8
0
 def MONBUSY(self, fsm, t):
     """MONIDLE state; monitor `timer` when NAV Timer is in BUSY state."""
     self.log_busy(duration=time2usec(t.duration) )
     yield waitevent, fsm, (t.done, t.kill)
     # timer fired
     if (t.done in fsm.eventsFired):
         pass
     # timer stopped
     elif (t.kill in fsm.eventsFired) and t.stopped:
         pass
     # otherwise -> raise exception
     else:
         raise RuntimeError, "[NAVTIMER]: Monitor indicates " + \
                             "NAV timer paused unexpectedly!"
     # done monitoring timer
     yield fsm.goto(self.MONIDLE)
Beispiel #9
0
 def TXBCAST(self, fsm):
     """TXBCAST state; broadcast `datatosend`."""
     assert self.isdot11data(self.datatosend), \
             "[DCF]: Cannot determine 'datatosend' in TXBCAST!"
     assert (self.datatosend.addr1==self.broadcast), \
             "[DCF]: Non-broadcast 'datatosend' in TXBCAST!"
     data = self.datatosend
     self.send_data(data)
     # send and hold for duration
     duration = self.duration(data)
     src, dst = data.addr2, data.addr1
     self.log_send(data, src=src, dst=dst, duration=time2usec(duration) )
     yield self.TXD.send(fsm, [data])
     yield hold, fsm, duration
     # go back to IDLE
     yield fsm.goto(self.IDLE)
Beispiel #10
0
 def get_dcf_anno(self, p):
     """Convenience method to extract annotations and convert to strings."""
     kwargs = {}
     if not isinstance(p, Packet): return kwargs
     kwargs['addr'] = self.address
     if p.hasanno('cif-duration'):
         kwargs['cif-duration'] = time2usec(p.getanno('cif-duration') )
     if p.hasanno('phy-rate'):
         kwargs['phy-rate'] = p.getanno('phy-rate')
     if p.hasanno('phy-sinr'):
         kwargs['phy-sinr'] = "%.4f dB"%(p.getanno('phy-sinr') )
     if p.hasanno('net-root'):
         kwargs['net-root'] = p.getanno('net-root')
     if p.hasanno('mac-root'):
         kwargs['mac-root'] = p.getanno('mac-root')
     if p.hasanno('mac-txts'):
         kwargs['mac-txts'] = p.getanno('mac-txts')
     if p.hasanno('mac-rxts'):
         kwargs['mac-rxts'] = p.getanno('mac-rxts')
     return kwargs
Beispiel #11
0
 def log_recv(self, p, *args, **kwargs):
     """Convenience method for logging receive event."""
     if self.verbose > DOT11A_VERBOSE:
         if isinstance(p, Dot11A):
             kwargs["phy-rate"] = p.rate
             kwargs["length"] = p.length
         if p.hasanno("phy-sinr"):
             kwargs["phy-sinr"] = "%.2f dB" % (p.getanno("phy-sinr"))
         if p.hasanno("rxpower"):
             kwargs["rxpower"] = "%.2f dBm" % (p.getanno("rxpower"))
         if p.hasanno("noisepower"):
             kwargs["noisepower"] = "%.2f dBm" % (p.getanno("noisepower"))
         if p.hasanno("cif-duration"):
             kwargs["cif-duration"] = time2usec(p.getanno("cif-duration"))
         if p.hasanno("dot11a-per"):
             kwargs["dot11a-per"] = "%.5g" % (p.getanno("dot11a-per"))
         if p.hasanno("crcerror"):
             crcerror = p.getanno("crcerror")
             if crcerror:
                 kwargs["crc"] = "FAIL"
             else:
                 kwargs["crc"] = "OK"
         self.log("rcv", p, *args, **kwargs)
Beispiel #12
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)
Beispiel #13
0
 def MON(self, fsm):
     """MON state; monitor `timer` events."""
     while fsm.active():
         # wait for timer to be set
         self.log_idle()
         yield waitevent, fsm, self.__wakeup
         t = self.__wakeup.signalparam
         # monitor timer events
         while isinstance(t, Timer):
             self.log_busy(duration=time2usec(t.duration) )
             yield waitevent, fsm, (t.done, t.kill)
             # timer fired
             if (t.done in fsm.eventsFired):
                 pass
             # timer stopped
             elif (t.kill in fsm.eventsFired) and t.stopped:
                 pass
             # otherwise -> raise exception
             else:
                 raise RuntimeError, "[NAVTIMER]: Monitor indicates " + \
                         "NAV timer paused unexpectedly!"
             # done monitoring timer
             t = None
     return
Beispiel #14
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)
Beispiel #15
0
 def log_forward(self, p, *args, **kwargs):
     """Convenience method for logging a forward event for packet `p`."""
     if p.hasanno('cm-delay'):
         delay = p.getanno('cm-delay')
         kwargs['cm-delay'] = time2usec(delay)
     self.log("fwd", p, *args, **kwargs)