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
This commit is contained in:
208
src/ethernet.h
Normal file
208
src/ethernet.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @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 */
|
||||
Reference in New Issue
Block a user