Exemple #1
0
def strcollision(p):
    """Get string representation of 'cif-collision' list from packet `p`."""
    coll = None
    if ANNO.supports(p, 'cif-collision'):
        coll = []
        for c in p.getanno('cif-collision'):
            try:
                s = c.traceid
                assert ANNO.supported(c), "s = %s, coll = %s"%(s, coll)
            except:
                s = c
                assert not ANNO.supported(c), "s = %s, coll = %s"%(s, coll)
            coll.append(s)
    return coll
Exemple #2
0
    def RECV(self, fsm):
        """RECV state; monitor traffic from lower layer.

        This state receives packets on `Port` 'RXD'. It then uses `ptype` to
        determine which packet handler should process the new data packet, and
        spawns a new thread to run the handler.
        
        :note: Currently, IPv4 is the only protocol type supported. Non-IPv4
               packets are passed to `ERRRECV` for handling.
        """
        # error messages
        rxderror = "[ROUTING]: Error occurred while receiving " + \
                   "traffic from RXD port!"
        pkterror = "[ROUTING]: Invalid packet from lower layer!"
        # get packet from lower layer
        yield self.RXD.recv(fsm, 1)
        assert fsm.acquired(self.RXD) and (len(fsm.got)==1), rxderror
        p = fsm.got[0]
        if isinstance(p, Reference): p = p._deref
        assert ANNO.supported(p), pkterror
        # use appropriate recv function based on ptype
        if (self.ptype == const.ARP_PTYPE_IP):
            f = FSM.launch(self.IPRECV, p)      # IP ptype
        else:
            f = FSM.launch(self.ERRRECV, p)     # unknown ptype
        # continue in RECV
        yield fsm.goto(self.RECV)
Exemple #3
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!"
Exemple #4
0
 def SEND(self, fsm):
     """Manage downstream (or outgoing traffic."""
     yield self.RXU.recv(fsm, 1)
     assert fsm.acquired(self.RXU) and (len(fsm.got)==1), \
             "[CHANNELIF]: SEND() error occurred during recv() from RXU!"
     # get packet and set annotations
     p, duration = fsm.got[0], 0
     errmsg = "[CHANNELIF]: Cannot send packet that does not support ANNO!"
     assert ANNO.supported(p), errmsg
     self.set_sendanno(p)
     if p.hasanno('cif-duration'): duration = p.getanno('cif-duration')
     # min-time is const.EPSILON
     if duration<const.EPSILON: duration = const.EPSILON
     p.setanno('cif-duration', duration)
     self.log_send(p)
     # send and simulate duration
     self.__ifstate = CHANNELIF_TX     # start TX
     self.drop("all")                # drop all packet in rxbuffer
     self.txdata.signal(p)
     yield self.TXD.send(fsm, [p])
     yield hold, fsm, duration       # simulate duration
     self.drop("all")                # drop all packet in rxbuffer
     self.__ifstate = CHANNELIF_RX     # resume RX
     self.txdone.signal(p)
     # continue in SEND
     yield fsm.goto(self.SEND)
Exemple #5
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
Exemple #6
0
    def framedetect(self, p, thresh=None):
        """Apply packet detection model for detecting training sequence; based
        on signal-to-interference-and-noise ratio (SINR).

        :param p: `Dot11A` packet being received.
        :param thresh: Packet detection SINR threshold (in dB)
                       [default=`DOT11A_FDTHRESHOLD`].
        :return: Boolean flag; if true, packet detection was successful.

        This method checks to make sure `p` is a `Dot11A` packet, and that the
        received SINR is greater than the receiver detection threshold `thresh`.
        This method will also mark the 'dot11a-detect' annotation to indicate
        the success (or failure) of the frame detection.

        **Overload this method to change how frame detection works.**

        :note: If `p` is not a `Dot11A` packet, this method will set the
               'dot11a-detect' annotation to false and return false.
        """
        if not isinstance(p, Dot11A):
            if ANNO.supported(p):
                p.setanno("dot11a-detect", False)
            return False
        # check SINR
        if thresh is None:
            thresh = DOT11A_FDTHRESHOLD
        sinr = self.sinr(p)
        detect = True
        if sinr < thresh:
            detect = False
        # mark annotations
        p.setanno("dot11a-detect", detect)
        return detect
