source: mainline/uspace/srv/net/ethip/ethip.c@ f93ba6d5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f93ba6d5 was 1c635d6, checked in by Martin Sucha <sucha14@…>, 11 years ago

Do not hold a task's return value after it has disconnected.

Holding the task's return value meant that if nobody waited
for task's result, it polluted NS's memory. This was apparently
done because of a race between spawning a task and waiting for it.

We solve this problem in another way: ns discards the return value
as soon as the task disconnects from it. This typically happens
when the task finishes its execution. In order to avoid the race,
we send the wait request to ns while spawning the task (i.e. when
we talk to the loader), but before we allow the loaded program
to run.

Fixes #132

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ethip
30 * @{
31 */
32/**
33 * @file
34 * @brief IP link provider for Ethernet
35 *
36 * Based on the IETF RFC 894 standard.
37 */
38
39#include <async.h>
40#include <errno.h>
41#include <inet/iplink_srv.h>
42#include <io/log.h>
43#include <loc.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <task.h>
47#include "arp.h"
48#include "ethip.h"
49#include "ethip_nic.h"
50#include "pdu.h"
51#include "std.h"
52
53#define NAME "ethip"
54
55static int ethip_open(iplink_srv_t *srv);
56static int ethip_close(iplink_srv_t *srv);
57static int ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu);
58static int ethip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu);
59static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
60static int ethip_get_mac48(iplink_srv_t *srv, addr48_t *mac);
61static int ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr);
62static int ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr);
63
64static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
65
66static iplink_ops_t ethip_iplink_ops = {
67 .open = ethip_open,
68 .close = ethip_close,
69 .send = ethip_send,
70 .send6 = ethip_send6,
71 .get_mtu = ethip_get_mtu,
72 .get_mac48 = ethip_get_mac48,
73 .addr_add = ethip_addr_add,
74 .addr_remove = ethip_addr_remove
75};
76
77static int ethip_init(void)
78{
79 async_set_client_connection(ethip_client_conn);
80
81 int rc = loc_server_register(NAME);
82 if (rc != EOK) {
83 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
84 return rc;
85 }
86
87 rc = ethip_nic_discovery_start();
88 if (rc != EOK)
89 return rc;
90
91 return EOK;
92}
93
94int ethip_iplink_init(ethip_nic_t *nic)
95{
96 int rc;
97 service_id_t sid;
98 category_id_t iplink_cat;
99 static unsigned link_num = 0;
100 char *svc_name = NULL;
101
102 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_iplink_init()");
103
104 iplink_srv_init(&nic->iplink);
105 nic->iplink.ops = &ethip_iplink_ops;
106 nic->iplink.arg = nic;
107
108 rc = asprintf(&svc_name, "net/eth%u", ++link_num);
109 if (rc < 0) {
110 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
111 goto error;
112 }
113
114 rc = loc_service_register(svc_name, &sid);
115 if (rc != EOK) {
116 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.", svc_name);
117 goto error;
118 }
119
120 nic->iplink_sid = sid;
121
122 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
123 if (rc != EOK) {
124 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
125 goto error;
126 }
127
128 rc = loc_service_add_to_cat(sid, iplink_cat);
129 if (rc != EOK) {
130 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.", svc_name);
131 goto error;
132 }
133
134 return EOK;
135
136error:
137 if (svc_name != NULL)
138 free(svc_name);
139 return rc;
140}
141
142static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
143{
144 ethip_nic_t *nic;
145 service_id_t sid;
146
147 sid = (service_id_t)IPC_GET_ARG1(*icall);
148 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
149 nic = ethip_nic_find_by_iplink_sid(sid);
150 if (nic == NULL) {
151 log_msg(LOG_DEFAULT, LVL_WARN, "Uknown service ID.");
152 return;
153 }
154
155 iplink_conn(iid, icall, &nic->iplink);
156}
157
158static int ethip_open(iplink_srv_t *srv)
159{
160 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_open()");
161 return EOK;
162}
163
164static int ethip_close(iplink_srv_t *srv)
165{
166 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_close()");
167 return EOK;
168}
169
170static int ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
171{
172 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send()");
173
174 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
175 eth_frame_t frame;
176
177 int rc = arp_translate(nic, sdu->src, sdu->dest, frame.dest);
178 if (rc != EOK) {
179 log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IPv4 address 0x%"
180 PRIx32, sdu->dest);
181 return rc;
182 }
183
184 addr48(nic->mac_addr, frame.src);
185 frame.etype_len = ETYPE_IP;
186 frame.data = sdu->data;
187 frame.size = sdu->size;
188
189 void *data;
190 size_t size;
191 rc = eth_pdu_encode(&frame, &data, &size);
192 if (rc != EOK)
193 return rc;
194
195 rc = ethip_nic_send(nic, data, size);
196 free(data);
197
198 return rc;
199}
200
201static int ethip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu)
202{
203 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send6()");
204
205 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
206 eth_frame_t frame;
207
208 addr48(sdu->dest, frame.dest);
209 addr48(nic->mac_addr, frame.src);
210 frame.etype_len = ETYPE_IPV6;
211 frame.data = sdu->data;
212 frame.size = sdu->size;
213
214 void *data;
215 size_t size;
216 int rc = eth_pdu_encode(&frame, &data, &size);
217 if (rc != EOK)
218 return rc;
219
220 rc = ethip_nic_send(nic, data, size);
221 free(data);
222
223 return rc;
224}
225
226int ethip_received(iplink_srv_t *srv, void *data, size_t size)
227{
228 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received(): srv=%p", srv);
229 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
230
231 log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode");
232
233 eth_frame_t frame;
234 int rc = eth_pdu_decode(data, size, &frame);
235 if (rc != EOK) {
236 log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode failed");
237 return rc;
238 }
239
240 iplink_recv_sdu_t sdu;
241
242 switch (frame.etype_len) {
243 case ETYPE_ARP:
244 arp_received(nic, &frame);
245 break;
246 case ETYPE_IP:
247 log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU");
248 sdu.data = frame.data;
249 sdu.size = frame.size;
250 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
251 rc = iplink_ev_recv(&nic->iplink, &sdu, ip_v4);
252 break;
253 case ETYPE_IPV6:
254 log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU IPv6");
255 sdu.data = frame.data;
256 sdu.size = frame.size;
257 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
258 rc = iplink_ev_recv(&nic->iplink, &sdu, ip_v6);
259 break;
260 default:
261 log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
262 frame.etype_len);
263 }
264
265 free(frame.data);
266 return rc;
267}
268
269static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
270{
271 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_get_mtu()");
272 *mtu = 1500;
273 return EOK;
274}
275
276static int ethip_get_mac48(iplink_srv_t *srv, addr48_t *mac)
277{
278 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_get_mac48()");
279
280 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
281 addr48(nic->mac_addr, *mac);
282
283 return EOK;
284}
285
286static int ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
287{
288 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
289
290 return ethip_nic_addr_add(nic, addr);
291}
292
293static int ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
294{
295 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
296
297 return ethip_nic_addr_remove(nic, addr);
298}
299
300int main(int argc, char *argv[])
301{
302 int rc;
303
304 printf(NAME ": HelenOS IP over Ethernet service\n");
305
306 if (log_init(NAME) != EOK) {
307 printf(NAME ": Failed to initialize logging.\n");
308 return 1;
309 }
310
311 rc = ethip_init();
312 if (rc != EOK)
313 return 1;
314
315 printf(NAME ": Accepting connections.\n");
316 task_retval(0);
317 async_manager();
318
319 /* Not reached */
320 return 0;
321}
322
323/** @}
324 */
Note: See TracBrowser for help on using the repository browser.