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