SilverOS implements three network protocols — ARP, IPv4, and ICMP — as thin, self-contained C modules that sit above the RTL8139 Ethernet driver. Each module handles one layer of the stack: ARP maps IP addresses to MAC addresses, IPv4 routes packets to the right protocol handler or builds outbound datagrams, and ICMP processes incoming ping requests and drives outbound echo requests from the kernel terminal. This page documents every public function, the shared type system, and the precise data flow through all three layers.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/pastaboy12345/SilverOS/llms.txt
Use this file to discover all available pages before exploring further.
Type definitions
All protocol structures and address types are defined ininclude/net.h with __attribute__((packed)) to guarantee no compiler-inserted padding. The byte layout of each struct maps exactly onto the wire format.
mac_addr_t and ip_addr_t are simple byte arrays. All multi-byte fields in the structs are stored in network byte order (big-endian) and must be converted with htons/ntohs or htonl/ntohl before use — see the Endianness helpers section of the overview.
ARP
Address Resolution Protocol translates an IPv4 address into the MAC address needed to construct an Ethernet frame. SilverOS implements a flat, statically-sized ARP cache innet/arp.c.
Cache. The cache holds 16 entries, each storing a validated (ip_addr_t, mac_addr_t) pair and an integer valid flag. arp_init zeroes all valid flags; it is called by net_init during boot.
Receiving ARP packets. arp_handle_packet is invoked by net_receive_packet for every frame with EtherType 0x0806. It first validates that the hardware type is 1 (Ethernet) and the protocol type is 0x0800 (IPv4), then unconditionally caches the sender’s IP-to-MAC mapping by scanning for an existing entry with that IP or the first free slot. If the packet is an ARP request (op == 1) addressed to net_my_ip, the function immediately builds a 28-byte ARP reply, swaps the sender and target fields, fills sender_mac with rtl8139_mac, and delivers it via ethernet_send.
Resolving a MAC address. arp_resolve scans all 16 cache entries for a valid match. On a hit it copies the cached MAC into *out_mac and returns 1. On a miss it calls arp_request to broadcast a 28-byte ARP request to net_bcast_mac, then returns 0 — the caller is responsible for retrying after the reply arrives and populates the cache.
The ARP cache is an in-memory array and is not persisted across reboots. After a hard reset, every IP-to-MAC mapping is lost. The first attempt to send a packet to a previously known address will trigger a new ARP request, and the initial outbound packet will be dropped while the exchange completes. A second attempt after the reply arrives will succeed.
IPv4
SilverOS’s IPv4 implementation innet/ipv4.c handles both the inbound path (demultiplexing received datagrams to the correct protocol handler) and the outbound path (building a standard 20-byte header and resolving the destination MAC before handing the frame to Ethernet).
Receiving IPv4 packets. ipv4_handle_packet is called by net_receive_packet for frames with EtherType 0x0800. It checks that the IP version field is 4, computes the header length from ihl * 4, and silently drops any packet not addressed to net_my_ip. For packets that pass the destination check, it calculates the payload pointer and length from total_length, then dispatches on proto:
proto == 1→icmp_handle_packet(ip_hdr, payload, payload_len)
ipv4_send constructs a 20-byte IPv4 header in a local 1536-byte buffer:
version = 4,ihl = 5(no options),tos = 0total_length=sizeof(ipv4_header_t) + payload_len, converted to network byte orderidentification= auto-incrementing 16-bit counterip_id++, in network byte orderflags_fragment = 0(no fragmentation)ttl = 64proto= caller-supplied protocol numberchecksum= computed bynet_checksumover the 20-byte header (checksum field zeroed first)src_ip=net_my_ip,dest_ip= caller-supplied destination
ipv4_send calls arp_resolve. On success, the complete packet is passed to ethernet_send with EtherType 0x0800. On failure (ARP miss), the packet is dropped and a message is written to serial output:
ICMP
ICMP in SilverOS (net/icmp.c) provides two capabilities: responding to incoming Echo Requests (ping replies) and generating outbound Echo Requests from the kernel terminal (ping command).
Handling incoming ICMP. icmp_handle_packet is called by ipv4_handle_packet with the already-parsed ipv4_header_t pointer (needed for the source IP), the ICMP payload, and its byte length. It dispatches on icmp->type:
-
Type 8 — Echo Request: logs the sender’s IP to serial, then constructs an Echo Reply in a local buffer. The reply header sets
type = 0andcode = 0, copiesidentifierandsequenceverbatim from the request, zeroes the checksum field, copies the request’s payload bytes after the header, and computes the checksum over the entire ICMP message. The reply is sent viaipv4_sendback toip_hdr->src_ip. -
Type 0 — Echo Reply: logs the sender’s IP and
ntohs(icmp->sequence)to serial output. No further action is taken.
icmp_send_echo_request builds a 40-byte ICMP packet: an 8-byte header followed by 32 bytes of dummy ASCII payload ('A' through 'Z' repeating). The identifier is always 0x1234; the sequence number is drawn from a static ping_seq counter that increments with each call. The checksum is computed over the full 40 bytes before the packet is handed to ipv4_send.
ping command calls icmp_send_echo_request and prints a confirmation:
make run with -serial stdio, looks like:
Packet flow example
The following traces a complete outbound ping from the moment the terminal command is issued to the moment the raw frame exits the NIC:- Terminal calls
icmp_send_echo_request({10, 0, 2, 2}). - ICMP (
net/icmp.c) builds a 40-byte packet: 8-byteicmp_header_t(type=8,id=0x1234,seq=ping_seq++) plus 32 bytes of'A'–'Z'payload.net_checksumis run over all 40 bytes and stored inicmp->checksum. - ICMP calls
ipv4_send({10, 0, 2, 2}, 1, packet, 40). - IPv4 (
net/ipv4.c) prepends a 20-byteipv4_header_t(version=4,ihl=5,ttl=64,proto=1,src=10.0.2.15,dest=10.0.2.2), computes the IPv4 header checksum vianet_checksum. - IPv4 calls
arp_resolve({10, 0, 2, 2}, &dest_mac):- Cache hit → proceeds immediately.
- Cache miss →
arp_requestbroadcasts an ARP request; IPv4 logs a drop message to serial and returns. The caller must retry after the ARP reply is received.
- Ethernet (
net/ethernet.c) prepends a 14-byteethernet_header_t(dest=dest_mac,src=rtl8139_mac,type=0x0800in network byte order) to produce a 74-byte frame. - RTL8139 (
drivers/rtl8139.c) copies the frame into one of four 1536-byte transmit buffers, writes the buffer address to the appropriateTSADregister, and writes the length to theTSDregister to trigger DMA transmission.