- 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
209 lines
6.7 KiB
C
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 */
|