Exemple #7
0
 def log_recv(self, p, *args, **kwargs):
     """Updated to print `RAI` parameters."""
     if ANNO.supported(p):
         if p.haslayer(RAI):
             kwargs['rai-rate'] = p[RAI].rate
             kwargs['rai-length'] = p[RAI].length
         if p.hasanno('phy-rate'):
             kwargs['phy-rate'] = p.getanno('phy-rate')
     DCF.log_recv(self, p, *args, **kwargs)
Exemple #8
0
 def cleananno(self, p):
     """Clean up annotations before passing to upper layers."""
     assert ANNO.supported(p), "[PHY]: ANNO not supported!"
     # replace/remove unwanted annotations
     if p.hasanno('cif-collision'):
         coll = strcollision(p)
         assert (coll is not None)
         p.delanno('cif-collision')
         p.setanno('cif-collision', coll, priv=True)
     return p
Exemple #9
0
def _apply_fixed_delay(cm, *args, **kwargs):
    """Internal method to implement `FixedDelay` `ChannelModel` wrapper."""
    assert isinstance(cm, ChannelModel)
    assert hasattr(cm, '__subclass__')
    assert hasattr(cm, '__fixed_delay__')
    subclass = cm.__subclass__
    delay = cm.__fixed_delay__
    r = subclass.apply(cm, *args, **kwargs)
    if ANNO.supports(r, 'cm-delay'):
        r.delanno('cm-delay')
    if ANNO.supported(r) and (delay>0):
        r.setanno('cm-delay', delay)
    return r
Exemple #10
0
    def set_recvanno(self, p, src, dst):
        """Set relevant annotations for received data to upper layer.

        :param p: Packet to modify.
        :param src: Network address of source.
        :param dst: Network address of destination.
        :return: Modified packet.

        This method sets the 'net-src' and 'net-dst' annotations.
        """
        errmsg = "[ROUTING]: Got non-Packet data from upper layer()!"
        assert ANNO.supported(p), errmsg
        # set address annotations
        p.setanno('net-src', src)
        p.setanno('net-dst', dst)
        return p
Exemple #11
0
    def set_sendanno(self, p, src, dst):
        """Set relevant annotations for outgoing packet.

        :param p: Packet to modify.
        :param src: Network address of source.
        :param dst: Network address of destination.
        :return: Modified packet.

        This method sets the 'net-src' and 'net-dst' annotations.
        """
        errmsg = "[ROUTING]: Got non-Packet data from upper layer()!"
        assert ANNO.supported(p), errmsg
        # set address annotations
        p.setanno('net-src', src)
        p.setanno('net-dst', dst)
        # set annotations used just for logging
        p.setanno('net-root', str(p.traceid))
        return p
Exemple #12
0
    def sinr_heap(self, p, force=True):
        """Calculate signal-to-interference-and noise ratio (SINR) for each
        partition created by `interval_heap()`.

        :param p: Packet to inspect.
        :param force: If true, recalculate interval heap, else use existing
                      annotation if it exists.
        :return: SINR heap.

        SINR heap has looks like this:

            [(t0, t1, sinr0), (t1, t2, sinr1), ... ]

        Note: This method uses the 'rxpower' and 'noisepower' annotations.
        """
        # check packet
        errmsg = "[CHANNELIF]: sinr_heap() cannot process non-Packet!"
        assert ANNO.supported(p), errmsg
        for a in ['rxpower', 'noisepower']:
            errmsg = "[CHANNELIF]: sinr_heap() cannot find '%s' annotation!"%(a)
            assert ANNO.supports(p, a), errmsg
        # get parameters
        rxpower = p.getanno('rxpower')          # in dBm
        noisepower = p.getanno('noisepower')    # in dBm
        npow = db2linear(noisepower)
        # get interval heap
        if p.hasanno('cif-iheap') and not force:
            iheap = p.getanno('cif-iheap')
        else:
            iheap = self.interval_heap(p)
        # start creating sinr heap
        sinrheap = []
        #print "%s: SINR heap for %s @ %.8f"%(self.traceid, p.traceid, now())
        for ta,tb,coll in iheap:
            ipow = 0
            for c in coll:
                errmsg = "[CHANNELIF]: sinr_heap() cannot find 'rxpower' " + \
                         "annotation in collision list!"
                assert ANNO.supports(c, 'rxpower'), errmsg
                ipow += db2linear(c.getanno('rxpower') )
            sinr = rxpower - linear2db(ipow + npow)
            sinrheap.append((ta,tb,sinr) )
            #print "  --> (%.8f, %.8f): %.3f dB, coll = %s"%(ta,tb, sinr, [c.traceid for c in coll])
        return sinrheap
