[lib][minip] add a mechanism to wait for the stack to be configured

Configured in this case means an ip address assigned and a nic
installed.
This commit is contained in:
Travis Geiselbrecht
2021-05-28 17:06:00 -07:00
committed by Travis Geiselbrecht
parent 9caf62273c
commit fe28bd8a95
13 changed files with 152 additions and 66 deletions

View File

@@ -172,14 +172,15 @@ static void zynq_common_target_init(uint level) {
sysparam_read("net0.ip_mask", &ip_mask, sizeof(ip_mask)); sysparam_read("net0.ip_mask", &ip_mask, sizeof(ip_mask));
sysparam_read("net0.ip_gateway", &ip_gateway, sizeof(ip_gateway)); sysparam_read("net0.ip_gateway", &ip_gateway, sizeof(ip_gateway));
minip_set_macaddr(mac_addr);
gem_set_macaddr(mac_addr); gem_set_macaddr(mac_addr);
minip_set_eth(gem_send_raw_pkt, NULL, mac_addr);
if (!use_dhcp && ip_addr != IPV4_NONE) { if (!use_dhcp && ip_addr != IPV4_NONE) {
minip_init(gem_send_raw_pkt, NULL, ip_addr, ip_mask, ip_gateway); minip_start_static(ip_addr, ip_mask, ip_gateway);
} else { } else {
/* Configure IP stack and hook to the driver */ /* Configure IP stack and hook to the driver */
minip_init_dhcp(gem_send_raw_pkt, NULL); minip_start_dhcp();
} }
gem_set_callback(minip_rx_driver_callback); gem_set_callback(minip_rx_driver_callback);
#endif #endif

View File

@@ -60,6 +60,8 @@ public:
bool is_e1000e() const { return id_feat_->e1000e; } bool is_e1000e() const { return id_feat_->e1000e; }
const uint8_t *mac_addr() const { return mac_addr_; }
private: private:
static const size_t rxring_len = 64; static const size_t rxring_len = 64;
static const size_t txring_len = 64; static const size_t txring_len = 64;
@@ -428,10 +430,6 @@ status_t e1000::init_device(pci_location_t loc, const e1000_id_features *id) {
} }
LTRACEF("IRQ number %#x\n", irq_base); LTRACEF("IRQ number %#x\n", irq_base);
// set up minip's macaddr
// TODO: move to something smarter
minip_set_macaddr(mac_addr_);
unmask_interrupt(irq_base); unmask_interrupt(irq_base);
// set up the rx ring // set up the rx ring
@@ -513,9 +511,7 @@ status_t e1000::init_device(pci_location_t loc, const e1000_id_features *id) {
return NO_ERROR; return NO_ERROR;
} }
// XXX REMOVE HACK static int e1000_tx(pktbuf_t *p) {
extern "C"
int e1000_tx(pktbuf_t *p) {
if (the_e) { if (the_e) {
the_e->tx(p); the_e->tx(p);
} }
@@ -523,6 +519,16 @@ int e1000_tx(pktbuf_t *p) {
return NO_ERROR; return NO_ERROR;
} }
extern "C"
status_t e1000_register_with_minip() {
if (the_e) {
minip_set_eth(e1000_tx, the_e, the_e->mac_addr());
return NO_ERROR;
}
return ERR_NOT_FOUND;
}
static void e1000_init(uint level) { static void e1000_init(uint level) {
LTRACE_ENTRY; LTRACE_ENTRY;

11
docs/lk_tap.txt Normal file
View File

@@ -0,0 +1,11 @@
# Setting up a tun/tap network for qemu
sudo ip tuntap add mode tap user $USER name qemu0
sudo ip link set qemu0 up
# manually making bridge
sudo brctl addbr br0
sudo brctl addif br0 qemu0
sudo brctl addif br0 <physical nic>
sudo ip link set br0 up
# alternatively using the network config to create the bridge and merge it with particular vlan

View File

@@ -322,6 +322,9 @@ done:
} }
state_ = CONFIGURED; state_ = CONFIGURED;
configured_ = true; configured_ = true;
// signal that minip is ready to be used
minip_set_configured();
} }
} }
} }
@@ -375,9 +378,7 @@ status_t dhcp::start() {
} // anonymous namespace } // anonymous namespace
void minip_init_dhcp(tx_func_t tx_func, void *tx_arg) { void minip_start_dhcp() {
minip_init(tx_func, tx_arg, IPV4_NONE, IPV4_NONE, IPV4_NONE);
static dhcp d; static dhcp d;
d.start(); d.start();
} }

View File

