WIP minip add interface layer

This commit is contained in:
Travis Geiselbrecht
2022-03-31 00:16:57 -07:00
parent bce9599d80
commit d0a71b1b94
8 changed files with 228 additions and 24 deletions

View File

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

View 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

View File

@@ -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()));

View File

@@ -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 *);

View File

@@ -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
View 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);
}

View File

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

View File

@@ -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);