# SPDX-License-Identifier: LSL-1.0 # Copyright (c) 2026 Markus Maiwald # Stewardship: Self Sovereign Society Foundation # # This file is part of the Nexus Sovereign Core. # See legal/LICENSE_SOVEREIGN.md for license terms. ## Rumpk Layer 1: Software Network Switch # core/rumpk/core/netswitch.nim # Phase 36.2: The Traffic Cop (Network Membrane Layer 2 Switch) # # Responsibilities: # - Poll VirtIO-Net hardware for incoming packets # - Route RX packets to s_net_rx ring (Kernel -> Userland) # - Drain s_net_tx ring and transmit via VirtIO-Net (Userland -> Kernel) # - Never yield during active traffic (War Mode latency optimization) {.push stackTrace: off, lineTrace: off.} import ion # Forward declare fiber_yield to avoid circular import proc fiber_yield*() {.importc, cdecl.} proc fiber_sleep*(ms: int) {.importc, cdecl.} # HAL Imports proc virtio_net_poll() {.importc, cdecl.} proc virtio_net_send(data: pointer, len: uint32) {.importc, cdecl.} # Logging proc kprintln(s: cstring) {.importc, cdecl.} proc kprint(s: cstring) {.importc, cdecl.} proc kprint_hex(v: uint64) {.importc, cdecl.} proc get_now_ns(): uint64 {.importc: "rumpk_timer_now_ns", cdecl.} # Membrane Infrastructure (LwIP Glue) proc membrane_init*() {.importc, cdecl.} proc pump_membrane_stack*() {.importc, cdecl.} var netswitch_initialized: bool = false proc netswitch_init*() = ## Initialize network channels and populate SysTable ## MUST be called before userland starts! ion_init_network() kprintln("[NetSwitch] Network Rings Initialized") netswitch_initialized = true proc netswitch_attach_systable*(sys: ptr SysTable) = ## Attach network ring pointers to SysTable for userland access sys.s_net_rx = chan_net_rx.ring sys.s_net_tx = chan_net_tx.ring kprintln("[NetSwitch] SysTable Rings Attached") type EthHeader* {.packed.} = object dst*: array[6, byte] src*: array[6, byte] ethertype*: uint16 # Big Endian proc swap16(v: uint16): uint16 = ((v and 0xFF) shl 8) or (v shr 8) proc netswitch_process_packet(pkt: IonPacket): bool = ## Layer 2 Demultiplexer if pkt.len < 14: ion_free(pkt) return false let eth = cast[ptr EthHeader](pkt.data) let etype = swap16(eth.ethertype) case etype: of 0x0800, 0x0806, 0x86DD: # IPv4, ARP, IPv6 # Route to Legacy/LwIP Membrane if not chan_net_rx.send(pkt): # Ring full (Backpressure) ion_free(pkt) return false return true of 0x88B5: # Sovereign UTCP (SPEC-700) # TODO: Route to dedicated UTCP channel # kprintln("[NetSwitch] UTCP Sovereign Packet Identified") ion_free(pkt) return true # Handled (dropped) else: # Drop unknown EtherTypes (Security/Sovereignty) ion_free(pkt) return false proc fiber_netswitch_entry*() {.cdecl.} = membrane_init() kprintln("[NetSwitch] Fiber Entry - The Traffic Cop is ON DUTY") var rx_activity: bool = false var tx_activity: bool = false var rx_count: uint64 = 0 var tx_count: uint64 = 0 var last_stat_print: uint64 = 0 while true: rx_activity = false tx_activity = false # 1. Drive the hardware poll (fills chan_netswitch_rx) virtio_net_poll() # 2. Drive the LwIP Stack (Timers/RX) pump_membrane_stack() # 2. Consume from the Driver -> Switch internal ring var raw_pkt: IonPacket while chan_netswitch_rx.recv(raw_pkt): if netswitch_process_packet(raw_pkt): rx_activity = true inc rx_count # 3. TX PATH: Userland -> Hardware var tx_pkt: IonPacket while chan_net_tx.recv(tx_pkt): if tx_pkt.data != nil and tx_pkt.len > 0: virtio_net_send(cast[pointer](tx_pkt.data), uint32(tx_pkt.len)) inc tx_count ion_free(tx_pkt) tx_activity = true # 4. Periodically print stats let now = get_now_ns() if now - last_stat_print > 5000000000'u64: # 5 seconds kprint("[NetSwitch] STATS - RX: ") kprint_hex(rx_count) kprint(" TX: ") kprint_hex(tx_count) kprintln("") last_stat_print = now # 5. Yield Strategy if rx_activity or tx_activity: # War Mode: High priority processing continue else: fiber_sleep(10) {.pop.}