@@ -28,12 +28,21 @@ typedef int (*tx_func_t)(pktbuf_t *p);
typedef void (*udp_callback_t)(void *data, size_t len, typedef void (*udp_callback_t)(void *data, size_t len,
uint32_t srcaddr, uint16_t srcport, void *arg); uint32_t srcaddr, uint16_t srcport, void *arg);
/* initialize minip with static configuration */ /* initialize and start minip with static configuration */
void minip_init(tx_func_t tx_func, void *tx_arg, void minip_start_static(uint32_t ip, uint32_t netmask, uint32_t gateway);
uint32_t ip, uint32_t netmask, uint32_t gateway);
/* initialize minip with DHCP configuration */ /* initialize and start minip with DHCP configuration
void minip_init_dhcp(tx_func_t tx_func, void *tx_arg); * note: may take a while to have an ip address assigned, check
* for configuration with minip_is_configured()
*/
void minip_start_dhcp(void);
/* ethernet driver install hook */
void minip_set_eth(tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr);
/* check or wait for minip to be configured */
bool minip_is_configured(void);
status_t minip_wait_for_configured(lk_time_t timeout);
/* packet rx hook to hand to ethernet driver */ /* packet rx hook to hand to ethernet driver */
void minip_rx_driver_callback(pktbuf_t *p); void minip_rx_driver_callback(pktbuf_t *p);
@@ -49,17 +58,9 @@ void minip_set_netmask(const uint32_t mask);
uint32_t minip_get_broadcast(void); // computed from ipaddr & netmask uint32_t minip_get_broadcast(void); // computed from ipaddr & netmask
uint32_t minip_get_gateway(void); uint32_t minip_get_gateway(void);
void minip_set_gateway(const uint32_t addr); void minip_set_gateway(const uint32_t addr);
void minip_set_hostname(const char *name); void minip_set_hostname(const char *name);
const char *minip_get_hostname(void); 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
uint32_t minip_get_broadcast(void);
uint32_t minip_get_netmask(void);
void minip_set_netmask(const uint32_t netmask);
uint32_t minip_get_gateway(void);
void minip_set_gateway(const uint32_t gateway);
/* udp */ /* udp */
typedef struct udp_socket udp_socket_t; typedef struct udp_socket udp_socket_t;
@@ -86,6 +87,7 @@ static inline status_t tcp_accept(tcp_socket_t *listen_socket, tcp_socket_t **ac
/* utilities */ /* utilities */
void gen_random_mac_address(uint8_t *mac_addr); void gen_random_mac_address(uint8_t *mac_addr);
uint32_t minip_parse_ipaddr(const char *addr, size_t len);
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(uint32_t x);

View File

@@ -9,6 +9,7 @@
#include "minip-internal.h" #include "minip-internal.h"
#include <assert.h>
#include <lk/err.h> #include <lk/err.h>
#include <stdio.h> #include <stdio.h>
#include <lk/debug.h> #include <lk/debug.h>
@@ -20,6 +21,8 @@
#include <lk/trace.h> #include <lk/trace.h>
#include <malloc.h> #include <malloc.h>
#include <lk/list.h> #include <lk/list.h>
#include <lk/init.h>
#include <kernel/event.h>
#include <kernel/thread.h> #include <kernel/thread.h>
// TODO // TODO
@@ -36,11 +39,37 @@ static uint8_t minip_mac[6] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
static char minip_hostname[32] = ""; static char minip_hostname[32] = "";
static volatile bool minip_configured = false;
static event_t minip_configured_event = EVENT_INITIAL_VALUE(minip_configured_event, false, 0);
/* This function is called by minip to send packets */
tx_func_t minip_tx_handler;
void *minip_tx_arg;
static void dump_mac_address(const uint8_t *mac); static void dump_mac_address(const uint8_t *mac);
static void dump_ipv4_addr(uint32_t addr); static void dump_ipv4_addr(uint32_t addr);
/* if all the important configuration bits are set, signal that we're configured */
static void check_and_set_configured(void) {
if (minip_ip == IPV4_NONE) return;
if (minip_netmask == IPV4_NONE) return;
if (minip_broadcast == IPV4_BCAST) return;
// minip_gateway doesn't have to be set
if (minip_mac[0] == 0xcc &&
minip_mac[1] == 0xcc &&
minip_mac[2] == 0xcc &&
minip_mac[3] == 0xcc &&
minip_mac[4] == 0xcc &&
minip_mac[5] == 0xcc) return;
// we're configured
printf("MINIP: setting configured state\n");
minip_set_configured();
}
void minip_set_hostname(const char *name) { void minip_set_hostname(const char *name) {
strlcpy(minip_hostname, name, sizeof(minip_hostname)); strlcpy(minip_hostname, name, sizeof(minip_hostname));
check_and_set_configured();
} }
const char *minip_get_hostname(void) { const char *minip_get_hostname(void) {
@@ -55,10 +84,6 @@ void minip_get_macaddr(uint8_t *addr) {
mac_addr_copy(addr, minip_mac); mac_addr_copy(addr, minip_mac);
} }
void minip_set_macaddr(const uint8_t *addr) {
mac_addr_copy(minip_mac, addr);
}
uint32_t minip_get_ipaddr(void) { uint32_t minip_get_ipaddr(void) {
return minip_ip; return minip_ip;
} }
@@ -66,6 +91,7 @@ uint32_t minip_get_ipaddr(void) {
void minip_set_ipaddr(const uint32_t addr) { void minip_set_ipaddr(const uint32_t addr) {
minip_ip = addr; minip_ip = addr;
compute_broadcast_address(); compute_broadcast_address();
check_and_set_configured();
} }
uint32_t minip_get_broadcast(void) { uint32_t minip_get_broadcast(void) {
@@ -79,14 +105,30 @@ uint32_t minip_get_netmask(void) {
void minip_set_netmask(const uint32_t netmask) { void minip_set_netmask(const uint32_t netmask) {
minip_netmask = netmask; minip_netmask = netmask;
compute_broadcast_address(); compute_broadcast_address();
check_and_set_configured();
} }
uint32_t minip_get_gateway(void) { uint32_t minip_get_gateway(void) {
return minip_gateway; return minip_gateway;
} }
void minip_set_gateway(const uint32_t gateway) { void minip_set_gateway(const uint32_t addr) {
minip_gateway = gateway; minip_gateway = addr;
// TODO: check that it is reacheable on local network
check_and_set_configured();
}
void minip_set_configured(void) {
minip_configured = true;
event_signal(&minip_configured_event, true);
}
bool minip_is_configured(void) {
return minip_configured;
}
status_t minip_wait_for_configured(lk_time_t timeout) {
return event_wait_timeout(&minip_configured_event, timeout);
} }
void gen_random_mac_address(uint8_t *mac_addr) { void gen_random_mac_address(uint8_t *mac_addr) {
@@ -98,21 +140,24 @@ void gen_random_mac_address(uint8_t *mac_addr) {
mac_addr[0] |= (1<<1); mac_addr[0] |= (1<<1);
} }
/* This function is called by minip to send packets */ void minip_start_static(uint32_t ip, uint32_t mask, uint32_t gateway) {
tx_func_t minip_tx_handler;
void *minip_tx_arg;
void minip_init(tx_func_t tx_handler, void *tx_arg,
uint32_t ip, uint32_t mask, uint32_t gateway) {
minip_tx_handler = tx_handler;
minip_tx_arg = tx_arg;
minip_set_ipaddr(ip); minip_set_ipaddr(ip);
minip_set_netmask(mask); minip_set_netmask(mask);
minip_set_gateway(gateway); minip_set_gateway(gateway);
}
arp_cache_init(); void minip_set_eth(tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr) {
net_timer_init(); LTRACEF("handler %p, arg %p, macaddr %p\n", tx_handler, tx_arg, macaddr);
DEBUG_ASSERT(minip_tx_handler == NULL);
DEBUG_ASSERT(minip_tx_arg == NULL);
// TODO: assert mac address is not already set
// set up the low level driver handler
minip_tx_handler = tx_handler;
minip_tx_arg = tx_arg;
mac_addr_copy(minip_mac, macaddr);
} }
static uint16_t ipv4_payload_len(struct ipv4_hdr *pkt) { static uint16_t ipv4_payload_len(struct ipv4_hdr *pkt) {
@@ -507,3 +552,12 @@ void printip_named(const char *s, uint32_t x) {
printf("%s ", s); printf("%s ", s);
printip(x); printip(x);
} }
// run static initialization
static void minip_init(uint level) {
arp_cache_init();
net_timer_init();
}
LK_INIT_HOOK(minip, minip_init, LK_INIT_LEVEL_THREADING);

View File

@@ -9,6 +9,7 @@
*/ */
#include <lk/err.h> #include <lk/err.h>
#include <lk/init.h>
#include <lk/trace.h> #include <lk/trace.h>
#include <arch/x86/mmu.h> #include <arch/x86/mmu.h>
#include <platform.h> #include <platform.h>
@@ -300,9 +301,16 @@ void platform_init(void) {
#endif #endif
platform_init_mmu_mappings(); platform_init_mmu_mappings();
}
#if WITH_LIB_MINIP #if WITH_LIB_MINIP
extern int e1000_tx(pktbuf_t *p); void _start_minip(uint level) {
minip_init_dhcp(e1000_tx, 0); extern status_t e1000_register_with_minip(void);
#endif status_t err = e1000_register_with_minip();
if (err == NO_ERROR) {
minip_start_dhcp();
}
} }
LK_INIT_HOOK(start_minip, _start_minip, LK_INIT_LEVEL_APPS - 1);
#endif

View File

@@ -226,16 +226,16 @@ void platform_init(void) {
TRACEF("found virtio networking interface\n"); TRACEF("found virtio networking interface\n");
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(virtio_net_send_minip_pkt, NULL, mac_addr);
__UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99); __UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99);
__UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0); __UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0);
__UNUSED uint32_t ip_gateway = IPV4_NONE; __UNUSED uint32_t ip_gateway = IPV4_NONE;
//minip_init(virtio_net_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway);
minip_init_dhcp(virtio_net_send_minip_pkt, NULL);
virtio_net_start(); virtio_net_start();
//minip_start_static(ip_addr, ip_mask, ip_gateway);
minip_start_dhcp();
} }
#endif #endif
} }

