def HRECV(self, fsm, net, mac): """HRECV state; manage incoming traffic from MAC protocol. :param net: Associated `NET`. :param mac: Associated `MAC`. Based on the value of `htype`, this method will invoke the appropriate message handler to classify and handle traffic from `mac` to `net`. """ if isinstance(net, Reference): net = net._deref if isinstance(mac, Reference): mac = mac._deref errmsg = "[ARP]: Must be connected to (%s,%s) to RECV!"%(net,mac) assert self.connected(net) and self.connected(mac), errmsg # get message from rxport rxport = self.getport((mac, "RX")) yield rxport.recv(fsm, 1) errmsg = "[ARP]: Error in receiving from mac 'RX' port in RECV!" assert fsm.acquired(rxport) and (len(fsm.got)==1), errmsg # send packet to appropriate message handler p = fsm.got[0] fname = "ARPTX.%s(%s)"%(self.traceid, p.traceid) if (mac.htype==const.ARP_HTYPE_ETHERNET): f = FSM(name=fname) f.goto(self.ETHRECV, net, mac, p) f.start() else: f = FSM(name=fname) f.goto(self.HERRRECV, net, mac, p) f.start() # continue in HRECV yield fsm.goto(self.HRECV, net, mac)
def PSEND(self, fsm, net, mac): """PSEND state; Manage outgoing traffic from network protocol. Based on the value of `ptype`, this method will invoke the appropriate message handler to forward traffic from `net` to `mac`. """ if isinstance(net, Reference): net = net._deref if isinstance(mac, Reference): mac = mac._deref errmsg = "[ARP]: Must be connected to (%s,%s) to SEND!"%(net,mac) assert self.connected(net) and self.connected(mac), errmsg # get message from rxport rxport = self.getport((net,"RX")) yield rxport.recv(fsm, 1) errmsg = "[ARP]: Error in receiving from net 'RX' port in SEND!" assert fsm.acquired(rxport) and (len(fsm.got)==1), errmsg # send packet to appropriate message handler p = fsm.got[0] fname = "ARPTX.%s(%s)"%(self.traceid, p.traceid) if (net.ptype==const.ARP_PTYPE_IP): f = FSM(name=fname) f.goto(self.IPSEND, net, mac, p) f.start() else: f = FSM(name=fname) f.goto(self.PERRSEND, net, mac, p) f.start() # continue in PSEND yield fsm.goto(self.PSEND, net, mac)
def LISTEN(self, fsm, cif, rxport): """Listen to traffic sent by `ChannelInterface` on `rxport`.""" assert (self.hasport(rxport) is not None), \ "[CHANNEL]: Cannot listen on invalid Port!" # get data from rxport yield rxport.recv(fsm, 1) assert fsm.acquired(rxport) and (len(fsm.got)==1), \ "[CHANNEL]: Error occurred during LISTEN on %s!"%(rxport) # forward on all outgoing edge p, u = fsm.got[0], cif neighbors = [str(c.traceid) for c in self.graph.neighbors(u) ] errmsg = "[CHANNEL]: Cannot forward non-Packet!" assert isinstance(p, Packet), errmsg for v in self.graph[u]: cmodel = self.graph[u][v]['model'] errmsg = "[CHANNEL]: Cannot find corresponding TX Port!" assert (self.hasport((v, "TX") ) is not None) # if channel model for link is not active -> ignore packet if not cmodel.active: continue # filter packets using channel model drop = self.apply_filter(cmodel, p, u, v) if drop: self.log("drp",p,drop=drop,src=u.traceid,dst=v.traceid) continue # continue with next link # copy and mark annotations c, txport = p.copy(), self.getport((v, "TX") ) c.setanno('cif-src', u, ref=True) c.setanno('cif-dst', v, ref=True) # apply channel model propdelay = None r = self.apply_model(cmodel, c, u, v) if cmodel.verbose>CHANNEL_VERBOSE: cmodel.log_forward(c, src=u.traceid, dst=v.traceid) if ANNO.supports(r, 'cm-delay'): propdelay = r.getanno('cm-delay') # forward to destination if (r is None): self.log("drp",c,action="dropped by %s"%(cmodel.traceid) ) elif (propdelay>0): # apply propagation delay f = FSM() f.goto(self.FORWARD, txport, [r]) f.start(delay=propdelay) else: # send immediately (no delay) yield txport.send(fsm, [r]) if self.verbose>CHANNEL_VERBOSE: self.log("fwd", p, dest="%s"%(neighbors) ) # continue in LISTEN yield fsm.goto(self.LISTEN, cif, rxport)
def LISTEN(self, fsm): """LISTEN state; monitor `radio` and manage packet detection.""" r = self.radio assert isinstance(r, Radio), "[DOT11A]: Cannot find radio in LISTEN!" while fsm.active(): # check rxenergy -> set csbusy? rxenergy = r.rxenergy() rxhigh = r.inreceive and (r.rxenergy() > DOT11A_CSTHRESHOLD) if rxhigh: self.set_csbusy(rxenergy="high, %.2f dBm" % (rxenergy), rxbuffer=[x.traceid for x in r.rxbuffer]) else: self.set_csidle(rxenergy="%.2f dBm" % (rxenergy)) # monitor events and RXD port yield self.RXD.recv(fsm, 1, renege=(r.rxdata, r.rxdone, r.txdata, r.txdone, self.detect)) # RXD -> ignore incoming packets in LISTEN if fsm.acquired(self.RXD): assert len(fsm.got) == 1, ( "[DOT11A]: Received unexpected " + "number of packets from 'RXD' port in LISTEN state!" ) p = fsm.got[0] self.log_drop(p, drop="not detected in LISTEN") # rxdata -> start DETECT thread if r.rxdata in fsm.eventsFired: p = r.rxdata.signalparam fname = "detect(%s)" % (p._id) ### XXX #### f = FSM() # f = self.newchild(fname, FSM, tracename=fname.upper() ) f.goto(self.DETECT, p) f.start() # detect -> set csbusy -> goto DECODE if self.detect in fsm.eventsFired: p = self.detect.signalparam rxenergy = "%.2f dBm" % (r.rxenergy()) sinr = "%.2f dB" % (self.sinr(p)) self.set_csbusy(p, detect=True, rxenergy=rxenergy) danno = "dot11a-detect" errmsg = "[DOT11A]: Cannot find 'dot11a-detect' " + "annotation in detected packet!" assert ANNO.supports(p, danno) and p.getanno(danno), errmsg # yield hold, fsm, 0 self.log("detect", p, rxenergy=rxenergy, sinr=sinr, rxbuffer=[x.traceid for x in r.rxbuffer]) yield fsm.goto(self.DECODE, p) # ignore otherwise ignore = r.txdata in fsm.eventsFired ignore = ignore or (r.txdone in fsm.eventsFired) ignore = ignore or (r.rxdone in fsm.eventsFired) if ignore: pass return
def RECV(self, fsm): """Manage upstream (or incoming) traffic. This method spawn worker processes to simulate the capture of each packet. These worker processes manage 'cif-drp' and 'cif-collision' annotations; along with simulating packet 'cif-duration'. """ yield self.RXD.recv(fsm, 1) errmsg = "[CHANNELIF]: RECV() error occurred during recv() from RXD!" assert fsm.acquired(self.RXD) and (len(fsm.got)==1), errmsg # start capture thread for p in fsm.got: w = FSM() w.goto(self.CAPTURE, p) w.start(prior=True) # continue in RECV yield fsm.goto(self.RECV) assert False, "State transition failed!"