/** * @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 /** 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 */