source: mainline/uspace/lib/net/netif/netif_skel.c@ 79ae36dd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 79ae36dd was 79ae36dd, checked in by Martin Decky <martin@…>, 14 years ago

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[14f1db0]1/*
2 * Copyright (c) 2009 Lukas Mejdrech
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
[774e6d1a]29/** @addtogroup libnet
[14f1db0]30 * @{
31 */
32
33/** @file
34 * Network interface module skeleton implementation.
[fe8dfa6]35 * @see netif_skel.h
[14f1db0]36 */
37
38#include <async.h>
39#include <mem.h>
40#include <fibril_synch.h>
41#include <stdio.h>
42#include <ipc/services.h>
[995689d1]43#include <ipc/netif.h>
[0ab68f6]44#include <errno.h>
[14f1db0]45
[514ee46]46#include <generic.h>
[c7a8442]47#include <net/modules.h>
[c69d327]48#include <net/packet.h>
[0a866eeb]49#include <packet_client.h>
[14f1db0]50#include <packet_remote.h>
51#include <adt/measured_strings.h>
[e526f08]52#include <net/device.h>
[774e6d1a]53#include <netif_skel.h>
[fe8dfa6]54#include <nil_remote.h>
[14f1db0]55
[79ae36dd]56// FIXME: remove this header
57#include <kernel/ipc/ipc_methods.h>
58
[14f1db0]59DEVICE_MAP_IMPLEMENT(netif_device_map, netif_device_t);
60
[42a9f27]61/** Network interface global data. */
[14f1db0]62netif_globals_t netif_globals;
63
64/** Probe the existence of the device.
65 *
[774e6d1a]66 * @param[in] netif_phone Network interface phone.
67 * @param[in] device_id Device identifier.
68 * @param[in] irq Device interrupt number.
69 * @param[in] io Device input/output address.
70 *
71 * @return EOK on success.
72 * @return Other error codes as defined for the
73 * netif_probe_message().
74 *
[14f1db0]75 */
[774e6d1a]76static int netif_probe_req_local(int netif_phone, device_id_t device_id,
77 int irq, void *io)
[14f1db0]78{
79 fibril_rwlock_write_lock(&netif_globals.lock);
80 int result = netif_probe_message(device_id, irq, io);
81 fibril_rwlock_write_unlock(&netif_globals.lock);
82
83 return result;
84}
85
86/** Send the packet queue.
87 *
[774e6d1a]88 * @param[in] netif_phone Network interface phone.
89 * @param[in] device_id Device identifier.
90 * @param[in] packet Packet queue.
91 * @param[in] sender Sending module service.
92 *
93 * @return EOK on success.
94 * @return Other error codes as defined for the generic_send_msg()
95 * function.
96 *
[14f1db0]97 */
[774e6d1a]98static int netif_send_msg_local(int netif_phone, device_id_t device_id,
[46d4d9f]99 packet_t *packet, services_t sender)
[14f1db0]100{
101 fibril_rwlock_write_lock(&netif_globals.lock);
102 int result = netif_send_message(device_id, packet, sender);
103 fibril_rwlock_write_unlock(&netif_globals.lock);
104
105 return result;
106}
107
108/** Start the device.
109 *
[774e6d1a]110 * @param[in] netif_phone Network interface phone.
111 * @param[in] device_id Device identifier.
112 *
113 * @return EOK on success.
114 * @return Other error codes as defined for the find_device()
115 * function.
116 * @return Other error codes as defined for the
117 * netif_start_message() function.
118 *
[14f1db0]119 */
[774e6d1a]120static int netif_start_req_local(int netif_phone, device_id_t device_id)
[14f1db0]121{
122 fibril_rwlock_write_lock(&netif_globals.lock);
123
124 netif_device_t *device;
[774e6d1a]125 int rc = find_device(device_id, &device);
[0ab68f6]126 if (rc != EOK) {
[14f1db0]127 fibril_rwlock_write_unlock(&netif_globals.lock);
[0ab68f6]128 return rc;
[14f1db0]129 }
130
131 int result = netif_start_message(device);
132 if (result > NETIF_NULL) {
133 int phone = device->nil_phone;
134 nil_device_state_msg(phone, device_id, result);
[4fc2b3b]135 fibril_rwlock_write_unlock(&netif_globals.lock);
[14f1db0]136 return EOK;
137 }
138
139 fibril_rwlock_write_unlock(&netif_globals.lock);
140
141 return result;
142}
143
144/** Stop the device.
145 *
[774e6d1a]146 * @param[in] netif_phone Network interface phone.
147 * @param[in] device_id Device identifier.
148 *
149 * @return EOK on success.
150 * @return Other error codes as defined for the find_device()
151 * function.
152 * @return Other error codes as defined for the
153 * netif_stop_message() function.
154 *
[14f1db0]155 */
[774e6d1a]156static int netif_stop_req_local(int netif_phone, device_id_t device_id)
[14f1db0]157{
158 fibril_rwlock_write_lock(&netif_globals.lock);
159
160 netif_device_t *device;
[774e6d1a]161 int rc = find_device(device_id, &device);
[0ab68f6]162 if (rc != EOK) {
[14f1db0]163 fibril_rwlock_write_unlock(&netif_globals.lock);
[0ab68f6]164 return rc;
[14f1db0]165 }
166
167 int result = netif_stop_message(device);
168 if (result > NETIF_NULL) {
169 int phone = device->nil_phone;
170 nil_device_state_msg(phone, device_id, result);
[4fc2b3b]171 fibril_rwlock_write_unlock(&netif_globals.lock);
[14f1db0]172 return EOK;
173 }
174
175 fibril_rwlock_write_unlock(&netif_globals.lock);
176
177 return result;
178}
179
[774e6d1a]180/** Find the device specific data.
181 *
182 * @param[in] device_id Device identifier.
183 * @param[out] device Device specific data.
[14f1db0]184 *
185 * @return EOK on success.
[774e6d1a]186 * @return ENOENT if device is not found.
187 * @return EPERM if the device is not initialized.
[14f1db0]188 *
189 */
190int find_device(device_id_t device_id, netif_device_t **device)
191{
192 if (!device)
193 return EBADMEM;
194
195 *device = netif_device_map_find(&netif_globals.device_map, device_id);
196 if (*device == NULL)
197 return ENOENT;
198
199 if ((*device)->state == NETIF_NULL)
200 return EPERM;
201
202 return EOK;
203}
204
205/** Clear the usage statistics.
206 *
[774e6d1a]207 * @param[in] stats The usage statistics.
208 *
[14f1db0]209 */
[f772bc55]210void null_device_stats(device_stats_t *stats)
[14f1db0]211{
212 bzero(stats, sizeof(device_stats_t));
213}
214
215/** Release the given packet.
216 *
217 * Prepared for future optimization.
218 *
[774e6d1a]219 * @param[in] packet_id The packet identifier.
220 *
[14f1db0]221 */
222void netif_pq_release(packet_id_t packet_id)
223{
224 pq_release_remote(netif_globals.net_phone, packet_id);
225}
226
227/** Allocate new packet to handle the given content size.
228 *
[774e6d1a]229 * @param[in] content Minimum content size.
230 *
231 * @return The allocated packet.
232 * @return NULL on error.
[14f1db0]233 *
234 */
[46d4d9f]235packet_t *netif_packet_get_1(size_t content)
[14f1db0]236{
237 return packet_get_1_remote(netif_globals.net_phone, content);
238}
239
[774e6d1a]240/** Register the device notification receiver,
241 *
242 * Register a network interface layer module as the device
243 * notification receiver.
244 *
245 * @param[in] device_id Device identifier.
246 * @param[in] phone Network interface layer module phone.
247 *
248 * @return EOK on success.
249 * @return ENOENT if there is no such device.
250 * @return ELIMIT if there is another module registered.
251 *
[14f1db0]252 */
[774e6d1a]253static int register_message(device_id_t device_id, int phone)
[14f1db0]254{
255 netif_device_t *device;
[774e6d1a]256 int rc = find_device(device_id, &device);
[0ab68f6]257 if (rc != EOK)
258 return rc;
259
[774e6d1a]260 if (device->nil_phone >= 0)
[14f1db0]261 return ELIMIT;
262
263 device->nil_phone = phone;
264 return EOK;
265}
266
267/** Process the netif module messages.
268 *
[774e6d1a]269 * @param[in] callid Mmessage identifier.
270 * @param[in] call Message.
271 * @param[out] answer Answer.
272 * @param[out] count Number of arguments of the answer.
273 *
274 * @return EOK on success.
275 * @return ENOTSUP if the message is unknown.
276 * @return Other error codes as defined for each specific module
277 * message function.
[14f1db0]278 *
279 * @see IS_NET_NETIF_MESSAGE()
280 *
281 */
[774e6d1a]282static int netif_module_message(ipc_callid_t callid, ipc_call_t *call,
283 ipc_call_t *answer, size_t *count)
[14f1db0]284{
285 size_t length;
286 device_stats_t stats;
[46d4d9f]287 packet_t *packet;
[14f1db0]288 measured_string_t address;
[0ab68f6]289 int rc;
[14f1db0]290
[774e6d1a]291 *count = 0;
292
[79ae36dd]293 if (!IPC_GET_IMETHOD(*call))
[42a9f27]294 return EOK;
295
[79ae36dd]296 switch (IPC_GET_IMETHOD(*call)) {
[42a9f27]297 case NET_NETIF_PROBE:
[774e6d1a]298 return netif_probe_req_local(0, IPC_GET_DEVICE(*call),
299 NETIF_GET_IRQ(*call), NETIF_GET_IO(*call));
300
[42a9f27]301 case IPC_M_CONNECT_TO_ME:
302 fibril_rwlock_write_lock(&netif_globals.lock);
[774e6d1a]303
304 rc = register_message(IPC_GET_DEVICE(*call), IPC_GET_PHONE(*call));
305
[42a9f27]306 fibril_rwlock_write_unlock(&netif_globals.lock);
[0ab68f6]307 return rc;
[774e6d1a]308
[42a9f27]309 case NET_NETIF_SEND:
[0ab68f6]310 rc = packet_translate_remote(netif_globals.net_phone, &packet,
[774e6d1a]311 IPC_GET_PACKET(*call));
[0ab68f6]312 if (rc != EOK)
313 return rc;
314
[774e6d1a]315 return netif_send_msg_local(0, IPC_GET_DEVICE(*call), packet,
316 IPC_GET_SENDER(*call));
317
[42a9f27]318 case NET_NETIF_START:
[774e6d1a]319 return netif_start_req_local(0, IPC_GET_DEVICE(*call));
320
[42a9f27]321 case NET_NETIF_STATS:
322 fibril_rwlock_read_lock(&netif_globals.lock);
[774e6d1a]323
[0ab68f6]324 rc = async_data_read_receive(&callid, &length);
325 if (rc != EOK) {
[14f1db0]326 fibril_rwlock_read_unlock(&netif_globals.lock);
[0ab68f6]327 return rc;
[42a9f27]328 }
[774e6d1a]329
[42a9f27]330 if (length < sizeof(device_stats_t)) {
[14f1db0]331 fibril_rwlock_read_unlock(&netif_globals.lock);
[42a9f27]332 return EOVERFLOW;
333 }
[774e6d1a]334
335 rc = netif_get_device_stats(IPC_GET_DEVICE(*call), &stats);
[0ab68f6]336 if (rc == EOK) {
337 rc = async_data_read_finalize(callid, &stats,
[42a9f27]338 sizeof(device_stats_t));
339 }
[774e6d1a]340
[42a9f27]341 fibril_rwlock_read_unlock(&netif_globals.lock);
[0ab68f6]342 return rc;
[774e6d1a]343
[42a9f27]344 case NET_NETIF_STOP:
[774e6d1a]345 return netif_stop_req_local(0, IPC_GET_DEVICE(*call));
346
[42a9f27]347 case NET_NETIF_GET_ADDR:
348 fibril_rwlock_read_lock(&netif_globals.lock);
[774e6d1a]349
350 rc = netif_get_addr_message(IPC_GET_DEVICE(*call), &address);
[0ab68f6]351 if (rc == EOK)
352 rc = measured_strings_reply(&address, 1);
[774e6d1a]353
[42a9f27]354 fibril_rwlock_read_unlock(&netif_globals.lock);
[0ab68f6]355 return rc;
[14f1db0]356 }
357
[774e6d1a]358 return netif_specific_message(callid, call, answer, count);
359}
360
361/** Default fibril for new module connections.
362 *
363 * @param[in] iid Initial message identifier.
364 * @param[in] icall Initial message call structure.
365 *
366 */
367static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
368{
369 /*
370 * Accept the connection by answering
371 * the initial IPC_M_CONNECT_ME_TO call.
372 */
[ffa2c8ef]373 async_answer_0(iid, EOK);
[774e6d1a]374
375 while (true) {
376 ipc_call_t answer;
377 size_t count;
378
379 /* Clear the answer structure */
380 refresh_answer(&answer, &count);
381
382 /* Fetch the next message */
383 ipc_call_t call;
384 ipc_callid_t callid = async_get_call(&call);
385
386 /* Process the message */
387 int res = netif_module_message(callid, &call, &answer, &count);
388
389 /* End if said to either by the message or the processing result */
[79ae36dd]390 if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
[774e6d1a]391 return;
392
393 /* Answer the message */
394 answer_call(callid, res, &answer, count);
395 }
[14f1db0]396}
397
398/** Start the network interface module.
399 *
[42a9f27]400 * Initialize the client connection serving function, initialize the module,
401 * registers the module service and start the async manager, processing IPC
402 * messages in an infinite loop.
[14f1db0]403 *
[774e6d1a]404 * @return EOK on success.
405 * @return Other error codes as defined for each specific module
406 * message function.
407 *
[14f1db0]408 */
[774e6d1a]409int netif_module_start(void)
[14f1db0]410{
[774e6d1a]411 async_set_client_connection(netif_client_connection);
[14f1db0]412
[774e6d1a]413 netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
414 netif_device_map_initialize(&netif_globals.device_map);
415
416 int rc = pm_init();
[0ab68f6]417 if (rc != EOK)
418 return rc;
[14f1db0]419
[774e6d1a]420 fibril_rwlock_initialize(&netif_globals.lock);
421
422 rc = netif_initialize();
423 if (rc != EOK) {
424 pm_destroy();
425 return rc;
426 }
427
[14f1db0]428 async_manager();
429
430 pm_destroy();
431 return EOK;
432}
433
434/** @}
435 */
Note: See TracBrowser for help on using the repository browser.