View File

@@ -106,16 +106,16 @@ void platform_init(void) {
TRACEF("found virtio networking interface\n"); TRACEF("found virtio networking interface\n");
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(virtio_net_send_minip_pkt, NULL, mac_addr);
__UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99); __UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99);
__UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0); __UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0);
__UNUSED uint32_t ip_gateway = IPV4_NONE; __UNUSED uint32_t ip_gateway = IPV4_NONE;
//minip_init(virtio_net_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway);
minip_init_dhcp(virtio_net_send_minip_pkt, NULL);
virtio_net_start(); virtio_net_start();
//minip_start_static(ip_addr, ip_mask, ip_gateway);
minip_start_dhcp();
} }
#endif #endif
} }

View File

@@ -198,16 +198,19 @@ void platform_init(void) {
TRACEF("found virtio networking interface\n"); TRACEF("found virtio networking interface\n");
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(virtio_net_send_minip_pkt, NULL, mac_addr);
virtio_net_start();
#if 0
__UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99); __UNUSED uint32_t ip_addr = IPV4(192, 168, 0, 99);
__UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0); __UNUSED uint32_t ip_mask = IPV4(255, 255, 255, 0);
__UNUSED uint32_t ip_gateway = IPV4_NONE; __UNUSED uint32_t ip_gateway = IPV4_NONE;
//minip_init(virtio_net_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway); minip_start_static(ip_addr, ip_mask, ip_gateway);
minip_init_dhcp(virtio_net_send_minip_pkt, NULL); #else
minip_start_dhcp();
virtio_net_start(); #endif
} }
#endif #endif
} }

