Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/nil/nildummy/nildummy.c

    r46d4d9f r514ee46  
    4141#include <stdio.h>
    4242#include <str.h>
     43#include <err.h>
    4344#include <ipc/ipc.h>
    4445#include <ipc/net.h>
     
    5758#include "nildummy.h"
    5859
    59 /** The module name. */
     60/** The module name.
     61 *
     62 */
    6063#define NAME  "nildummy"
    6164
    62 /** Default maximum transmission unit. */
     65/** Default maximum transmission unit.
     66 *
     67 */
    6368#define NET_DEFAULT_MTU  1500
    6469
    65 /** Network interface layer module global data. */
     70/** Network interface layer module global data.
     71 *
     72 */
    6673nildummy_globals_t nildummy_globals;
    6774
     
    7178{
    7279        fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
     80       
    7381        if (nildummy_globals.proto.phone)
    74                 il_device_state_msg(nildummy_globals.proto.phone, device_id,
    75                     state, nildummy_globals.proto.service);
     82                il_device_state_msg(nildummy_globals.proto.phone, device_id, state,
     83                    nildummy_globals.proto.service);
     84       
    7685        fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
    7786       
     
    8190int nil_initialize(int net_phone)
    8291{
    83         int rc;
     92        ERROR_DECLARE;
    8493       
    8594        fibril_rwlock_initialize(&nildummy_globals.devices_lock);
     
    9099        nildummy_globals.net_phone = net_phone;
    91100        nildummy_globals.proto.phone = 0;
    92         rc = nildummy_devices_initialize(&nildummy_globals.devices);
     101        ERROR_PROPAGATE(nildummy_devices_initialize(&nildummy_globals.devices));
    93102       
    94103        fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
    95104        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    96105       
    97         return rc;
    98 }
    99 
    100 /** Process IPC messages from the registered device driver modules in an
    101  * infinite loop.
    102  *
    103  * @param[in] iid       The message identifier.
    104  * @param[in,out]       icall The message parameters.
    105  */
    106 static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
    107 {
    108         packet_t *packet;
    109         int rc;
    110 
    111         while (true) {
    112                 switch (IPC_GET_METHOD(*icall)) {
    113                 case NET_NIL_DEVICE_STATE:
    114                         rc = nil_device_state_msg_local(0,
    115                             IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
    116                         ipc_answer_0(iid, (ipcarg_t) rc);
    117                         break;
    118                
    119                 case NET_NIL_RECEIVED:
    120                         rc = packet_translate_remote(nildummy_globals.net_phone,
    121                             &packet, IPC_GET_PACKET(icall));
    122                         if (rc == EOK) {
    123                                 rc = nil_received_msg_local(0,
    124                                     IPC_GET_DEVICE(icall), packet, 0);
    125                         }
    126                         ipc_answer_0(iid, (ipcarg_t) rc);
    127                         break;
    128                
    129                 default:
    130                         ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
    131                 }
    132                
     106        return EOK;
     107}
     108
     109/** Process IPC messages from the registered device driver modules in an infinite loop.
     110 *
     111 * @param[in]     iid   The message identifier.
     112 * @param[in,out] icall The message parameters.
     113 *
     114 */
     115static void nildummy_receiver(ipc_callid_t iid, ipc_call_t * icall){
     116        ERROR_DECLARE;
     117
     118        packet_t packet;
     119
     120        while(true){
     121                switch(IPC_GET_METHOD(*icall)){
     122                        case NET_NIL_DEVICE_STATE:
     123                                ERROR_CODE = nil_device_state_msg_local(0, IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
     124                                ipc_answer_0(iid, (ipcarg_t) ERROR_CODE);
     125                                break;
     126                        case NET_NIL_RECEIVED:
     127                                if(! ERROR_OCCURRED(packet_translate_remote(nildummy_globals.net_phone, &packet, IPC_GET_PACKET(icall)))){
     128                                        ERROR_CODE = nil_received_msg_local(0, IPC_GET_DEVICE(icall), packet, 0);
     129                                }
     130                                ipc_answer_0(iid, (ipcarg_t) ERROR_CODE);
     131                                break;
     132                        default:
     133                                ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
     134                }
    133135                iid = async_get_call(icall);
    134136        }
     
    139141 * Determine the device local hardware address.
    140142 *
    141  * @param[in] device_id The new device identifier.
    142  * @param[in] service   The device driver service.
    143  * @param[in] mtu       The device maximum transmission unit.
    144  * @return              EOK on success.
    145  * @return              EEXIST if the device with the different service exists.
    146  * @return              ENOMEM if there is not enough memory left.
    147  * @return              Other error codes as defined for the
    148  *                      netif_bind_service() function.
    149  * @return              Other error codes as defined for the
    150  *                      netif_get_addr_req() function.
     143 * @param[in] device_id The new device identifier.
     144 * @param[in] service   The device driver service.
     145 * @param[in] mtu       The device maximum transmission unit.
     146 *
     147 * @returns EOK on success.
     148 * @returns EEXIST if the device with the different service exists.
     149 * @returns ENOMEM if there is not enough memory left.
     150 * @returns Other error codes as defined for the netif_bind_service() function.
     151 * @returns Other error codes as defined for the netif_get_addr_req() function.
     152 *
    151153 */
    152154static int nildummy_device_message(device_id_t device_id, services_t service,
    153155    size_t mtu)
    154156{
    155         nildummy_device_t *device;
     157        ERROR_DECLARE;
     158
     159        nildummy_device_ref device;
    156160        int index;
    157         int rc;
    158161
    159162        fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
    160 
    161         /* An existing device? */
     163        // an existing device?
    162164        device = nildummy_devices_find(&nildummy_globals.devices, device_id);
    163         if (device) {
    164                 if (device->service != service) {
     165        if(device){
     166                if(device->service != service){
    165167                        printf("Device %d already exists\n", device->device_id);
    166                         fibril_rwlock_write_unlock(
    167                             &nildummy_globals.devices_lock);
     168                        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    168169                        return EEXIST;
    169                 }
    170                
    171                 /* Update MTU */
    172                 if (mtu > 0)
     170                }else{
     171                        // update mtu
     172                        if(mtu > 0){
     173                                device->mtu = mtu;
     174                        }else{
     175                                device->mtu = NET_DEFAULT_MTU;
     176                        }
     177                        printf("Device %d already exists:\tMTU\t= %d\n", device->device_id, device->mtu);
     178                        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
     179                        // notify the upper layer module
     180                        fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
     181                        if(nildummy_globals.proto.phone){
     182                                il_mtu_changed_msg(nildummy_globals.proto.phone, device->device_id, device->mtu, nildummy_globals.proto.service);
     183                        }
     184                        fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
     185                        return EOK;
     186                }
     187        }else{
     188                // create a new device
     189                device = (nildummy_device_ref) malloc(sizeof(nildummy_device_t));
     190                if(! device){
     191                        return ENOMEM;
     192                }
     193                device->device_id = device_id;
     194                device->service = service;
     195                if(mtu > 0){
    173196                        device->mtu = mtu;
    174                 else
     197                }else{
    175198                        device->mtu = NET_DEFAULT_MTU;
    176                
    177                 printf("Device %d already exists:\tMTU\t= %d\n",
    178                     device->device_id, device->mtu);
    179                 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    180                
    181                 /* Notify the upper layer module */
    182                 fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
    183                 if (nildummy_globals.proto.phone) {
    184                         il_mtu_changed_msg(nildummy_globals.proto.phone,
    185                             device->device_id, device->mtu,
    186                             nildummy_globals.proto.service);
    187                 }
    188                 fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
    189                
    190                 return EOK;
    191         }
    192        
    193         /* Create a new device */
    194         device = (nildummy_device_t *) malloc(sizeof(nildummy_device_t));
    195         if (!device)
    196                 return ENOMEM;
    197        
    198         device->device_id = device_id;
    199         device->service = service;
    200         if (mtu > 0)
    201                 device->mtu = mtu;
    202         else
    203                 device->mtu = NET_DEFAULT_MTU;
    204 
    205         /* Bind the device driver */
    206         device->phone = netif_bind_service(device->service, device->device_id,
    207             SERVICE_ETHERNET, nildummy_receiver);
    208         if (device->phone < 0) {
    209                 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    210                 free(device);
    211                 return device->phone;
    212         }
    213        
    214         /* Get hardware address */
    215         rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
    216             &device->addr_data);
    217         if (rc != EOK) {
    218                 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    219                 free(device);
    220                 return rc;
    221         }
    222        
    223         /* Add to the cache */
    224         index = nildummy_devices_add(&nildummy_globals.devices,
    225             device->device_id, device);
    226         if (index < 0) {
    227                 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    228                 free(device->addr);
    229                 free(device->addr_data);
    230                 free(device);
    231                 return index;
    232         }
    233        
    234         printf("%s: Device registered (id: %d, service: %d, mtu: %d)\n",
    235             NAME, device->device_id, device->service, device->mtu);
     199                }
     200                // bind the device driver
     201                device->phone = netif_bind_service(device->service, device->device_id, SERVICE_ETHERNET, nildummy_receiver);
     202                if(device->phone < 0){
     203                        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
     204                        free(device);
     205                        return device->phone;
     206                }
     207                // get hardware address
     208                if(ERROR_OCCURRED(netif_get_addr_req(device->phone, device->device_id, &device->addr, &device->addr_data))){
     209                        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
     210                        free(device);
     211                        return ERROR_CODE;
     212                }
     213                // add to the cache
     214                index = nildummy_devices_add(&nildummy_globals.devices, device->device_id, device);
     215                if(index < 0){
     216                        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
     217                        free(device->addr);
     218                        free(device->addr_data);
     219                        free(device);
     220                        return index;
     221                }
     222                printf("%s: Device registered (id: %d, service: %d, mtu: %d)\n",
     223                    NAME, device->device_id, device->service, device->mtu);
     224        }
    236225        fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
    237226        return EOK;
     
    240229/** Return the device hardware address.
    241230 *
    242  * @param[in] device_id The device identifier.
    243  * @param[out] address  The device hardware address.
    244  * @return               EOK on success.
    245  * @return              EBADMEM if the address parameter is NULL.
    246  * @return              ENOENT if there no such device.
     231 * @param[in]  device_id The device identifier.
     232 * @param[out] address   The device hardware address.
     233 *
     234 * @return EOK on success.
     235 * @return EBADMEM if the address parameter is NULL.
     236 * @return ENOENT if there no such device.
    247237 *
    248238 */
    249239static int nildummy_addr_message(device_id_t device_id,
    250     measured_string_t **address)
    251 {
    252         nildummy_device_t *device;
    253 
    254         if (!address)
     240    measured_string_ref *address)
     241{
     242        nildummy_device_ref device;
     243
     244        if(! address){
    255245                return EBADMEM;
    256        
     246        }
    257247        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    258248        device = nildummy_devices_find(&nildummy_globals.devices, device_id);
    259         if (!device) {
     249        if(! device){
    260250                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    261251                return ENOENT;
     
    263253        *address = device->addr;
    264254        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    265        
    266255        return (*address) ? EOK : ENOENT;
    267256}
     
    269258/** Return the device packet dimensions for sending.
    270259 *
    271  * @param[in] device_id The device identifier.
    272  * @param[out] addr_len The minimum reserved address length.
    273  * @param[out] prefix   The minimum reserved prefix size.
    274  * @param[out] content  The maximum content size.
    275  * @param[out] suffix   The minimum reserved suffix size.
    276  * @return              EOK on success.
    277  * @return              EBADMEM if either one of the parameters is NULL.
    278  * @return              ENOENT if there is no such device.
    279  *
    280  */
    281 static int nildummy_packet_space_message(device_id_t device_id, size_t *addr_len,
    282     size_t *prefix, size_t *content, size_t *suffix)
    283 {
    284         nildummy_device_t *device;
    285 
    286         if (!addr_len || !prefix || !content || !suffix)
     260 * @param[in]  device_id The device identifier.
     261 * @param[out] addr_len  The minimum reserved address length.
     262 * @param[out] prefix    The minimum reserved prefix size.
     263 * @param[out] content   The maximum content size.
     264 * @param[out] suffix    The minimum reserved suffix size.
     265 *
     266 * @return EOK on success.
     267 * @return EBADMEM if either one of the parameters is NULL.
     268 * @return ENOENT if there is no such device.
     269 *
     270 */
     271static int nildummy_packet_space_message(device_id_t device_id,
     272    size_t *addr_len, size_t *prefix, size_t *content, size_t *suffix)
     273{
     274        nildummy_device_ref device;
     275
     276        if(!(addr_len && prefix && content && suffix)){
    287277                return EBADMEM;
    288        
     278        }
    289279        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    290280        device = nildummy_devices_find(&nildummy_globals.devices, device_id);
    291         if (!device) {
     281        if(! device){
    292282                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    293283                return ENOENT;
    294284        }
    295 
    296285        *content = device->mtu;
    297286        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    298        
    299287        *addr_len = 0;
    300288        *prefix = 0;
     
    303291}
    304292
    305 int nil_received_msg_local(int nil_phone, device_id_t device_id,
    306     packet_t *packet, services_t target)
    307 {
    308         packet_t *next;
     293int nil_received_msg_local(int nil_phone, device_id_t device_id, packet_t packet, services_t target){
     294        packet_t next;
    309295
    310296        fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
    311         if (nildummy_globals.proto.phone) {
    312                 do {
     297        if(nildummy_globals.proto.phone){
     298                do{
    313299                        next = pq_detach(packet);
    314                         il_received_msg(nildummy_globals.proto.phone, device_id,
    315                             packet, nildummy_globals.proto.service);
     300                        il_received_msg(nildummy_globals.proto.phone, device_id, packet, nildummy_globals.proto.service);
    316301                        packet = next;
    317                 } while(packet);
     302                }while(packet);
    318303        }
    319304        fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
    320        
    321305        return EOK;
    322306}
     
    326310 * Pass received packets for this service.
    327311 *
    328  * @param[in] service   The module service.
    329  * @param[in] phone     The service phone.
    330  * @return              EOK on success.
    331  * @return              ENOENT if the service is not known.
    332  * @return              ENOMEM if there is not enough memory left.
     312 * @param[in] service The module service.
     313 * @param[in] phone   The service phone.
     314 *
     315 * @return EOK on success.
     316 * @return ENOENT if the service is not known.
     317 * @return ENOMEM if there is not enough memory left.
     318 *
    333319 */
    334320static int nildummy_register_message(services_t service, int phone)
     
    347333/** Send the packet queue.
    348334 *
    349  * @param[in] device_id The device identifier.
    350  * @param[in] packet    The packet queue.
    351  * @param[in] sender    The sending module service.
    352  * @return              EOK on success.
    353  * @return              ENOENT if there no such device.
    354  * @return              EINVAL if the service parameter is not known.
    355  */
    356 static int nildummy_send_message(device_id_t device_id, packet_t *packet,
     335 * @param[in] device_id The device identifier.
     336 * @param[in] packet    The packet queue.
     337 * @param[in] sender    The sending module service.
     338 *
     339 * @return EOK on success.
     340 * @return ENOENT if there no such device.
     341 * @return EINVAL if the service parameter is not known.
     342 *
     343 */
     344static int nildummy_send_message(device_id_t device_id, packet_t packet,
    357345    services_t sender)
    358346{
    359         nildummy_device_t *device;
     347        nildummy_device_ref device;
    360348
    361349        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    362350        device = nildummy_devices_find(&nildummy_globals.devices, device_id);
    363         if (!device) {
     351        if(! device){
    364352                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    365353                return ENOENT;
    366354        }
    367 
    368         /* Send packet queue */
    369         if (packet)
    370                 netif_send_msg(device->phone, device_id, packet,
    371                     SERVICE_NILDUMMY);
     355        // send packet queue
     356        if(packet){
     357                netif_send_msg(device->phone, device_id, packet, SERVICE_NILDUMMY);
     358        }
    372359        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    373360        return EOK;
    374361}
    375362
    376 int nil_message_standalone(const char *name, ipc_callid_t callid,
    377     ipc_call_t *call, ipc_call_t *answer, int *answer_count)
    378 {
    379         measured_string_t *address;
    380         packet_t *packet;
     363int nil_message_standalone(const char *name, ipc_callid_t callid, ipc_call_t *call,
     364    ipc_call_t *answer, int *answer_count)
     365{
     366        ERROR_DECLARE;
     367       
     368        measured_string_ref address;
     369        packet_t packet;
    381370        size_t addrlen;
    382371        size_t prefix;
    383372        size_t suffix;
    384373        size_t content;
    385         int rc;
    386374       
    387375        *answer_count = 0;
    388376        switch (IPC_GET_METHOD(*call)) {
    389         case IPC_M_PHONE_HUNGUP:
    390                 return EOK;
    391        
    392         case NET_NIL_DEVICE:
    393                 return nildummy_device_message(IPC_GET_DEVICE(call),
    394                     IPC_GET_SERVICE(call), IPC_GET_MTU(call));
    395        
    396         case NET_NIL_SEND:
    397                 rc = packet_translate_remote(nildummy_globals.net_phone,
    398                     &packet, IPC_GET_PACKET(call));
    399                 if (rc != EOK)
    400                         return rc;
    401                 return nildummy_send_message(IPC_GET_DEVICE(call), packet,
    402                     IPC_GET_SERVICE(call));
    403        
    404         case NET_NIL_PACKET_SPACE:
    405                 rc = nildummy_packet_space_message(IPC_GET_DEVICE(call),
    406                     &addrlen, &prefix, &content, &suffix);
    407                 if (rc != EOK)
    408                         return rc;
    409                 IPC_SET_ADDR(answer, addrlen);
    410                 IPC_SET_PREFIX(answer, prefix);
    411                 IPC_SET_CONTENT(answer, content);
    412                 IPC_SET_SUFFIX(answer, suffix);
    413                 *answer_count = 4;
    414                 return EOK;
    415        
    416         case NET_NIL_ADDR:
    417                 rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
    418                 if (rc != EOK)
    419                         return rc;
    420                 return measured_strings_reply(address, 1);
    421        
    422         case NET_NIL_BROADCAST_ADDR:
    423                 rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
    424                 if (rc != EOK)
    425                         return rc;
    426                 return measured_strings_reply(address, 1);
    427        
    428         case IPC_M_CONNECT_TO_ME:
    429                 return nildummy_register_message(NIL_GET_PROTO(call),
    430                     IPC_GET_PHONE(call));
     377                case IPC_M_PHONE_HUNGUP:
     378                        return EOK;
     379                case NET_NIL_DEVICE:
     380                        return nildummy_device_message(IPC_GET_DEVICE(call),
     381                            IPC_GET_SERVICE(call), IPC_GET_MTU(call));
     382                case NET_NIL_SEND:
     383                        ERROR_PROPAGATE(packet_translate_remote(nildummy_globals.net_phone,
     384                            &packet, IPC_GET_PACKET(call)));
     385                        return nildummy_send_message(IPC_GET_DEVICE(call), packet,
     386                            IPC_GET_SERVICE(call));
     387                case NET_NIL_PACKET_SPACE:
     388                        ERROR_PROPAGATE(nildummy_packet_space_message(IPC_GET_DEVICE(call),
     389                            &addrlen, &prefix, &content, &suffix));
     390                        IPC_SET_ADDR(answer, addrlen);
     391                        IPC_SET_PREFIX(answer, prefix);
     392                        IPC_SET_CONTENT(answer, content);
     393                        IPC_SET_SUFFIX(answer, suffix);
     394                        *answer_count = 4;
     395                        return EOK;
     396                case NET_NIL_ADDR:
     397                        ERROR_PROPAGATE(nildummy_addr_message(IPC_GET_DEVICE(call),
     398                            &address));
     399                        return measured_strings_reply(address, 1);
     400                case NET_NIL_BROADCAST_ADDR:
     401                        ERROR_PROPAGATE(nildummy_addr_message(IPC_GET_DEVICE(call),
     402                            &address));
     403                        return measured_strings_reply(address, 1);
     404                case IPC_M_CONNECT_TO_ME:
     405                        return nildummy_register_message(NIL_GET_PROTO(call),
     406                            IPC_GET_PHONE(call));
    431407        }
    432408       
     
    436412/** Default thread for new connections.
    437413 *
    438  * @param[in] iid       The initial message identifier.
    439  * @param[in] icall     The initial message call structure.
     414 * @param[in] iid   The initial message identifier.
     415 * @param[in] icall The initial message call structure.
     416 *
    440417 */
    441418static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     
    447424        ipc_answer_0(iid, EOK);
    448425       
    449         while (true) {
     426        while(true) {
    450427                ipc_call_t answer;
    451428                int answer_count;
     
    459436               
    460437                /* Process the message */
    461                 int res = nil_module_message_standalone(NAME, callid, &call,
    462                     &answer, &answer_count);
     438                int res = nil_module_message_standalone(NAME, callid, &call, &answer,
     439                    &answer_count);
    463440               
    464                 /*
    465                  * End if told to either by the message or the processing
    466                  * result.
    467                  */
    468                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    469                     (res == EHANGUP))
     441                /* End if said to either by the message or the processing result */
     442                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    470443                        return;
    471444               
     
    477450int main(int argc, char *argv[])
    478451{
    479         int rc;
     452        ERROR_DECLARE;
    480453       
    481454        /* Start the module */
    482         rc = nil_module_start_standalone(nil_client_connection);
    483         return rc;
     455        if (ERROR_OCCURRED(nil_module_start_standalone(nil_client_connection)))
     456                return ERROR_CODE;
     457       
     458        return EOK;
    484459}
    485460
Note: See TracChangeset for help on using the changeset viewer.