def on_arp(self, raw): arp = ARP(raw) if arp.oper == ARP.Oper.IAm: mint.report('{} got ARP annoucement from {}'.format( ip_to_str(self.ip), ip_to_str(arp.src_ip), )) self.arp_cache[arp.src_ip] = (arp.src_mac, mint.now()) packets = self.pending_packets[arp.src_ip] for packet in packets: self.framer.send(packet.raw, arp.src_mac) del packets[:] elif arp.oper == ARP.Oper.WhoIs: if not arp.dst_ip == self.ip: mint.report('{} got irrelevant ARP packet'.format( ip_to_str(self.ip))) return packet = ARP( oper=ARP.Oper.IAm, src_ip=self.ip, src_mac=self.framer.mac, dst_ip=arp.src_ip, dst_mac=arp.src_mac, ).raw self.framer.send( packet, to=arp.src_mac, ethertype=Frame.EtherType.ARP, )
def recver(self): while True: frame = self.servant.recv() header, payload, _ = self.decompose(frame) header = self.unbuild(header) if header.acking: # sending frame ACKed if header.ack == self.sending_seq: self.acked = True self.sending_seq = (self.sending_seq + 1) % self.SEQ_SIZE self.timer.stop() if payload: # is the expecting frame if header.seq == self.expecting_seq: self.master.push(payload) self.expecting_seq = (self.expecting_seq + 1) % self.SEQ_SIZE else: utils.put(self.host, 'drop', struct.unpack('!B', payload)[0], 'at', mint.now()) # send ACK header = self.build( acking=True, ack=header.seq, # ack the recved frame seq=0) # meaningless frame = self.compose(header) # no payload self.servant.send(frame)
def remove_expired_entries(self): now = mint.now() n_entries = len(self.route_table) self.route_table = { k: v for k, v in self.route_table.items() if now - v.time < self.entry_duration } if len(self.route_table) != n_entries: mint.report('switch\'s expired entries cleaned')
def recv(self): while True: try: frame = self.nic.recv(block=False) frame = mint.PDU.Frame(frame) self.routes[frame.src_addr] = mint.utils.Bunch( port=self, time=mint.now()) self.iframes.append(frame) except mint.exceptions.WouldBlock: break
def start(self): self.now = mint.now() + self.n_laps
def __getitem__(self, key): val, ctime = self.entries[key] if mint.now() - ctime > self.entry_duration: del self.entries[key] raise KeyError('entry expired') return val
def __setitem__(self, key, val): self.entries[key] = (val, mint.now())
def report(self, *args, **kwargs): s = put_format(*args, **kwargs) self.stdout.append('{:5} | {}'.format(mint.now(), s)) mint.report(self, '|', s)
def register(self, addr, port): mint.report('register host with address {:02x} on port-{}', addr, self.ports.index(port)) if addr == 0x00: return self.route_table[addr] = bunch(ports=[port], time=mint.now())
def register(self, addr, port): mint.report('register host with address {:02x} on port-{}', mac_from_bytes(addr), self.ports.index(port)) if addr == '\x00': return self.route_table[addr] = bunch(ports=[port], time=mint.now())