| #include <dev/class/netif.h> |
| #include <kernel/event.h> |
| #include <arch/ops.h> |
| #include <netif/etharp.h> |
| #include <lwip/netif.h> |
| #include <lwip/dhcp.h> |
| #include <debug.h> |
| #include <trace.h> |
| #include <assert.h> |
| #include <list.h> |
| #include <err.h> |
| |
| #define LOCAL_TRACE 0 |
| |
| struct local_netif { |
| struct netif netif; |
| struct device *dev; |
| }; |
| |
| static event_t netif_up_event = EVENT_INITIAL_VALUE(netif_up_event, false, 0); |
| static volatile int netif_up_count = 0; |
| |
| static err_t local_linkoutput(struct netif *netif, struct pbuf *p) |
| { |
| LTRACE_ENTRY; |
| |
| struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| DEBUG_ASSERT(nif); |
| |
| status_t res = class_netif_output(nif->dev, p); |
| |
| LTRACE_EXIT; |
| |
| switch (res) { |
| case NO_ERROR: return ERR_OK; |
| case ERR_NO_MEMORY: return ERR_MEM; |
| case ERR_TIMED_OUT: return ERR_TIMEOUT; |
| default: return ERR_IF; |
| } |
| } |
| |
| static void local_netif_status(struct netif *netif) |
| { |
| struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| DEBUG_ASSERT(nif); |
| |
| if (netif->flags & NETIF_FLAG_UP) { |
| TRACEF("netif %c%c ip %u.%u.%u.%u netmask %u.%u.%u.%u gw %u.%u.%u.%u\n", |
| netif->name[0], netif->name[1], |
| ip4_addr1_16(&netif->ip_addr), |
| ip4_addr2_16(&netif->ip_addr), |
| ip4_addr3_16(&netif->ip_addr), |
| ip4_addr4_16(&netif->ip_addr), |
| ip4_addr1_16(&netif->netmask), |
| ip4_addr2_16(&netif->netmask), |
| ip4_addr3_16(&netif->netmask), |
| ip4_addr4_16(&netif->netmask), |
| ip4_addr1_16(&netif->gw), |
| ip4_addr2_16(&netif->gw), |
| ip4_addr3_16(&netif->gw), |
| ip4_addr4_16(&netif->gw)); |
| |
| if (atomic_add(&netif_up_count, 1) >= 0) |
| event_signal(&netif_up_event, true); |
| } else { |
| if (atomic_add(&netif_up_count, -1) == 1) |
| event_unsignal(&netif_up_event); |
| } |
| } |
| |
| static err_t local_netif_init(struct netif *netif) |
| { |
| LTRACE_ENTRY; |
| |
| struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| DEBUG_ASSERT(nif); |
| |
| netif->linkoutput = local_linkoutput; |
| netif->output = etharp_output; |
| |
| netif->hwaddr_len = class_netif_get_hwaddr(nif->dev, netif->hwaddr, sizeof(netif->hwaddr)); |
| netif->mtu = class_netif_get_mtu(nif->dev); |
| |
| netif->name[0] = 'e'; |
| netif->name[1] = 'n'; |
| netif->num = 0; |
| netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; |
| |
| LTRACE_EXIT; |
| |
| return ERR_OK; |
| } |
| |
| status_t class_netstack_wait_for_network(lk_time_t timeout) |
| { |
| status_t res; |
| |
| LTRACE_ENTRY; |
| |
| res = event_wait_timeout(&netif_up_event, timeout); |
| LTRACEF("res=%d\n", res); |
| |
| LTRACE_EXIT; |
| return res; |
| } |
| |
| status_t class_netif_add(struct device *dev) |
| { |
| status_t err; |
| ip_addr_t ipaddr, netmask, gw; |
| |
| struct local_netif *nif = malloc(sizeof(struct local_netif)); |
| if (!nif) |
| return ERR_NO_MEMORY; |
| |
| nif->dev = dev; |
| |
| err = class_netif_set_state(dev, (struct netstack_state *) nif); |
| if (err) |
| goto done; |
| |
| IP4_ADDR(&gw, 0, 0, 0, 0); |
| IP4_ADDR(&ipaddr, 0, 0, 0, 0); |
| IP4_ADDR(&netmask, 255, 255, 255, 255); |
| |
| netif_add(&nif->netif, &ipaddr, &netmask, &gw, nif, local_netif_init, ethernet_input); |
| netif_set_default(&nif->netif); |
| netif_set_status_callback(&nif->netif, local_netif_status); |
| dhcp_start(&nif->netif); |
| |
| err = NO_ERROR; |
| |
| done: |
| return err; |
| } |
| |
| status_t class_netstack_input(struct device *dev, struct netstack_state *state, struct pbuf *p) |
| { |
| LTRACE_ENTRY; |
| |
| struct local_netif *nif = (struct local_netif *) state; |
| if (!nif) |
| return ERR_INVALID_ARGS; |
| |
| if (nif->netif.input(p, &nif->netif) != ERR_OK) |
| pbuf_free(p); |
| |
| LTRACE_EXIT; |
| |
| return NO_ERROR; |
| } |
| |