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