# ION Soft-Switch # Sovereign Dispatch Logic import memory import ../ring import ../net # For LwIP fallback proc console_write(p: pointer, len: csize_t) {.importc, cdecl.} type FlowType* = enum FLOW_LWIP # The Unix Path FLOW_DIRECT # The ION Path # A Subscription to the Bus NetFlow* = object port*: uint16 ring*: ptr RingBuffer[IonPacket, 256] # Direct injection ring fType*: FlowType var # The Lookup Table (Simple Array for Phase 7) # Index = Port Number. flow_table: array[65536, ptr NetFlow] proc ion_register*(port: uint16, flow: ptr NetFlow) = flow_table[port] = flow proc parse_dest_port(data: ptr UncheckedArray[byte]): uint16 = # Ethernet Type at 12. IP Protocol at 23. Dest Port at 36. if data[12] == 0x08 and data[13] == 0x00: # IPv4 let proto = data[23] if proto == 17: # UDP let dport = (uint16(data[36]) shl 8) or uint16(data[37]) return dport return 0 proc dispatch_packet(data: ptr UncheckedArray[byte], len: int, id: uint16) = let dest_port = parse_dest_port(data) let flow = if dest_port != 0: flow_table[dest_port] else: nil if dest_port == 8080: var msg = "[ION SW] 8080 Hit! RingPtr=" console_write(addr msg[0], csize_t(msg.len)) # Simple address check (first 8 bytes of ptr) if flow != nil: var hex_str = "ADR\n" console_write(addr hex_str[0], 4) var pkt: IonPacket pkt.id = id pkt.len = uint16(len) pkt.data = data if flow != nil and flow.fType == FLOW_DIRECT: if flow.ring[].push(pkt): var msg = "[ION SW] Pushed to Ring!\n" console_write(addr msg[0], csize_t(msg.len)) else: var msg = "[ION SW] Ring FULL!\n" console_write(addr msg[0], csize_t(msg.len)) ion_free_raw(id) else: discard net_ingest_packet(cast[ptr byte](pkt.data), int(pkt.len)) ion_free_raw(id) proc ion_ingress*(id: uint16, len: uint16) {.exportc.} = ## The Hot Path. Called by VirtIO Interrupt/Poller. ## Takes a Slab ID that has been filled by NIC or local TX. const VIRTIO_NET_HDR_SIZE = 10 let slab_base = ion_get_virt(id) if len <= VIRTIO_NET_HDR_SIZE: # Packet too small (just header or less) ion_free_raw(id) return # Adjust for Headroom (Zero-Copy Pointer Math) # eth_frame points to the Ethernet Header, skipping VirtIO Header let eth_frame = cast[ptr UncheckedArray[byte]](cast[uint](slab_base) + VIRTIO_NET_HDR_SIZE) let eth_len = int(len) - VIRTIO_NET_HDR_SIZE # DEBUG: Print RX packet info (Full Eth Header) var prefix = "[ION] RX: " console_write(addr prefix[0], csize_t(prefix.len)) const hexDigits = "0123456789ABCDEF" for i in 0..<14: let b = eth_frame[i] var hex: array[3, char] hex[0] = hexDigits[int(b shr 4)] hex[1] = hexDigits[int(b and 0xF)] hex[2] = if i == 5 or i == 11: '|' else: ' ' if i == 13: hex[2] = '\n' console_write(addr hex[0], 3) dispatch_packet(eth_frame, eth_len, id) proc ion_egress*(pkt: IonPacket) {.exportc.} = ## The Fast Path TX (Standard Interface) if not ion_tx_push(pkt): # Backpressure / Ring Full -> Drop var msg = "[ION SW] TX Ring FULL! Dropping.\n" console_write(addr msg[0], csize_t(msg.len)) ion_free(pkt) proc ion_egress_to_port*(port: uint16, pkt: IonPacket) {.exportc.} = ## Route a packet to a specific ION Port. ## Port 0 is reserved for Kernel Console. if port == 0: when defined(is_kernel): console_write(pkt.data, csize_t(pkt.len)) ion_free(pkt) else: # In the Membrane, Port 0 egresses to the Bus ion_egress(pkt) else: # Future: Internal routing via flow_table ion_egress(pkt)