rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | #include <dev/class/netif.h> |
| 2 | #include <kernel/event.h> |
| 3 | #include <arch/ops.h> |
| 4 | #include <netif/etharp.h> |
| 5 | #include <lwip/netif.h> |
| 6 | #include <lwip/dhcp.h> |
| 7 | #include <debug.h> |
| 8 | #include <trace.h> |
| 9 | #include <assert.h> |
| 10 | #include <list.h> |
| 11 | #include <err.h> |
| 12 | |
| 13 | #define LOCAL_TRACE 0 |
| 14 | |
| 15 | struct local_netif { |
| 16 | struct netif netif; |
| 17 | struct device *dev; |
| 18 | }; |
| 19 | |
| 20 | static event_t netif_up_event = EVENT_INITIAL_VALUE(netif_up_event, false, 0); |
| 21 | static volatile int netif_up_count = 0; |
| 22 | |
| 23 | static err_t local_linkoutput(struct netif *netif, struct pbuf *p) |
| 24 | { |
| 25 | LTRACE_ENTRY; |
| 26 | |
| 27 | struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| 28 | DEBUG_ASSERT(nif); |
| 29 | |
| 30 | status_t res = class_netif_output(nif->dev, p); |
| 31 | |
| 32 | LTRACE_EXIT; |
| 33 | |
| 34 | switch (res) { |
| 35 | case NO_ERROR: return ERR_OK; |
| 36 | case ERR_NO_MEMORY: return ERR_MEM; |
| 37 | case ERR_TIMED_OUT: return ERR_TIMEOUT; |
| 38 | default: return ERR_IF; |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | static void local_netif_status(struct netif *netif) |
| 43 | { |
| 44 | struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| 45 | DEBUG_ASSERT(nif); |
| 46 | |
| 47 | if (netif->flags & NETIF_FLAG_UP) { |
| 48 | TRACEF("netif %c%c ip %u.%u.%u.%u netmask %u.%u.%u.%u gw %u.%u.%u.%u\n", |
| 49 | netif->name[0], netif->name[1], |
| 50 | ip4_addr1_16(&netif->ip_addr), |
| 51 | ip4_addr2_16(&netif->ip_addr), |
| 52 | ip4_addr3_16(&netif->ip_addr), |
| 53 | ip4_addr4_16(&netif->ip_addr), |
| 54 | ip4_addr1_16(&netif->netmask), |
| 55 | ip4_addr2_16(&netif->netmask), |
| 56 | ip4_addr3_16(&netif->netmask), |
| 57 | ip4_addr4_16(&netif->netmask), |
| 58 | ip4_addr1_16(&netif->gw), |
| 59 | ip4_addr2_16(&netif->gw), |
| 60 | ip4_addr3_16(&netif->gw), |
| 61 | ip4_addr4_16(&netif->gw)); |
| 62 | |
| 63 | if (atomic_add(&netif_up_count, 1) >= 0) |
| 64 | event_signal(&netif_up_event, true); |
| 65 | } else { |
| 66 | if (atomic_add(&netif_up_count, -1) == 1) |
| 67 | event_unsignal(&netif_up_event); |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | static err_t local_netif_init(struct netif *netif) |
| 72 | { |
| 73 | LTRACE_ENTRY; |
| 74 | |
| 75 | struct local_netif *nif = containerof(netif, struct local_netif, netif); |
| 76 | DEBUG_ASSERT(nif); |
| 77 | |
| 78 | netif->linkoutput = local_linkoutput; |
| 79 | netif->output = etharp_output; |
| 80 | |
| 81 | netif->hwaddr_len = class_netif_get_hwaddr(nif->dev, netif->hwaddr, sizeof(netif->hwaddr)); |
| 82 | netif->mtu = class_netif_get_mtu(nif->dev); |
| 83 | |
| 84 | netif->name[0] = 'e'; |
| 85 | netif->name[1] = 'n'; |
| 86 | netif->num = 0; |
| 87 | netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; |
| 88 | |
| 89 | LTRACE_EXIT; |
| 90 | |
| 91 | return ERR_OK; |
| 92 | } |
| 93 | |
| 94 | status_t class_netstack_wait_for_network(lk_time_t timeout) |
| 95 | { |
| 96 | status_t res; |
| 97 | |
| 98 | LTRACE_ENTRY; |
| 99 | |
| 100 | res = event_wait_timeout(&netif_up_event, timeout); |
| 101 | LTRACEF("res=%d\n", res); |
| 102 | |
| 103 | LTRACE_EXIT; |
| 104 | return res; |
| 105 | } |
| 106 | |
| 107 | status_t class_netif_add(struct device *dev) |
| 108 | { |
| 109 | status_t err; |
| 110 | ip_addr_t ipaddr, netmask, gw; |
| 111 | |
| 112 | struct local_netif *nif = malloc(sizeof(struct local_netif)); |
| 113 | if (!nif) |
| 114 | return ERR_NO_MEMORY; |
| 115 | |
| 116 | nif->dev = dev; |
| 117 | |
| 118 | err = class_netif_set_state(dev, (struct netstack_state *) nif); |
| 119 | if (err) |
| 120 | goto done; |
| 121 | |
| 122 | IP4_ADDR(&gw, 0, 0, 0, 0); |
| 123 | IP4_ADDR(&ipaddr, 0, 0, 0, 0); |
| 124 | IP4_ADDR(&netmask, 255, 255, 255, 255); |
| 125 | |
| 126 | netif_add(&nif->netif, &ipaddr, &netmask, &gw, nif, local_netif_init, ethernet_input); |
| 127 | netif_set_default(&nif->netif); |
| 128 | netif_set_status_callback(&nif->netif, local_netif_status); |
| 129 | dhcp_start(&nif->netif); |
| 130 | |
| 131 | err = NO_ERROR; |
| 132 | |
| 133 | done: |
| 134 | return err; |
| 135 | } |
| 136 | |
| 137 | status_t class_netstack_input(struct device *dev, struct netstack_state *state, struct pbuf *p) |
| 138 | { |
| 139 | LTRACE_ENTRY; |
| 140 | |
| 141 | struct local_netif *nif = (struct local_netif *) state; |
| 142 | if (!nif) |
| 143 | return ERR_INVALID_ARGS; |
| 144 | |
| 145 | if (nif->netif.input(p, &nif->netif) != ERR_OK) |
| 146 | pbuf_free(p); |
| 147 | |
| 148 | LTRACE_EXIT; |
| 149 | |
| 150 | return NO_ERROR; |
| 151 | } |
| 152 | |