Exemple #13
0
    def seterror(self, p):
        """Convenience method to set error annotation (or parameters) in `p`.

        :return: Modified packet with updated parameters/annotations.

        By default, if packet `p` has a `CRC32` layer, this method will set the
        'crcerror' field, otherwise this method will set the 'crcerror'
        annotation to 1.

        **Overload this method as needed.**
        """
        hascrc = CRC32.supported(p)
        hasanno = ANNO.supported(p)
        if hascrc:
            p[CRC32].crcerror = 1
        elif hasanno:
            p.setanno('crcerror', 1)
        else:
            raise RuntimeError, "[PHY]: seterror() failed to find packet!"
Exemple #14
0
    def SEND(self, fsm):
        """SEND state; monitor traffic from upstream protocol and pass to
        routing algorithm.

        This state uses the 'net-src' and 'net-dst' annotations to determine the
        addresses of the source and destination. If not available, these values
        default to the local `address` and `broadcast` address.

        This state then uses `ptype` to determine which packet handler should
        process the new data packet, and spawns a new thread to run the handler.
        
        :note: Currently, IPv4 is the only protocol type supported. Non-IPv4
               packets are passed to `ERRSEND` for handling. Also, this state
               will check for loopback addresses and send them back to the upper
               layer protocol.
        """
        # error messages
        rxuerror = "[ROUTING]: Error occurred receiving from RXU port!"
        pkterror = "[ROUTING]: Invalid packet from upper layer!"
        # get packet to send from upperlayer
        yield self.RXU.recv(fsm, 1)
        assert fsm.acquired(self.RXU) and (len(fsm.got)==1), rxuerror
        p = fsm.got[0]
        if isinstance(p, Reference): p = p._deref
        assert ANNO.supported(p), pkterror
        # process new data packet
        addr = self.address
        src, dst = addr, self.broadcast
        if p.hasanno('net-src'): src = p.getanno('net-src')
        if p.hasanno('net-dst'): dst = p.getanno('net-dst')
        r = self.set_sendanno(p, src, dst)
        # send loopback back to upper layer
        if (dst==addr):
            self.log_loopback(p, src=src, dst=dst)
            yield self.TXU.send(fsm, [p])
            yield fsm.goto(self.SEND)           # continue in SEND
        # otherwise -> use appropriate send function based on ptype
        if (self.ptype == const.ARP_PTYPE_IP):
            f = FSM.launch(self.IPSEND, r, src, dst)        # IP ptype
        else:
            f = FSM.launch(self.ERRSEND, r, src, dst)       # unknown ptype
        # continue in SEND
        yield fsm.goto(self.SEND)
Exemple #15
0
    def haserror(self, p, *args, **kwargs):
        """Convenience method to determine if packet `p` has an error.

        :param args: Additional arguments passed to `CRC32.haserror()`.
        :param kwargs: Keyword arguments passed to `CRC32.haserror()`.
        :return: Boolean; true if error is found; false otherwise.

        By default, this method calls `CRC32.haserror()`. If no `CRC32` layer is
        found, or no 'crcerror' annotation is found the packet is assumed to be
        error-free.
        
        **Overload this method as needed to change this operation.**

        :note: This method ignores the CRC when `checkcrc` is set to false.
        """
        hascrc = isinstance(p, Packet) and p.haslayer(CRC32)
        hasanno = ANNO.supported(p) and p.hasanno('crcerror')
        crcerror = (hascrc or hasanno) and CRC32.haserror(p,*args,**kwargs)
        if not self.checkcrc:
            crcerror = False    # assume no error when checkcrc is false
        return crcerror