View File

@@ -123,13 +123,13 @@ void target_init(void) {
eth_init(mac_addr, PHY_KSZ8721); eth_init(mac_addr, PHY_KSZ8721);
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(stm32_eth_send_minip_pkt, NULL, mac_addr);
uint32_t ip_addr = IPV4(192, 168, 0, 98); uint32_t ip_addr = IPV4(192, 168, 0, 98);
uint32_t ip_mask = IPV4(255, 255, 255, 0); uint32_t ip_mask = IPV4(255, 255, 255, 0);
uint32_t ip_gateway = IPV4_NONE; uint32_t ip_gateway = IPV4_NONE;
minip_init(stm32_eth_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway); minip_start_static(ip_addr, ip_mask, ip_gateway);
#endif #endif
#if WITH_LIB_FS_SPIFS #if WITH_LIB_FS_SPIFS

View File

@@ -67,13 +67,13 @@ void target_init(void) {
eth_init(mac_addr, PHY_DP83848); eth_init(mac_addr, PHY_DP83848);
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(stm32_eth_send_minip_pkt, NULL, mac_addr);
uint32_t ip_addr = IPV4(192, 168, 0, 99); uint32_t ip_addr = IPV4(192, 168, 0, 99);
uint32_t ip_mask = IPV4(255, 255, 255, 0); uint32_t ip_mask = IPV4(255, 255, 255, 0);
uint32_t ip_gateway = IPV4_NONE; uint32_t ip_gateway = IPV4_NONE;
minip_init(stm32_eth_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway); minip_start_static(ip_addr, ip_mask, ip_gateway);
#endif #endif
TRACE_EXIT; TRACE_EXIT;

View File

@@ -64,13 +64,13 @@ void target_init(void) {
eth_init(mac_addr, PHY_LAN8742A); eth_init(mac_addr, PHY_LAN8742A);
/* start minip */ /* start minip */
minip_set_macaddr(mac_addr); minip_set_eth(stm32_eth_send_minip_pkt, NULL, mac_addr);
uint32_t ip_addr = IPV4(192, 168, 0, 98); uint32_t ip_addr = IPV4(192, 168, 0, 98);
uint32_t ip_mask = IPV4(255, 255, 255, 0); uint32_t ip_mask = IPV4(255, 255, 255, 0);
uint32_t ip_gateway = IPV4_NONE; uint32_t ip_gateway = IPV4_NONE;
minip_init(stm32_eth_send_minip_pkt, NULL, ip_addr, ip_mask, ip_gateway); minip_start_static(ip_addr, ip_mask, ip_gateway);
#endif #endif
// start usb // start usb