# 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.}

# 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.}

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")

proc fiber_netswitch_entry*() {.cdecl.} =
  kprintln("[NetSwitch] Fiber Entry - The Traffic Cop is ON DUTY")
  
  var rx_activity: bool = false
  var tx_activity: bool = false
  
  while true:
    rx_activity = false
    tx_activity = false
    
    # ============================================
    # RX PATH: Hardware -> chan_net_rx -> Userland
    # ============================================
    # virtio_net_poll() internally calls ion_ingress() which pushes
    # received packets to the hardware driver's internal ring.
    # We poll here to drive the RX path.
    virtio_net_poll()
    
    # ============================================
    # TX PATH: Userland -> chan_net_tx -> 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))
      ion_free(tx_pkt)
      tx_activity = true
    
    # ============================================
    # YIELD STRATEGY
    # ============================================
    if rx_activity or tx_activity:
      # War Mode: Continue processing if we moved data
      continue
    else:
      # Peace Mode: Yield to let other fibers run
      fiber_yield()

{.pop.}
