source: mainline/uspace/srv/net/nil/nildummy/nildummy.c@ c7315dd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c7315dd was 21580dd, checked in by Lukas Mejdrech <lukas@…>, 16 years ago

Merged with network branch svn://svn.helenos.org/HelenOS/branches/network revision 4759; ipc_share_* and ipc_data_* changed to async_*; client connection in module.c returns on IPC_M_PHONE_HUNGUP; * Qemu scripts renamed to net-qe.*; (the dp8390 does not respond)

  • Property mode set to 100644
File size: 12.7 KB
Line 
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
29/** @addtogroup nildummy
30 * @{
31 */
32
33/** @file
34 * Dummy network interface layer module implementation.
35 * @see nildummy.h
36 */
37
38#include <async.h>
39#include <malloc.h>
40#include <mem.h>
41#include <stdio.h>
42#include <string.h>
43
44#include <ipc/ipc.h>
45#include <ipc/services.h>
46
47#include "../../err.h"
48#include "../../messages.h"
49#include "../../modules.h"
50
51#include "../../include/device.h"
52#include "../../include/netif_interface.h"
53#include "../../include/nil_interface.h"
54#include "../../include/il_interface.h"
55
56#include "../../structures/measured_strings.h"
57#include "../../structures/packet/packet.h"
58
59#include "../nil_module.h"
60
61#include "nildummy.h"
62
63/** Default maximum transmission unit.
64 */
65#define NET_DEFAULT_MTU 1500
66
67/** Network interface layer module global data.
68 */
69nildummy_globals_t nildummy_globals;
70
71/** @name Message processing functions
72 */
73/*@{*/
74
75/** Processes IPC messages from the registered device driver modules in an infinite loop.
76 * @param[in] iid The message identifier.
77 * @param[in,out] icall The message parameters.
78 */
79void nildummy_receiver( ipc_callid_t iid, ipc_call_t * icall );
80
81/** Registers new device or updates the MTU of an existing one.
82 * Determines the device local hardware address.
83 * @param[in] device_id The new device identifier.
84 * @param[in] service The device driver service.
85 * @param[in] mtu The device maximum transmission unit.
86 * @returns EOK on success.
87 * @returns EEXIST if the device with the different service exists.
88 * @returns ENOMEM if there is not enough memory left.
89 * @returns Other error codes as defined for the netif_bind_service() function.
90 * @returns Other error codes as defined for the netif_get_addr_req() function.
91 */
92int nildummy_device_message( device_id_t device_id, services_t service, size_t mtu );
93
94/** Returns the device packet dimensions for sending.
95 * @param[in] device_id The device identifier.
96 * @param[out] addr_len The minimum reserved address length.
97 * @param[out] prefix The minimum reserved prefix size.
98 * @param[out] content The maximum content size.
99 * @param[out] suffix The minimum reserved suffix size.
100 * @returns EOK on success.
101 * @returns EBADMEM if either one of the parameters is NULL.
102 * @returns ENOENT if there is no such device.
103 */
104int nildummy_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix );
105
106/** Registers receiving module service.
107 * Passes received packets for this service.
108 * @param[in] service The module service.
109 * @param[in] phone The service phone.
110 * @returns EOK on success.
111 * @returns ENOENT if the service is not known.
112 * @returns ENOMEM if there is not enough memory left.
113 */
114int nildummy_register_message( services_t service, int phone );
115
116/** Sends the packet queue.
117 * @param[in] device_id The device identifier.
118 * @param[in] packet The packet queue.
119 * @param[in] sender The sending module service.
120 * @returns EOK on success.
121 * @returns ENOENT if there no such device.
122 * @returns EINVAL if the service parameter is not known.
123 */
124int nildummy_send_message( device_id_t device_id, packet_t packet, services_t sender );
125
126/** Returns the device hardware address.
127 * @param[in] device_id The device identifier.
128 * @param[out] address The device hardware address.
129 * @returns EOK on success.
130 * @returns EBADMEM if the address parameter is NULL.
131 * @returns ENOENT if there no such device.
132 */
133int nildummy_addr_message( device_id_t device_id, measured_string_ref * address );
134
135/*@}*/
136
137DEVICE_MAP_IMPLEMENT( nildummy_devices, nildummy_device_t )
138
139int nil_device_state_msg( int nil_phone, device_id_t device_id, int state ){
140 fibril_rwlock_read_lock( & nildummy_globals.protos_lock );
141 if( nildummy_globals.proto.phone ) il_device_state_msg( nildummy_globals.proto.phone, device_id, state, nildummy_globals.proto.service );
142 fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
143 return EOK;
144}
145
146int nil_initialize( int net_phone ){
147 ERROR_DECLARE;
148
149 fibril_rwlock_initialize( & nildummy_globals.devices_lock );
150 fibril_rwlock_initialize( & nildummy_globals.protos_lock );
151 fibril_rwlock_write_lock( & nildummy_globals.devices_lock );
152 fibril_rwlock_write_lock( & nildummy_globals.protos_lock );
153 nildummy_globals.net_phone = net_phone;
154 nildummy_globals.proto.phone = 0;
155 ERROR_PROPAGATE( nildummy_devices_initialize( & nildummy_globals.devices ));
156 fibril_rwlock_write_unlock( & nildummy_globals.protos_lock );
157 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
158 return EOK;
159}
160
161int nildummy_device_message( device_id_t device_id, services_t service, size_t mtu ){
162 ERROR_DECLARE;
163
164 nildummy_device_ref device;
165 int index;
166
167 fibril_rwlock_write_lock( & nildummy_globals.devices_lock );
168 // an existing device?
169 device = nildummy_devices_find( & nildummy_globals.devices, device_id );
170 if( device ){
171 if( device->service != service ){
172 printf( "Device %d already exists\n", device->device_id );
173 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
174 return EEXIST;
175 }else{
176 // update mtu
177 if( mtu > 0 ){
178 device->mtu = mtu;
179 }else{
180 device->mtu = NET_DEFAULT_MTU;
181 }
182 printf( "Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu );
183 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
184 // notify the upper layer module
185 fibril_rwlock_read_lock( & nildummy_globals.protos_lock );
186 if( nildummy_globals.proto.phone ){
187 il_mtu_changed_msg( nildummy_globals.proto.phone, device->device_id, device->mtu, nildummy_globals.proto.service );
188 }
189 fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
190 return EOK;
191 }
192 }else{
193 // create a new device
194 device = ( nildummy_device_ref ) malloc( sizeof( nildummy_device_t ));
195 if( ! device ) return ENOMEM;
196 device->device_id = device_id;
197 device->service = service;
198 if( mtu > 0 ){
199 device->mtu = mtu;
200 }else{
201 device->mtu = NET_DEFAULT_MTU;
202 }
203 // bind the device driver
204 device->phone = netif_bind_service( device->service, device->device_id, SERVICE_ETHERNET, nildummy_receiver );
205 if( device->phone < 0 ){
206 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
207 free( device );
208 return device->phone;
209 }
210 // get hardware address
211 if( ERROR_OCCURRED( netif_get_addr_req( device->phone, device->device_id, & device->addr, & device->addr_data ))){
212 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
213 free( device );
214 return ERROR_CODE;
215 }
216 // add to the cache
217 index = nildummy_devices_add( & nildummy_globals.devices, device->device_id, device );
218 if( index < 0 ){
219 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
220 free( device->addr );
221 free( device->addr_data );
222 free( device );
223 return index;
224 }
225 printf( "New device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n", device->device_id, device->service, device->mtu );
226 }
227 fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
228 return EOK;
229}
230
231int nildummy_addr_message( device_id_t device_id, measured_string_ref * address ){
232 nildummy_device_ref device;
233
234 if( ! address ) return EBADMEM;
235 fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
236 device = nildummy_devices_find( & nildummy_globals.devices, device_id );
237 if( ! device ){
238 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
239 return ENOENT;
240 }
241 * address = device->addr;
242 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
243 return ( * address ) ? EOK : ENOENT;
244}
245
246int nildummy_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
247 nildummy_device_ref device;
248
249 if( !( addr_len && prefix && content && suffix )) return EBADMEM;
250 fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
251 device = nildummy_devices_find( & nildummy_globals.devices, device_id );
252 if( ! device ){
253 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
254 return ENOENT;
255 }
256 * content = device->mtu;
257 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
258 * addr_len = 0;
259 * prefix = 0;
260 * suffix = 0;
261 return EOK;
262}
263
264int nil_received_msg( int nil_phone, device_id_t device_id, packet_t packet, services_t target ){
265 packet_t next;
266
267 fibril_rwlock_read_lock( & nildummy_globals.protos_lock );
268 if( nildummy_globals.proto.phone ){
269 do{
270 next = pq_detach( packet );
271 il_received_msg( nildummy_globals.proto.phone, device_id, packet, nildummy_globals.proto.service );
272 packet = next;
273 }while( packet );
274 }
275 fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
276 return EOK;
277}
278
279int nildummy_register_message( services_t service, int phone ){
280 fibril_rwlock_write_lock( & nildummy_globals.protos_lock );
281 nildummy_globals.proto.service = service;
282 nildummy_globals.proto.phone = phone;
283 printf( "New protocol registered:\n\tservice\t= %d\n\tphone\t= %d\n", nildummy_globals.proto.service, nildummy_globals.proto.phone );
284 fibril_rwlock_write_unlock( & nildummy_globals.protos_lock );
285 return EOK;
286}
287
288int nildummy_send_message( device_id_t device_id, packet_t packet, services_t sender ){
289 nildummy_device_ref device;
290
291 fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
292 device = nildummy_devices_find( & nildummy_globals.devices, device_id );
293 if( ! device ){
294 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
295 return ENOENT;
296 }
297 // send packet queue
298 if( packet ){
299 netif_send_msg( device->phone, device_id, packet, SERVICE_NILDUMMY );
300 }
301 fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
302 return EOK;
303}
304
305int nil_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
306 ERROR_DECLARE;
307
308 measured_string_ref address;
309 packet_t packet;
310
311// printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_NIL_FIRST );
312 * answer_count = 0;
313 switch( IPC_GET_METHOD( * call )){
314 case IPC_M_PHONE_HUNGUP:
315 return EOK;
316 case NET_NIL_DEVICE:
317 return nildummy_device_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), IPC_GET_MTU( call ));
318 case NET_NIL_SEND:
319 ERROR_PROPAGATE( packet_translate( nildummy_globals.net_phone, & packet, IPC_GET_PACKET( call )));
320 return nildummy_send_message( IPC_GET_DEVICE( call ), packet, IPC_GET_SERVICE( call ));
321 case NET_NIL_PACKET_SPACE:
322 ERROR_PROPAGATE( nildummy_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
323 * answer_count = 4;
324 return EOK;
325 case NET_NIL_ADDR:
326 ERROR_PROPAGATE( nildummy_addr_message( IPC_GET_DEVICE( call ), & address ));
327 return measured_strings_reply( address, 1 );
328 case IPC_M_CONNECT_TO_ME:
329 return nildummy_register_message( NIL_GET_PROTO( call ), IPC_GET_PHONE( call ));
330 }
331 return ENOTSUP;
332}
333
334void nildummy_receiver( ipc_callid_t iid, ipc_call_t * icall ){
335 ERROR_DECLARE;
336
337 packet_t packet;
338
339 while( true ){
340// printf( "message %d - %d\n", IPC_GET_METHOD( * icall ), NET_NIL_FIRST );
341 switch( IPC_GET_METHOD( * icall )){
342 case NET_NIL_DEVICE_STATE:
343 ERROR_CODE = nil_device_state_msg( 0, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall ));
344 ipc_answer_0( iid, ( ipcarg_t ) ERROR_CODE );
345 break;
346 case NET_NIL_RECEIVED:
347 if( ! ERROR_OCCURRED( packet_translate( nildummy_globals.net_phone, & packet, IPC_GET_PACKET( icall )))){
348 ERROR_CODE = nil_received_msg( 0, IPC_GET_DEVICE( icall ), packet, 0 );
349 }
350 ipc_answer_0( iid, ( ipcarg_t ) ERROR_CODE );
351 break;
352 default:
353 ipc_answer_0( iid, ( ipcarg_t ) ENOTSUP );
354 }
355 iid = async_get_call( icall );
356 }
357}
358
359/** @}
360 */
Note: See TracBrowser for help on using the repository browser.