WIP minip add interface layer
This commit is contained in:
@@ -24,6 +24,9 @@ __BEGIN_CDECLS
|
||||
#define IPV4_BCAST (0xFFFFFFFF)
|
||||
#define IPV4_NONE (0)
|
||||
|
||||
/* types */
|
||||
typedef uint32_t ipv4_addr_t;
|
||||
|
||||
typedef int (*tx_func_t)(void *arg, pktbuf_t *p);
|
||||
typedef void (*udp_callback_t)(void *data, size_t len,
|
||||
uint32_t srcaddr, uint16_t srcport, void *arg);
|
||||
@@ -52,12 +55,12 @@ void minip_get_macaddr(uint8_t *addr);
|
||||
void minip_set_macaddr(const uint8_t *addr);
|
||||
|
||||
uint32_t minip_get_ipaddr(void);
|
||||
void minip_set_ipaddr(const uint32_t addr);
|
||||
void minip_set_ipaddr(const ipv4_addr_t addr);
|
||||
uint32_t minip_get_netmask(void);
|
||||
void minip_set_netmask(const uint32_t mask);
|
||||
void minip_set_netmask(const ipv4_addr_t mask);
|
||||
uint32_t minip_get_broadcast(void); // computed from ipaddr & netmask
|
||||
uint32_t minip_get_gateway(void);
|
||||
void minip_set_gateway(const uint32_t addr);
|
||||
void minip_set_gateway(const ipv4_addr_t addr);
|
||||
void minip_set_hostname(const char *name);
|
||||
const char *minip_get_hostname(void);
|
||||
void minip_set_configured(void); // set by dhcp or static init to signal minip is ready to be used
|
||||
@@ -92,5 +95,6 @@ uint32_t minip_parse_ipaddr(const char *addr, size_t len);
|
||||
uint32_t minip_parse_ipaddr(const char *addr, size_t len);
|
||||
void printip(uint32_t x);
|
||||
void printip_named(const char *s, u32 x);
|
||||
void print_mac_address(const uint8_t *mac);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
60
lib/minip/include/lib/minip/netif.h
Normal file
60
lib/minip/include/lib/minip/netif.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Travis Geiselbrecht
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <lib/minip.h>
|
||||
|
||||
// Network interface layer for minip
|
||||
|
||||
// Per network interface structure, created by the network driver and registered
|
||||
// with the net stack.
|
||||
struct netif {
|
||||
uint32_t magic;
|
||||
struct list_node node;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
// mac address
|
||||
uint8_t mac_address[6];
|
||||
|
||||
// ipv4 address
|
||||
ipv4_addr_t ipv4_addr;
|
||||
uint8_t ipv4_subnet_width;
|
||||
|
||||
// driver tx routine
|
||||
tx_func_t tx_func;
|
||||
void *tx_func_arg;
|
||||
|
||||
// name
|
||||
char name[32];
|
||||
};
|
||||
typedef struct netif netif_t;
|
||||
#define NETIF_MAGIC 'NETI'
|
||||
|
||||
#define NETIF_FLAG_ETH_CONFIGURED (1U << 0) // mac address and tx func set
|
||||
#define NETIF_FLAG_REGISTERED (1U << 1) // added to the main list
|
||||
#define NETIF_FLAG_IPV4_CONFIGURED (1U << 2) // ipv4 address is set
|
||||
|
||||
// Initialize a netif struct.
|
||||
// Allocates a new one if passed in pointer is null.
|
||||
netif_t *netif_create(netif_t *n, const char *name);
|
||||
|
||||
status_t netif_set_eth(netif_t *n, tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr);
|
||||
status_t netif_set_ipv4_addr(netif_t *n, ipv4_addr_t addr, uint8_t subnet_width);
|
||||
status_t netif_register(netif_t *n);
|
||||
|
||||
// construct netmask and broadcast addresses dynamically
|
||||
static inline ipv4_addr_t netif_get_netmask_ipv4(netif_t *n) {
|
||||
return n->ipv4_addr & (0xffffffff >> n->ipv4_subnet_width);
|
||||
}
|
||||
static inline ipv4_addr_t netif_get_broadcast_ipv4(netif_t *n) {
|
||||
return (n->ipv4_addr & netif_get_netmask_ipv4(n)) | (0xffffffff << (32 - n->ipv4_subnet_width));
|
||||
}
|
||||
|
||||
// TODO: add temporary hack to remember the first real NIC as the 'main' one and replace global
|
||||
// stuff in minip.c with a lookup for this
|
||||
@@ -66,6 +66,7 @@ static int cmd_minip(int argc, const console_cmd_args *argv) {
|
||||
minip_usage:
|
||||
printf("minip commands\n");
|
||||
printf("mi [a]rp dump arp table\n");
|
||||
printf("mi [i]interfaces dump interface list\n");
|
||||
printf("mi [s]tatus print ip status\n");
|
||||
printf("mi [t]est [dest] [port] [cnt] send <cnt> test packets to the dest:port\n");
|
||||
} else {
|
||||
@@ -75,6 +76,9 @@ minip_usage:
|
||||
arp_cache_dump();
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
netif_dump();
|
||||
break;
|
||||
case 's': {
|
||||
printf("hostname: %s\n", minip_get_hostname());
|
||||
printf("ip: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_ipaddr()));
|
||||
|
||||
@@ -91,7 +91,6 @@ extern void *minip_tx_arg;
|
||||
|
||||
typedef struct udp_hdr udp_hdr_t;
|
||||
static const uint8_t bcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
typedef uint32_t ipv4_addr;
|
||||
typedef union {
|
||||
uint32_t u;
|
||||
uint8_t b[4];
|
||||
@@ -120,6 +119,10 @@ void udp_input(pktbuf_t *p, uint32_t src_ip);
|
||||
|
||||
const uint8_t *get_dest_mac(uint32_t host);
|
||||
|
||||
// interface list
|
||||
void netif_init(void);
|
||||
void netif_dump(void);
|
||||
|
||||
// timers
|
||||
typedef void (*net_timer_callback_t)(void *);
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
// TODO
|
||||
// 1. Tear endian code out into something that flips words before/after tx/rx calls
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
static uint32_t minip_ip = IPV4_NONE;
|
||||
static uint32_t minip_netmask = IPV4_NONE;
|
||||
static uint32_t minip_broadcast = IPV4_BCAST;
|
||||
static uint32_t minip_gateway = IPV4_NONE;
|
||||
#define LOCAL_TRACE 1
|
||||
static ipv4_addr_t minip_ip = IPV4_NONE;
|
||||
static ipv4_addr_t minip_netmask = IPV4_NONE;
|
||||
static ipv4_addr_t minip_broadcast = IPV4_BCAST;
|
||||
static ipv4_addr_t minip_gateway = IPV4_NONE;
|
||||
|
||||
static const uint8_t broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
static uint8_t minip_mac[6] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
|
||||
@@ -46,7 +46,6 @@ static event_t minip_configured_event = EVENT_INITIAL_VALUE(minip_configured_eve
|
||||
tx_func_t minip_tx_handler;
|
||||
void *minip_tx_arg;
|
||||
|
||||
static void dump_mac_address(const uint8_t *mac);
|
||||
static void dump_ipv4_addr(uint32_t addr);
|
||||
|
||||
/* if all the important configuration bits are set, signal that we're configured */
|
||||
@@ -88,7 +87,7 @@ uint32_t minip_get_ipaddr(void) {
|
||||
return minip_ip;
|
||||
}
|
||||
|
||||
void minip_set_ipaddr(const uint32_t addr) {
|
||||
void minip_set_ipaddr(const ipv4_addr_t addr) {
|
||||
minip_ip = addr;
|
||||
compute_broadcast_address();
|
||||
check_and_set_configured();
|
||||
@@ -102,7 +101,7 @@ uint32_t minip_get_netmask(void) {
|
||||
return minip_netmask;
|
||||
}
|
||||
|
||||
void minip_set_netmask(const uint32_t netmask) {
|
||||
void minip_set_netmask(const ipv4_addr_t netmask) {
|
||||
minip_netmask = netmask;
|
||||
compute_broadcast_address();
|
||||
check_and_set_configured();
|
||||
@@ -112,7 +111,7 @@ uint32_t minip_get_gateway(void) {
|
||||
return minip_gateway;
|
||||
}
|
||||
|
||||
void minip_set_gateway(const uint32_t addr) {
|
||||
void minip_set_gateway(const ipv4_addr_t addr) {
|
||||
minip_gateway = addr;
|
||||
// TODO: check that it is reacheable on local network
|
||||
check_and_set_configured();
|
||||
@@ -477,9 +476,9 @@ __NO_INLINE static int handle_arp_pkt(pktbuf_t *p) {
|
||||
|
||||
static void dump_eth_packet(const struct eth_hdr *eth) {
|
||||
printf("ETH src ");
|
||||
dump_mac_address(eth->src_mac);
|
||||
print_mac_address(eth->src_mac);
|
||||
printf(" dst ");
|
||||
dump_mac_address(eth->dst_mac);
|
||||
print_mac_address(eth->dst_mac);
|
||||
printf(" type 0x%hx\n", htons(eth->type));
|
||||
}
|
||||
|
||||
@@ -513,7 +512,7 @@ void minip_rx_driver_callback(pktbuf_t *p) {
|
||||
}
|
||||
}
|
||||
|
||||
void dump_mac_address(const uint8_t *mac) {
|
||||
void print_mac_address(const uint8_t *mac) {
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
@@ -557,6 +556,7 @@ void printip_named(const char *s, uint32_t x) {
|
||||
static void minip_init(uint level) {
|
||||
arp_cache_init();
|
||||
net_timer_init();
|
||||
netif_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
132
lib/minip/netif.c
Normal file
132
lib/minip/netif.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Travis Geiselbrecht
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
|
||||
#include <lib/minip/netif.h>
|
||||
|
||||
#include <lk/err.h>
|
||||
#include <lk/list.h>
|
||||
#include <lk/trace.h>
|
||||
#include <lib/minip.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <kernel/mutex.h>
|
||||
|
||||
#include "minip-internal.h"
|
||||
|
||||
#define LOCAL_TRACE 1
|
||||
|
||||
static struct list_node netif_list = LIST_INITIAL_VALUE(netif_list);
|
||||
static mutex_t lock = MUTEX_INITIAL_VALUE(lock);
|
||||
static netif_t loopback;
|
||||
|
||||
static int loopback_tx_func(void *arg, pktbuf_t *p) {
|
||||
LTRACEF("arg %p, pkt %p\n", arg, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void netif_init(void) {
|
||||
LTRACE;
|
||||
|
||||
// loopback device
|
||||
netif_create(&loopback, "loopback");
|
||||
netif_set_eth(&loopback, loopback_tx_func, NULL, bcast_mac);
|
||||
netif_set_ipv4_addr(&loopback, IPV4(128, 0, 0, 1), 8);
|
||||
netif_register(&loopback);
|
||||
}
|
||||
|
||||
netif_t *netif_create(netif_t *n, const char *name) {
|
||||
LTRACEF("n %p\n", n);
|
||||
|
||||
if (!n) {
|
||||
n = malloc(sizeof(netif_t));
|
||||
}
|
||||
if (!n) {
|
||||
return n;
|
||||
}
|
||||
|
||||
memset(n, 0, sizeof(*n));
|
||||
|
||||
n->magic = NETIF_MAGIC;
|
||||
strlcpy(n->name, name, sizeof(n->name));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
status_t netif_register(netif_t *n) {
|
||||
LTRACEF("n %p\n", n);
|
||||
|
||||
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
|
||||
|
||||
mutex_acquire(&lock);
|
||||
|
||||
// check that it is at least configured
|
||||
DEBUG_ASSERT(n->flags & NETIF_FLAG_ETH_CONFIGURED);
|
||||
DEBUG_ASSERT((n->flags & NETIF_FLAG_REGISTERED) == 0);
|
||||
|
||||
list_add_head(&netif_list, &n->node);
|
||||
n->flags |= NETIF_FLAG_REGISTERED;
|
||||
|
||||
mutex_release(&lock);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t netif_set_eth(netif_t *n, tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr) {
|
||||
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
|
||||
DEBUG_ASSERT(tx_handler);
|
||||
|
||||
mutex_acquire(&lock);
|
||||
|
||||
// must not have been already configured
|
||||
DEBUG_ASSERT((n->flags & NETIF_FLAG_ETH_CONFIGURED) == 0);
|
||||
|
||||
// set the state and mark configured
|
||||
mac_addr_copy(n->mac_address, macaddr);
|
||||
n->tx_func = tx_handler;
|
||||
n->tx_func_arg = tx_arg;
|
||||
n->flags |= NETIF_FLAG_ETH_CONFIGURED;
|
||||
|
||||
mutex_release(&lock);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t netif_set_ipv4_addr(netif_t *n, ipv4_addr_t addr, uint8_t subnet_width) {
|
||||
DEBUG_ASSERT(n->magic == NETIF_MAGIC);
|
||||
|
||||
mutex_acquire(&lock);
|
||||
|
||||
n->ipv4_addr = addr;
|
||||
n->ipv4_subnet_width = subnet_width;
|
||||
n->flags |= NETIF_FLAG_IPV4_CONFIGURED;
|
||||
|
||||
mutex_release(&lock);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void netif_dump(void) {
|
||||
mutex_acquire(&lock);
|
||||
|
||||
netif_t *n;
|
||||
list_for_every_entry(&netif_list, n, netif_t, node) {
|
||||
printf("net interface @%p: name '%s' mac ", n, n->name);
|
||||
print_mac_address(n->mac_address);
|
||||
printf(" addr ");
|
||||
printip(n->ipv4_addr);
|
||||
printf("/%u", n->ipv4_subnet_width);
|
||||
printf(" net ");
|
||||
printip(netif_get_netmask_ipv4(n));
|
||||
printf(" bcast ");
|
||||
printip(netif_get_broadcast_ipv4(n));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
mutex_release(&lock);
|
||||
}
|
||||
@@ -15,6 +15,7 @@ MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/lk_console.c \
|
||||
$(LOCAL_DIR)/minip.c \
|
||||
$(LOCAL_DIR)/net_timer.c \
|
||||
$(LOCAL_DIR)/netif.c \
|
||||
$(LOCAL_DIR)/pktbuf.c \
|
||||
$(LOCAL_DIR)/tcp.c \
|
||||
$(LOCAL_DIR)/udp.c
|
||||
|
||||
@@ -37,8 +37,8 @@ typedef struct tcp_header {
|
||||
} __PACKED tcp_header_t;
|
||||
|
||||
typedef struct tcp_pseudo_header {
|
||||
ipv4_addr source_addr;
|
||||
ipv4_addr dest_addr;
|
||||
ipv4_addr_t source_addr;
|
||||
ipv4_addr_t dest_addr;
|
||||
uint8_t zero;
|
||||
uint8_t protocol;
|
||||
uint16_t tcp_length;
|
||||
@@ -80,8 +80,8 @@ typedef struct tcp_socket {
|
||||
volatile int ref;
|
||||
|
||||
tcp_state_t state;
|
||||
ipv4_addr local_ip;
|
||||
ipv4_addr remote_ip;
|
||||
ipv4_addr_t local_ip;
|
||||
ipv4_addr_t remote_ip;
|
||||
uint16_t local_port;
|
||||
uint16_t remote_port;
|
||||
|
||||
@@ -138,11 +138,11 @@ static struct list_node tcp_socket_list = LIST_INITIAL_VALUE(tcp_socket_list);
|
||||
static bool tcp_debug = false;
|
||||
|
||||
/* local routines */
|
||||
static tcp_socket_t *lookup_socket(ipv4_addr remote_ip, ipv4_addr local_ip, uint16_t remote_port, uint16_t local_port);
|
||||
static tcp_socket_t *lookup_socket(ipv4_addr_t remote_ip, ipv4_addr_t local_ip, uint16_t remote_port, uint16_t local_port);
|
||||
static void add_socket_to_list(tcp_socket_t *s);
|
||||
static void remove_socket_from_list(tcp_socket_t *s);
|
||||
static tcp_socket_t *create_tcp_socket(bool alloc_buffers);
|
||||
static status_t tcp_send(ipv4_addr dest_ip, uint16_t dest_port, ipv4_addr src_ip, uint16_t src_port, const void *buf,
|
||||
static status_t tcp_send(ipv4_addr_t dest_ip, uint16_t dest_port, ipv4_addr_t src_ip, uint16_t src_port, const void *buf,
|
||||
size_t len, tcp_flags_t flags, const void *options, size_t options_length, uint32_t ack, uint32_t sequence, uint16_t window_size);
|
||||
static status_t tcp_socket_send(tcp_socket_t *s, const void *data, size_t len, tcp_flags_t flags, const void *options, size_t options_length, uint32_t sequence);
|
||||
static void handle_data(tcp_socket_t *s, const void *data, size_t len, uint32_t sequence);
|
||||
@@ -216,7 +216,7 @@ static void dump_socket(tcp_socket_t *s) {
|
||||
}
|
||||
}
|
||||
|
||||
static tcp_socket_t *lookup_socket(ipv4_addr remote_ip, ipv4_addr local_ip, uint16_t remote_port, uint16_t local_port) {
|
||||
static tcp_socket_t *lookup_socket(ipv4_addr_t remote_ip, ipv4_addr_t local_ip, uint16_t remote_port, uint16_t local_port) {
|
||||
LTRACEF_LEVEL(2, "remote ip 0x%x local ip 0x%x remote port %u local port %u\n", remote_ip, local_ip, remote_port, local_port);
|
||||
|
||||
mutex_acquire(&tcp_socket_list_lock);
|
||||
@@ -719,7 +719,7 @@ static void send_ack(tcp_socket_t *s) {
|
||||
tcp_socket_send(s, NULL, 0, PKT_ACK, NULL, 0, s->tx_win_low);
|
||||
}
|
||||
|
||||
static status_t tcp_send(ipv4_addr dest_ip, uint16_t dest_port, ipv4_addr src_ip, uint16_t src_port, const void *buf,
|
||||
static status_t tcp_send(ipv4_addr_t dest_ip, uint16_t dest_port, ipv4_addr_t src_ip, uint16_t src_port, const void *buf,
|
||||
size_t len, tcp_flags_t flags, const void *options, size_t options_length, uint32_t ack, uint32_t sequence, uint16_t window_size) {
|
||||
DEBUG_ASSERT(len == 0 || buf);
|
||||
DEBUG_ASSERT(options_length == 0 || options);
|
||||
|
||||
Reference in New Issue
Block a user