Files
claude-os/src/ethernet.h
AI 35bafdcad9 Implement Ethernet subsystem with unified NIC abstraction (AI)
- Created src/ethernet.h: eth_iface_t interface struct, Ethernet header
  type, htons/ntohs/htonl/ntohl byte-order helpers, EtherType constants,
  send/recv with automatic header construction/stripping
- Created src/ethernet.c: interface table, char device ops routed
  through ethernet layer, sysfs /sys/net namespace exposing per-iface
  mac/ip/netmask/gateway/link files, IPv4 address parse/format
- NE2000 and 3C509B drivers now register through ethernet_register()
  instead of directly via devicefs_register_char(); removed redundant
  char device ops from both drivers
- Kernel calls ethernet_init() before init_drivers() so the subsystem
  is ready when NIC drivers probe
- Tested: NE2000 detected with NIC, 'eth1' registered via ethernet
  subsystem; clean boot without NIC
2026-02-24 07:24:56 +00:00

209 lines
6.7 KiB
C

/**
* @file ethernet.h
* @brief Ethernet subsystem.
*
* Provides a unified abstraction over individual Ethernet NIC drivers.
* Each NIC driver registers itself with the ethernet subsystem, which
* then creates the `/dev/ethN` character device and exposes interface
* information via `/sys/net`.
*
* Higher-level protocols (IPv4, ARP, etc.) use this subsystem to send
* and receive Ethernet frames without knowing which NIC driver is in use.
*/
#ifndef ETHERNET_H
#define ETHERNET_H
#include <stdint.h>
/** Maximum number of Ethernet interfaces. */
#define ETH_MAX_IFACES 8
/** Ethernet MAC address length. */
#define ETH_ALEN 6
/** Ethernet header size (dst + src + ethertype). */
#define ETH_HLEN 14
/** Maximum Ethernet payload size. */
#define ETH_MTU 1500
/** Maximum Ethernet frame size (header + payload). */
#define ETH_FRAME_LEN (ETH_HLEN + ETH_MTU)
/* ================================================================
* EtherType constants
* ================================================================ */
#define ETHERTYPE_IPV4 0x0800 /**< IPv4 */
#define ETHERTYPE_ARP 0x0806 /**< ARP */
/* ================================================================
* Ethernet header (14 bytes)
* ================================================================ */
/**
* Ethernet frame header.
*/
typedef struct __attribute__((packed)) eth_header {
uint8_t dst[ETH_ALEN]; /**< Destination MAC address. */
uint8_t src[ETH_ALEN]; /**< Source MAC address. */
uint16_t ethertype; /**< EtherType (big-endian). */
} eth_header_t;
/* ================================================================
* NIC driver callbacks
* ================================================================ */
/**
* Callback to send a raw Ethernet frame (complete with header).
*
* @param dev_data Driver-specific device pointer.
* @param frame Complete Ethernet frame (header + payload).
* @param len Frame length in bytes.
* @return 0 on success, -1 on failure.
*/
typedef int (*eth_send_fn)(void *dev_data, const void *frame, uint32_t len);
/**
* Callback to receive a raw Ethernet frame (complete with header).
*
* @param dev_data Driver-specific device pointer.
* @param buf Buffer for received frame.
* @param bufsize Buffer size.
* @return Number of bytes received, 0 if none, -1 on error.
*/
typedef int (*eth_recv_fn)(void *dev_data, void *buf, uint32_t bufsize);
/* ================================================================
* Ethernet interface
* ================================================================ */
/**
* Represents one Ethernet network interface.
*/
typedef struct eth_iface {
char name[16]; /**< Interface name (e.g., "eth1"). */
uint8_t mac[ETH_ALEN]; /**< MAC address. */
uint8_t active; /**< 1 if registered, 0 if free. */
uint8_t link_up; /**< 1 if link is up. */
uint32_t ip_addr; /**< IPv4 address (0 if not configured). */
uint32_t netmask; /**< Subnet mask (0 if not configured). */
uint32_t gateway; /**< Default gateway (0 if not configured). */
eth_send_fn send; /**< NIC driver send callback. */
eth_recv_fn recv; /**< NIC driver receive callback. */
void *dev_data; /**< Opaque pointer to NIC driver state. */
} eth_iface_t;
/* ================================================================
* Public API
* ================================================================ */
/**
* Initialize the ethernet subsystem.
* Registers sysfs namespace "net" and prepares the interface table.
*/
void ethernet_init(void);
/**
* Register a NIC with the ethernet subsystem.
*
* Creates a `/dev/ethN` character device and adds the interface to the
* internal table. Called by NIC drivers during initialization.
*
* @param mac 6-byte MAC address.
* @param send Send callback function.
* @param recv Receive callback function.
* @param dev_data Opaque NIC device pointer (passed to callbacks).
* @return Pointer to the registered interface, or NULL on failure.
*/
eth_iface_t *ethernet_register(const uint8_t *mac,
eth_send_fn send,
eth_recv_fn recv,
void *dev_data);
/**
* Send an Ethernet frame through an interface.
*
* Constructs the Ethernet header (src MAC from interface, dst from caller)
* and dispatches through the NIC driver.
*
* @param iface Interface to send through.
* @param dst_mac Destination MAC address (6 bytes).
* @param ethertype EtherType (host byte order, will be converted to big-endian).
* @param payload Frame payload.
* @param len Payload length (max ETH_MTU).
* @return 0 on success, -1 on failure.
*/
int ethernet_send(eth_iface_t *iface, const uint8_t *dst_mac,
uint16_t ethertype, const void *payload, uint32_t len);
/**
* Receive an Ethernet frame from an interface.
*
* @param iface Interface to receive from.
* @param buf Buffer for frame payload (Ethernet header is stripped).
* @param bufsize Buffer size.
* @param src_mac Output: source MAC of received frame (6 bytes, can be NULL).
* @param ethertype Output: EtherType of received frame (host byte order, can be NULL).
* @return Payload length in bytes, 0 if no packet, -1 on error.
*/
int ethernet_recv(eth_iface_t *iface, void *buf, uint32_t bufsize,
uint8_t *src_mac, uint16_t *ethertype);
/**
* Get an interface by index.
*
* @param index 0-based index.
* @return Pointer to interface, or NULL if index out of range.
*/
eth_iface_t *ethernet_get_iface(uint32_t index);
/**
* Get the number of registered interfaces.
*
* @return Number of active Ethernet interfaces.
*/
uint32_t ethernet_get_iface_count(void);
/**
* Find an interface by name (e.g., "eth1").
*
* @param name Interface name.
* @return Pointer to interface, or NULL if not found.
*/
eth_iface_t *ethernet_find_iface(const char *name);
/**
* Convert a 16-bit value from host to network byte order (big-endian).
*/
static inline uint16_t htons(uint16_t h) {
return (uint16_t)((h >> 8) | (h << 8));
}
/**
* Convert a 16-bit value from network to host byte order.
*/
static inline uint16_t ntohs(uint16_t n) {
return htons(n);
}
/**
* Convert a 32-bit value from host to network byte order (big-endian).
*/
static inline uint32_t htonl(uint32_t h) {
return ((h >> 24) & 0x000000FF) |
((h >> 8) & 0x0000FF00) |
((h << 8) & 0x00FF0000) |
((h << 24) & 0xFF000000);
}
/**
* Convert a 32-bit value from network to host byte order.
*/
static inline uint32_t ntohl(uint32_t n) {
return htonl(n);
}
#endif /* ETHERNET_H */