Skip to main content

LIG Script Architecture

Code Structure

The lig.py script is made up of the following modules:

1. Nokia LI Shim Parser

The Nokia ip-udp-shim format has the following structure:

BytesFieldDescription
0-1FlagsBit 15 = address (0=ingress, 1=egress)
23Intercept-IDInterception identifier (uint16)
4-5Padding0x0000
6-7Session-IDSession identifier (uint16)
8+Ethernet FrameFrame Ethernet with QinQ + IP inner

The parser navigates the layers:

  1. Nokia Shim (8 bytes): Extract flags, intercept-id, session-id, address
  2. Ethernet Header: MAC dst/src + 802.1Q tags (outer/inner VLAN)
  3. IP Header: Detect IPv4 or IPv6, extract src/dst IP, protocol, ports

2. UDP Listener

def udp_listener():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 11111))
while True:
data, addr = sock.recvfrom(65535)
parsed = parse_shim(data)
# Almacenar en deque y actualizar estadísticas

3. REST API

EndpointMethodDescription
/GETHTML Dashboard
/api/eventsGETEvent list (params: limit, intercept_id)
/api/statsGETGlobal statistics
/api/interceptsGETList of active intercept-ids
/api/clearGETClear all data

4. Memory Storage

  • events: deque(maxlen=2000) - Last 2000 events parsed
  • stats: Dictionary with global counters (total, ingress, egress, ipv4, ipv6)
  • stats["intercepts"]: Dictionary by intercept_id with packets, bytes, first/last_seen
  • Thread-safe with threading.Lock()

Design Decisions

Why these decisions
  • No external dependencies: Just use Python stdlib to work on any Linux container without installing packages
  • Deque with maxlen: Limit memory usage to 2000 events, discarding the oldest ones automatically
  • Threading: One thread for the UDP listener and another for the HTTP server, both daemons for automatic cleaning
  • Generic 802.1Q Parser: Navigate up to 3 chained VLAN tags, supporting both QinQ and single-tag