def __init__(self, dev): self.verbose = default_verbosity super(TapDriver, self).__init__(dev) self.dev = dev self.mm = dev.interface.mm self.stats = TapStatistics()
class TapDriver(TDInt): def __init__(self, dev): self.verbose = default_verbosity super(TapDriver, self).__init__(dev) self.dev = dev self.mm = dev.interface.mm self.stats = TapStatistics() def __enter__(self): print "[+] driver initialization begins" super(TapDriver, self).__enter__() self._device_setup() return self def __exit__(self, t, v, traceback): self.dev.close() super(TapDriver, self).__exit__() print "[+] driver terminated" def __init_xx_ring(self, bdtype): mm = self.mm ring_len = mm.page_sz / ctypes.sizeof(bdtype) if ring_len > 512: ring_len = 512 for i in range(4): ring_len |= (ring_len >> (2 ** i)) ring_len = ring_len - (ring_len >> 1) vaddr = mm.alloc(ring_len * ctypes.sizeof(bdtype)) return (vaddr, ring_len) def _init_tx_rings(self): mm = self.mm self.tx_ring_vaddr, self.tx_ring_len = self.__init_xx_ring(tg.sbd) self.tx_ring_paddr = mm.get_paddr(self.tx_ring_vaddr) self._tx_pi = 0 self._tx_ci = 0 self._tx_buffers = [0] * self.tx_ring_len dev = self.dev dev.mem.txrcb[0].addr_hi = self.tx_ring_paddr >> 32 dev.mem.txrcb[0].addr_low = self.tx_ring_paddr & 0xffffffff dev.mem.txrcb[0].max_len = self.tx_ring_len #dev.mem.txrcb[0].nic_addr = 0x4000 dev.mem.txrcb[0].flags.disabled = 0 print "[+] send ring 0 of size %d allocated at %x" % (self.tx_ring_len, self.tx_ring_vaddr) for i in range(len(dev.mem.txrcb) - 1): dev.mem.txrcb[i + 1].flags.disabled = 1 print "[+] send ring %d disabled" % (i + 1) def _init_rx_rings(self): dev = self.dev mm = self.mm dev.rdi.mini_rcb.disable_ring = 1 print "[+] mini receive producer ring disabled" self.rx_ring_vaddr, self.rx_ring_len = self.__init_xx_ring(tg.rbd) self.rx_ring_paddr = mm.get_paddr(self.rx_ring_vaddr) dev.rdi.std_rcb.host_addr_hi = self.rx_ring_paddr >> 32 dev.rdi.std_rcb.host_addr_low = self.rx_ring_paddr & 0xffffffff dev.rdi.std_rcb.ring_size = self.rx_ring_len dev.rdi.std_rcb.max_frame_len = 0x600 dev.rdi.std_rcb.nic_addr = 0x6000 dev.rdi.std_rcb.disable_ring = 0 print "[+] standard receive producer ring of size %d allocated at %x" % (self.rx_ring_len, self.rx_ring_vaddr) dev.rdi.jumbo_rcb.disable_ring = 1 print "[+] jumbo receive producer ring disabled" def _init_rr_rings(self): dev = self.dev mm = self.mm ring_vaddr, self.rr_rings_len = self.__init_xx_ring(tg.rbd) self.rr_rings_vaddr = [ring_vaddr] print "[+] receive return ring 0 of size %d allocated at %x" % (self.rr_rings_len, ring_vaddr) for i in range(1, len(dev.mem.rxrcb)): ring_vaddr, tmp = self.__init_xx_ring(tg.rbd) assert tmp == self.rr_rings_len self.rr_rings_vaddr += [ring_vaddr] print "[+] receive return ring %d of size %d allocated at %x" % (i, tmp, ring_vaddr) self.rr_rings_ci = [0] * len(dev.mem.rxrcb) self.rr_rings_paddr = [] for i in range(0, len(dev.mem.rxrcb)): ring_vaddr = self.rr_rings_vaddr[i] p = mm.get_paddr(ring_vaddr) self.rr_rings_paddr += [p] dev.mem.rxrcb[i].addr_hi = (p >> 32) dev.mem.rxrcb[i].addr_low = (p & 0xffffffff) dev.mem.rxrcb[i].nic_addr = 0x6000 dev.mem.rxrcb[i].max_len = self.rr_rings_len dev.mem.rxrcb[i].flags.disabled = 0 def _populate_rx_ring(self, count = None): if count == None: count = self.rx_ring_len - 1 assert count < self.rx_ring_len mm = self.mm r = ctypes.cast(self.rx_ring_vaddr, ctypes.POINTER(tg.rbd)) self.rx_ring_bds = r self.rx_ring_buffers = [] for i in range(self.rx_ring_len): buf = mm.alloc(0x800) self.rx_ring_buffers += [buf] pbuf = mm.get_paddr(buf) r[i].addr_hi = pbuf >> 32 r[i].addr_low = pbuf & 0xffffffff r[i].index = i r[i].length = 0x800 r[i].flags.disabled = 0 print "[+] produced %d rx buffers" % self.rx_ring_len self.dev.hpmb.box[tg.mb_rbd_standard_producer].low = count self._std_rbd_pi = count self._std_rbd_ci = 0 def _device_setup(self): dev = self.dev mm = self.mm dev.drv = self print "[+] initializing device" dev.init() print "[+] resetting device" dev.reset() sleep(0.5) if dev.pci.misc_host_ctrl.enable_tagged_status_mode == 0: print "[+] enabling tagged status mode" dev.pci.misc_host_ctrl.enable_tagged_status_mode = 1 dma_wmm = 0x6 try: if dev.config.caps['pcie'].max_payload_size > 0: dma_wmm += 0x1 except: pass if dev.pci.dma_rw_ctrl.dma_write_watermark != dma_wmm: print "[+] configuring dma write watermark" dev.pci.dma_rw_ctrl.dma_write_watermark = dma_wmm if not dev.pci.dma_rw_ctrl.disable_cache_alignment: print "[+] disabling pci dma alignment" dev.pci.dma_rw_ctrl.disable_cache_alignment = 1 if dev.msi.mode.msix_multi_vector_mode: print "[+] disabling multi vector mode" dev.msi.mode.msix_multi_vector_mode = 0 if not dev.grc.misc_local_control.interrupt_on_attention: print "[+] configuring interrupts on grc attention" dev.grc.misc_local_control.interrupt_on_attention = 1 if not dev.grc.misc_local_control.auto_seeprom: print "[+] configuring automatic eeprom access mode" dev.grc.misc_local_control.auto_seeprom = 1 if not dev.grc.misc_config.timer_prescaler == 0x41: print "[+] configuring grc timer prescaler" dev.grc.misc_config.timer_prescaler = 0x41 if not dev.grc.mode.host_send_bds: print "[+] enabling host send bds" self.dev.grc.mode.send_no_pseudo_header_cksum = 1 self.dev.grc.mode.host_send_bds = 1 if not dev.grc.mode.host_stack_up: print "[+] setting host stack up" dev.grc.mode.host_stack_up = 1 if dev.bufman.dma_mbuf_low_watermark.count != 0x2a: print "[+] setting dma mbuf low watermark" dev.bufman.dma_mbuf_low_watermark.count = 0x2a if dev.bufman.mbuf_high_watermark.count != 0xa0: print "[+] setting mbuf high watermark" dev.bufman.mbuf_high_watermark.count = 0xa0 if dev.emac.low_watermark_max_receive_frame.count != 1: print "[+] configuring dma low watermark flow control" dev.emac.low_watermark_max_receive_frame.count = 1 dev.bufman.mode.attention_enable = 1 dev.bufman.block_enable() if dev.rbdi.std_ring_replenish_threshold.count != 0x19: print "[+] configuring standard rx producer ring replenish threshold" dev.rbdi.std_ring_replenish_threshold.count = 0x19 self._init_rx_rings() dev.hpmb.box[tg.mb_rbd_standard_producer].low = 0 dev.rbdi.std_ring_replenish_watermark.count = 0x20 self._init_tx_rings() dev.hpmb.box[tg.mb_sbd_host_producer].low = 0 self._init_rr_rings() self.mac_addr = [getattr(dev.emac.addr[0], "byte_%d" % (i + 1)) for i in range(6)] print ("[+] device mac addr: %02x" + (":%02x" * 5)) % tuple(self.mac_addr) print "[+] configuring tx mac" dev.emac.tx_random_backoff = sum(self.mac_addr) & 0x3ff dev.emac.tx_mac_lengths.ipg = 0x6 dev.emac.tx_mac_lengths.ipg_crs = 0x2 dev.emac.tx_mac_lengths.slot = 0x20 print "[+] configuring rx mac" dev.emac.rx_mtu = 1500 dev.emac.rx_rules_conf.no_rules_matches_default_class = 2 print "[+] configuring receive list placement" dev.rlp.config.default_interrupt_distribution_queue = 0 dev.rlp.config.bad_frames_class = 1 dev.rlp.config.number_of_active_lists = 0x10 dev.rlp.config.number_of_lists_per_distribution_group = 1 print "[+] enabling rx statistics" dev.rlp.stats_enable_mask.a1_silent_indication = 1 dev.rlp.stats_enable_mask.cpu_mactq_priority_disable = 1 dev.rlp.stats_enable_mask.enable_cos_stats = 1 dev.rlp.stats_enable_mask.enable_indiscard_stats = 1 dev.rlp.stats_enable_mask.enable_inerror_stats = 1 dev.rlp.stats_enable_mask.enable_no_more_rbd_stats = 0 dev.rlp.stats_enable_mask.perst_l = 1 dev.rlp.stats_enable_mask.rc_return_ring_enable = 0 dev.rlp.stats_enable_mask.rss_priority = 0 assert dev.rlp.stats_enable_mask.word == 0x7bffff dev.rlp.stats_control.statistics_enable = 1 print "[+] enabling tx statistics" dev.sdi.statistics_mask.counters_enable_mask = 1 dev.sdi.statistics_control.faster_update = 1 dev.sdi.statistics_control.statistics_enable = 1 dev.hc.block_disable() print "[+] configuring host coalesence" dev.hc.mode.status_block_size = 2 dev.hc.mode.clear_ticks_mode_on_rx = 1 dev.hc.rx_coal_ticks = 0x48 dev.hc.tx_coal_ticks = 0x14 dev.hc.rx_max_coal_bds = 0x05 dev.hc.tx_max_coal_bds = 0x35 dev.hc.rc_max_coal_bds_in_int = 0x05 dev.hc.tx_max_coal_bds_in_int = 0x05 self.status_block_vaddr = mm.alloc(sizeof(tg.status_block)) self.status_block = cast(self.status_block_vaddr, POINTER(tg.status_block))[0] self.status_block_paddr = mm.get_paddr(self.status_block_vaddr) dev.hc.status_block_host_addr_hi = self.status_block_paddr >> 32 dev.hc.status_block_host_addr_low = self.status_block_paddr & 0xffffffff dev.hc.block_enable() dev.rbdc.mode.attention_enable = 1 dev.rbdc.block_enable() dev.rlp.block_enable() if not dev.emac.mode.en_fhde: print "[+] enabling frame header dma engine" dev.emac.mode.en_fhde = 1 if not dev.emac.mode.en_rde: print "[+] enabling receive dma engine" dev.emac.mode.en_rde = 1 if not dev.emac.mode.en_tde: print "[+] enabling transmit dma engine" dev.emac.mode.en_tde = 1 print "[+] clearing rx statistics" dev.emac.mode.clear_rx_statistics = 1 print "[+] clearing tx statistics" dev.emac.mode.clear_tx_statistics = 1 while dev.emac.mode.clear_rx_statistics: pass while dev.emac.mode.clear_tx_statistics: pass if not dev.emac.mode.en_rx_statistics: print "[+] enabling rx statistics" dev.emac.mode.en_rx_statistics = 1 if not dev.emac.mode.en_tx_statistics: print "[+] enabling tx statistics" dev.emac.mode.en_tx_statistics = 1 if not dev.emac.event_enable.link_state_changed: print "[+] enabling emac attention on link statue changed" dev.emac.event_enable.link_state_changed = 1 if not dev.grc.mode.int_on_mac_attn: print "[+] enabling interrupt on mac attention" dev.grc.mode.int_on_mac_attn = 1 print "[+] configuringing write dma engine" dev.wdma.mode.write_dma_pci_target_abort_attention_enable = 1 dev.wdma.mode.write_dma_pci_master_abort_attention_enable = 1 dev.wdma.mode.write_dma_pci_parity_attention_enable = 1 dev.wdma.mode.write_dma_pci_host_address_overflow_attention_enable = 1 dev.wdma.mode.write_dma_pci_fifo_overrun_attention_enable = 1 dev.wdma.mode.write_dma_pci_fifo_underrun_attention_enable = 1 dev.wdma.mode.write_dma_pci_fifo_overwrite_attention_enable = 1 dev.wdma.mode.write_dma_local_memory = 1 dev.wdma.mode.write_dma_pci_parity_error_attention_enable = 1 dev.wdma.mode.write_dma_pci_host_address_overflow_error_attention_enable = 1 dev.wdma.mode.status_tag_fix_enable = 1 dev.wdma.mode.reserved2 = 0 dev.wdma.block_enable() print "[+] configuring read dma engine" dev.rdma.mode.read_dma_pci_target_abort_attention_enable = 1 dev.rdma.mode.read_dma_pci_master_abort_attention_enable = 1 dev.rdma.mode.read_dma_pci_parity_error_attention_enable = 1 dev.rdma.mode.read_dma_pci_host_address_overflow_error_attention_enable = 1 dev.rdma.mode.read_dma_pci_fifo_overrun_attention_enable = 1 dev.rdma.mode.read_dma_pci_fifo_underrun_attention_enable = 1 dev.rdma.mode.read_dma_pci_fifo_overread_attention_enable = 1 dev.rdma.mode.read_dma_local_memory_write_longer_than_dma_length_attention_enable = 1 dev.rdma.mode.read_dma_pci_x_split_transaction_timeout_expired_attention_enable = 0 dev.rdma.mode.bd_sbd_corruption_attn_enable = 0 dev.rdma.mode.mbuf_rbd_corruption_attn_enable = 0 dev.rdma.mode.mbuf_sbd_corruption_attn_enable = 0 dev.rdma.mode.reserved3 = 0 dev.rdma.mode.pci_request_burst_length = 3 dev.rdma.mode.reserved2 = 0 dev.rdma.mode.jumbo_2k_mmrr_mode = 1 dev.rdma.mode.mmrr_disable = 0 dev.rdma.mode.address_overflow_error_logging_enable = 0 dev.rdma.mode.post_dma_debug_enable = 0 dev.rdma.mode.hardware_ipv4_post_dma_processing_enable = 0 dev.rdma.mode.hardware_ipv6_post_dma_processing_enable = 0 dev.rdma.mode.in_band_vtag_enable = 0 dev.rdma.mode.reserved = 0 dev.rdma.block_enable() dev.rdc.mode.attention_enable = 1 dev.rdc.block_enable() dev.sdc.block_enable() dev.sbdc.mode.attention_enable = 1 dev.sbdc.block_enable() dev.rbdi.mode.receive_bds_available_on_disabled_rbd_ring_attn_enable = 1 dev.rbdi.block_enable() dev.rdi.mode.illegal_return_ring_size = 1 dev.rdi.block_enable() dev.sdi.mode.multiple_segment_enable = 0 dev.sdi.mode.hardware_pre_dma_enable = 0 dev.sdi.block_enable() dev.sbdi.mode.attention_enable = 1 dev.sbdi.block_enable() dev.sbds.mode.attention_enable = 1 dev.sbds.block_enable() self._populate_rx_ring() print "[+] enabling transmit mac" dev.emac.tx_mac_mode.enable_bad_txmbuf_lockup_fix = 1 #dev.emac.tx_mac_mode.enable_flow_control = 1 dev.emac.tx_mac_mode.enable = 1 usleep(100) print "[+] enabling receive mac" #dev.emac.mac_hash_0 = 0xffffffff #dev.emac.mac_hash_1 = 0xffffffff #dev.emac.mac_hash_2 = 0xffffffff #dev.emac.mac_hash_3 = 0xffffffff dev.emac.rx_mac_mode.promiscuous_mode = 1 dev.emac.rx_mac_mode.accept_runts = 1 #dev.emac.rx_mac_mode.enable_flow_control = 1 dev.emac.rx_mac_mode.rss_enable = 1 #dev.emac.rx_mac_mode.rss_ipv4_hash_enable = 1 #dev.emac.rx_mac_mode.rss_tcpipv4_hash_enable = 1 #dev.emac.rx_mac_mode.rss_ipv6_hash_enable = 1 #dev.emac.rx_mac_mode.rss_tcpipv6_hash_enable = 1 dev.emac.rx_mac_mode.enable = 1 usleep(100) print "[+] configuring led" dev.emac.led_control.word = 0x800 dev.emac.low_watermark_max_receive_frames = 1 def _link_detect(self): print "[+] detecting link" res = self.dev.gphy.autonegotiate() if not res & 0x8000: print "[-] no link detected" self._set_tapdev_status(False) self._hcd = 0 else: hcd = (res & 0x700) >> 8 self._hcd = hcd if (hcd & 0x6) == 6: txpause = self.dev.gphy.may_send_pause() rxpause = self.dev.gphy.may_recv_pause() if hcd & 1: print "[+] full duplex gige link negotated (res: %08x, txpause: %s, rxpause: %s)" % (res, txpause, rxpause) self.dev.emac.mode.half_duplex = 1 else: print "[+] half duplex gige link negotated (res: %08x, txpause: %s, rxpause: %s)" % (res, txpause, rxpause) self.dev.emac.mode.half_duplex = 0 self.dev.emac.mode.port_mode = 2 self.dev.emac.rx_mac_mode.enable_flow_control = 1 if rxpause else 0 self.dev.emac.tx_mac_mode.enable_flow_control = 1 if txpause else 0 elif (hcd > 0): if hcd == 5: print "[+] full duplex 100base-tx link negotiated" self.dev.emac.mode.half_duplex = 0 elif hcd == 4: print "[+] 100base-t4 link negotiated" self.dev.emac.mode.half_duplex = 0 elif hcd == 3: print "[+] half duplex 100base-tx link negotiated" self.dev.emac.mode.half_duplex = 1 elif hcd == 2: print "[+] full duplex 10base-t link negotiated" self.dev.emac.mode.half_duplex = 0 elif hcd == 1: print "[+] half duplex 10base-t link negotiated" self.dev.emac.mode.half_duplex = 1 self.dev.emac.mode.port_mode = 1 self.dev.emac.rx_mac_mode.enable_flow_control = 0 self.dev.emac.tx_mac_mode.enable_flow_control = 0 else: raise Exception("autonegotiaton failed, hcd %x" % hcd) self._set_tapdev_status(True) def _handle_interrupt(self): _ = self._get_serial() dev = self.dev if self.verbose: print "[+] handling interrupt" _ = dev.hpmb.box[tg.mb_interrupt].low tag = 0 while self.status_block.updated: tag = self.status_block.status_tag if self.verbose: print "[+] status tag %x" % tag tag = tag << 24 self.status_block.updated = 0 if self.verbose: print "[+] status block updated! link: %d, attention: %d" % (self.status_block.link_status, self.status_block.attention) if dev.emac.status.link_state_changed: self._link_detect() dev.emac.status.link_state_changed = 1 for i in range(len(dev.mem.rxrcb)): pi = getattr(self.status_block, "rr%d_pi" % i) ci = self.rr_rings_ci[i] if pi != ci: if self.verbose: print "[+] rr %d: pi is %x, ci was %x," % (i, pi, ci), if pi < ci: count = self.rr_rings_len - ci count += pi else: count = pi - ci if self.verbose: print "%d bds received" % count rbds = ctypes.cast(self.rr_rings_vaddr[i], ctypes.POINTER(tg.rbd)) while count > 0: ci += 1 if ci > self.rr_rings_len: ci = 1 rbd = rbds[ci - 1] if self.verbose: print "consuming bd 0x%x" % ci print " addr: %08x:%08x" % (rbd.addr_hi, rbd.addr_low) print " buf[%d] vaddr: %x, paddr: %x" % (rbd.index, self.rx_ring_buffers[rbd.index], self.mm.get_paddr(self.rx_ring_buffers[rbd.index])) print " length: %04x" % rbd.length print " index: %04x" % rbd.index print " type: %04x" % rbd.type print " flags: ", for j in ["is_ipv6", "is_tcp", "l4_checksum_correct", "ip_checksum_correct", "reserved", "has_error", "has_vlan_tag", "reserved2", "reserved3", "rss_hash_valid", "packet_end", "reserved4", "reserved5"]: if getattr(rbd.flags, j): print j, print if rbd.flags.rss_hash_type != 0: print " rss hash type: %x" % rbd.flags.rss_hash_type print " ip cksum: %04x" % rbd.ip_cksum print " l4 cksum: %04x" % rbd.l4_cksum print " err flags:", for j in ["reserved1", "reserved2", "reserved3", "reserved4", "reserved5", "reserved6", "reserved7", "giant_packet", "trunc_no_res", "len_less_64", "mac_abort", "dribble_nibble", "phy_decode_error", "link_lost", "collision", "bad_crc"]: if getattr(rbd.error_flags, j): print j, print print " vlan_tag: %04x" % rbd.vlan_tag print " rss_hash: %08x" % rbd.rss_hash print " opaque: %08x" % rbd.opaque buf = ctypes.cast(self.rx_ring_buffers[rbd.index], ctypes.POINTER(ctypes.c_char * rbd.length))[0] ''' def _populate_rx_ring(self, count = None): if count == None: count = self.rx_ring_len - 1 assert count < self.rx_ring_len mm = self.mm r = ctypes.cast(self.rx_ring_vaddr, ctypes.POINTER(tg.rbd)) self.rx_ring_bds = r self.rx_ring_buffers = [] for i in range(self.rx_ring_len): buf = mm.alloc(0x800) self.rx_ring_buffers += [buf] pbuf = mm.get_paddr(buf) r[i].addr_hi = pbuf >> 32 r[i].addr_low = pbuf & 0xffffffff r[i].index = i r[i].length = 0x800 r[i].flags.disabled = 0 print "[+] produced %d rx buffers" % self.rx_ring_len self.dev.hpmb.box[tg.mb_rbd_standard_producer].low = count self._std_rbd_pi = count self._std_rbd_ci = 0 ''' new_buf = self.mm.alloc(0x800) new_pbuf = self.mm.get_paddr(new_buf) self.rx_ring_bds[rbd.index].addr_hi = new_pbuf >> 32 self.rx_ring_bds[rbd.index].addr_low = new_pbuf & 0xffffffff self.rx_ring_buffers[rbd.index] = new_buf self._write_pkt(buf, rbd.length) count -= 1 mb = getattr(tg, "mb_rbd_rr%d_consumer" % i) dev.hpmb.box[mb].low = ci self.rr_rings_ci[i] = ci new_ci = self.status_block.rpci old_ci = self._std_rbd_ci count = 0 if new_ci != old_ci: if self.verbose: print "[+] rbdp ci now %x, was %x" % (new_ci, old_ci) rbds = ctypes.cast(self.rx_ring_vaddr, ctypes.POINTER(tg.rbd)) while new_ci != old_ci: count += 1 rbds[old_ci].flags.word = 0 rbds[old_ci].error_flags.word = 0 rbds[old_ci].length = 0x600 old_ci += 1 if old_ci == self.rx_ring_len: old_ci = 0 self._std_rbd_ci = new_ci self._std_rbd_pi += count if self._std_rbd_pi >= self.rx_ring_len: self._std_rbd_pi -= self.rx_ring_len if self.verbose: print "[+] moving std rbd pi to %x" % self._std_rbd_pi self.dev.hpmb.box[tg.mb_rbd_standard_producer].low = self._std_rbd_pi tx_ci = self.status_block.sbdci if tx_ci != self._tx_ci: if self.verbose: print "[+] sbd ci: %x" % tx_ci if tx_ci < self._tx_ci: if self.verbose: if self._tx_ci + 1 == self.tx_ring_len: print "[.] freeing tx buffer %02x" % self._tx_ci else: print "[.] freeing tx buffers %02x-%02x" % (self._tx_ci, self.tx_ring_len - 1) while self._tx_ci < self.tx_ring_len: self.mm.free(self._tx_buffers[self._tx_ci]) self._tx_ci += 1 if self._tx_ci == self.tx_ring_len: self._tx_ci = 0 if self.verbose: if tx_ci == self._tx_ci + 1: print "[.] freeing tx buffer %02x" % self._tx_ci elif tx_ci > self._tx_ci: print "[.] freeing tx buffers %02x-%02x" % (self._tx_ci, tx_ci - 1) while tx_ci > self._tx_ci: self.mm.free(self._tx_buffers[self._tx_ci]) self._tx_ci += 1 if self.verbose: print "[+] interrupt handling concluded" self.dev.hpmb.box[tg.mb_interrupt].low = tag _ = self.dev.hpmb.box[tg.mb_interrupt].low def _write_pkt(self, pkt, length): super(TapDriver, self)._write_pkt(pkt, length) self.stats.pkt_in(length) def send(self, data, flags=None): if len(data) < 64: data = data + ('\x00' * (64 - len(data))) b_vaddr = self.mm.alloc(len(data)) b = ctypes.cast(b_vaddr, ctypes.POINTER(ctypes.c_char * len(data))) b[0] = (ctypes.c_char * len(data)).from_buffer_copy(data) self._send_b(b_vaddr, len(data), flags=flags) def _send_b(self, buf, buf_sz, flags=None): i = self._tx_pi self._tx_buffers[i] = buf if self.verbose: print "[+] sending buffer at %x len 0x%x using sbd #%d" % (buf, buf_sz, i) paddr = self.mm.get_paddr(buf) txb = ctypes.cast(self.tx_ring_vaddr, ctypes.POINTER(tg.sbd)) txb[i].addr_hi = paddr >> 32 txb[i].addr_low = paddr & 0xffffffff txb[i].length = buf_sz txb[i].flags.packet_end = 1 if flags != None: for j in flags: setattr(txb[i].flags, j, 1) i += 1 if i == self.tx_ring_len: i = 0 self.dev.hpmb.box[tg.mb_sbd_host_producer].low = i _ = self.dev.hpmb.box[tg.mb_sbd_host_producer].low self._tx_pi = i if self.verbose: print "[+] host sbd pi now %x" % i self.stats.pkt_out(buf_sz) def _handle_tap(self): pkt, sz = self._get_packet() self._send_b(pkt, sz) def _handle_keypress(self, handlers): k = self._get_key() if k in handlers: handlers[k][1]() elif k == '' or k == ' ' or k == None: pass else: print "keypress '%s' unhandled. press 'h' for help." % k def _help(self, handlers): print for k in handlers: print "%s - %s" % (k, handlers[k][0]) print def toggle_verbosity(self): self.verbose = not self.verbose print "[+] verbosity %s" % ("enabled" if self.verbose else "disabled") def run(self): self.dev.unmask_interrupts() print "[+] waiting for interrupts..." k_handlers = {'q': ("quit", functools.partial(sys.exit, 0)), 'd': ("link detect", functools.partial(TapDriver._link_detect, self)), 'v': ("toggle verbosity", functools.partial(TapDriver.toggle_verbosity, self)), 's': ("dump statistics", functools.partial(TapStatistics.display, self.stats)), 'r': ("reset statistics", functools.partial(TapStatistics.reset, self.stats))} k_handlers['h'] = ("help", functools.partial(TapDriver._help, self, k_handlers)) e_handlers = {0: functools.partial(TapDriver._handle_keypress, self, k_handlers), 1: functools.partial(TapDriver._handle_interrupt, self), 2: functools.partial(TapDriver._handle_tap, self)} while True: e_handlers[self._wait_for_something()]()