Changeset 8b5690f in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2011-02-03T05:11:01Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ba38f72c
Parents:
22027b6e (diff), 86d7bfa (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/arp/arp.c

    r22027b6e r8b5690f  
    3636 */
    3737
    38 #include "arp.h"
    39 #include "arp_header.h"
    40 #include "arp_oc.h"
    41 #include "arp_module.h"
    42 
    4338#include <async.h>
    4439#include <malloc.h>
    4540#include <mem.h>
    4641#include <fibril_synch.h>
     42#include <assert.h>
    4743#include <stdio.h>
    4844#include <str.h>
    4945#include <task.h>
    5046#include <adt/measured_strings.h>
    51 #include <ipc/ipc.h>
    5247#include <ipc/services.h>
    5348#include <ipc/net.h>
    5449#include <ipc/arp.h>
    5550#include <ipc/il.h>
     51#include <ipc/nil.h>
    5652#include <byteorder.h>
    5753#include <errno.h>
    58 
    5954#include <net/modules.h>
    6055#include <net/device.h>
    6156#include <net/packet.h>
    62 
    63 #include <nil_interface.h>
     57#include <nil_remote.h>
    6458#include <protocol_map.h>
    6559#include <packet_client.h>
    6660#include <packet_remote.h>
    67 #include <il_interface.h>
    68 #include <il_local.h>
    69 
     61#include <il_remote.h>
     62#include <il_skel.h>
     63#include "arp.h"
    7064
    7165/** ARP module name. */
     
    7367
    7468/** Number of microseconds to wait for an ARP reply. */
    75 #define ARP_TRANS_WAIT  1000000
     69#define ARP_TRANS_WAIT  1000000
     70
     71/** @name ARP operation codes definitions */
     72/*@{*/
     73
     74/** REQUEST operation code. */
     75#define ARPOP_REQUEST  1
     76
     77/** REPLY operation code. */
     78#define ARPOP_REPLY  2
     79
     80/*@}*/
     81
     82/** Type definition of an ARP protocol header.
     83 * @see arp_header
     84 */
     85typedef struct arp_header arp_header_t;
     86
     87/** ARP protocol header. */
     88struct arp_header {
     89        /**
     90         * Hardware type identifier.
     91         * @see hardware.h
     92         */
     93        uint16_t hardware;
     94       
     95        /** Protocol identifier. */
     96        uint16_t protocol;
     97        /** Hardware address length in bytes. */
     98        uint8_t hardware_length;
     99        /** Protocol address length in bytes. */
     100        uint8_t protocol_length;
     101       
     102        /**
     103         * ARP packet type.
     104         * @see arp_oc.h
     105         */
     106        uint16_t operation;
     107} __attribute__ ((packed));
    76108
    77109/** ARP global data. */
     
    88120                trans->hw_addr = NULL;
    89121        }
     122       
    90123        fibril_condvar_broadcast(&trans->cv);
    91124}
     
    94127{
    95128        int count;
    96         arp_trans_t *trans;
    97 
     129       
    98130        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    99                 trans = arp_addr_items_get_index(&addresses->values, count);
     131                arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
     132                    count);
    100133                if (trans)
    101134                        arp_clear_trans(trans);
     
    103136}
    104137
    105 
    106 /** Clears the device specific data.
    107  *
    108  * @param[in] device    The device specific data.
     138/** Clear the device specific data.
     139 *
     140 * @param[in] device Device specific data.
    109141 */
    110142static void arp_clear_device(arp_device_t *device)
    111143{
    112144        int count;
    113         arp_proto_t *proto;
    114 
     145       
    115146        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    116147            count--) {
    117                 proto = arp_protos_get_index(&device->protos, count);
     148                arp_proto_t *proto = arp_protos_get_index(&device->protos,
     149                    count);
     150               
    118151                if (proto) {
    119152                        if (proto->addr)
    120153                                free(proto->addr);
     154                       
    121155                        if (proto->addr_data)
    122156                                free(proto->addr_data);
     157                       
    123158                        arp_clear_addr(&proto->addresses);
    124159                        arp_addr_destroy(&proto->addresses);
    125160                }
    126161        }
     162       
    127163        arp_protos_clear(&device->protos);
    128164}
     
    131167{
    132168        int count;
    133         arp_device_t *device;
    134 
     169       
    135170        fibril_mutex_lock(&arp_globals.lock);
    136171        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    137172            count--) {
    138                 device = arp_cache_get_index(&arp_globals.cache, count);
     173                arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
     174                    count);
     175               
    139176                if (device) {
    140177                        arp_clear_device(device);
    141178                        if (device->addr_data)
    142179                                free(device->addr_data);
     180                       
    143181                        if (device->broadcast_data)
    144182                                free(device->broadcast_data);
    145183                }
    146184        }
     185       
    147186        arp_cache_clear(&arp_globals.cache);
    148187        fibril_mutex_unlock(&arp_globals.lock);
    149         printf("Cache cleaned\n");
     188       
    150189        return EOK;
    151190}
     
    154193    services_t protocol, measured_string_t *address)
    155194{
    156         arp_device_t *device;
    157         arp_proto_t *proto;
    158         arp_trans_t *trans;
    159 
    160195        fibril_mutex_lock(&arp_globals.lock);
    161         device = arp_cache_find(&arp_globals.cache, device_id);
     196       
     197        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    162198        if (!device) {
    163199                fibril_mutex_unlock(&arp_globals.lock);
    164200                return ENOENT;
    165201        }
    166         proto = arp_protos_find(&device->protos, protocol);
     202       
     203        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    167204        if (!proto) {
    168205                fibril_mutex_unlock(&arp_globals.lock);
    169206                return ENOENT;
    170207        }
    171         trans = arp_addr_find(&proto->addresses, address->value, address->length);
     208       
     209        arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
     210            address->length);
    172211        if (trans)
    173212                arp_clear_trans(trans);
     213       
    174214        arp_addr_exclude(&proto->addresses, address->value, address->length);
     215       
    175216        fibril_mutex_unlock(&arp_globals.lock);
    176217        return EOK;
    177218}
    178219
    179 
    180220static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    181221{
    182         arp_device_t *device;
    183 
    184222        fibril_mutex_lock(&arp_globals.lock);
    185         device = arp_cache_find(&arp_globals.cache, device_id);
     223       
     224        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    186225        if (!device) {
    187226                fibril_mutex_unlock(&arp_globals.lock);
    188227                return ENOENT;
    189228        }
     229       
    190230        arp_clear_device(device);
    191         printf("Device %d cleared\n", device_id);
     231       
    192232        fibril_mutex_unlock(&arp_globals.lock);
    193233        return EOK;
    194234}
    195235
    196 /** Creates new protocol specific data.
    197  *
    198  * Allocates and returns the needed memory block as the proto parameter.
    199  *
    200  * @param[out] proto    The allocated protocol specific data.
    201  * @param[in] service   The protocol module service.
    202  * @param[in] address   The actual protocol device address.
    203  * @return              EOK on success.
    204  * @return              ENOMEM if there is not enough memory left.
     236/** Create new protocol specific data.
     237 *
     238 * Allocate and return the needed memory block as the proto parameter.
     239 *
     240 * @param[out] proto   Allocated protocol specific data.
     241 * @param[in]  service Protocol module service.
     242 * @param[in]  address Actual protocol device address.
     243 *
     244 * @return EOK on success.
     245 * @return ENOMEM if there is not enough memory left.
     246 *
    205247 */
    206248static int arp_proto_create(arp_proto_t **proto, services_t service,
    207249    measured_string_t *address)
    208250{
    209         int rc;
    210 
    211251        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    212252        if (!*proto)
     
    217257        (*proto)->addr_data = address->value;
    218258       
    219         rc = arp_addr_initialize(&(*proto)->addresses);
     259        int rc = arp_addr_initialize(&(*proto)->addresses);
    220260        if (rc != EOK) {
    221261                free(*proto);
     
    226266}
    227267
    228 /** Registers the device.
    229  *
    230  * Creates new device entry in the cache or updates the protocol address if the
    231  * device with the device identifier and the driver service exists.
    232  *
    233  * @param[in] device_id The device identifier.
    234  * @param[in] service   The device driver service.
    235  * @param[in] protocol  The protocol service.
    236  * @param[in] address   The actual device protocol address.
    237  * @return              EOK on success.
    238  * @return              EEXIST if another device with the same device identifier
    239  *                      and different driver service exists.
    240  * @return              ENOMEM if there is not enough memory left.
    241  * @return              Other error codes as defined for the
    242  *                      measured_strings_return() function.
    243  */
    244 static int arp_device_message(device_id_t device_id, services_t service,
    245     services_t protocol, measured_string_t *address)
    246 {
    247         arp_device_t *device;
    248         arp_proto_t *proto;
    249         hw_type_t hardware;
    250         int index;
     268/** Process the received ARP packet.
     269 *
     270 * Update the source hardware address if the source entry exists or the packet
     271 * is targeted to my protocol address.
     272 *
     273 * Respond to the ARP request if the packet is the ARP request and is
     274 * targeted to my address.
     275 *
     276 * @param[in]     device_id Source device identifier.
     277 * @param[in,out] packet    Received packet.
     278 *
     279 * @return EOK on success and the packet is no longer needed.
     280 * @return One on success and the packet has been reused.
     281 * @return EINVAL if the packet is too small to carry an ARP
     282 *         packet.
     283 * @return EINVAL if the received address lengths differs from
     284 *         the registered values.
     285 * @return ENOENT if the device is not found in the cache.
     286 * @return ENOENT if the protocol for the device is not found in
     287 *         the cache.
     288 * @return ENOMEM if there is not enough memory left.
     289 *
     290 */
     291static int arp_receive_message(device_id_t device_id, packet_t *packet)
     292{
    251293        int rc;
    252 
    253         fibril_mutex_lock(&arp_globals.lock);
    254 
    255         /* An existing device? */
    256         device = arp_cache_find(&arp_globals.cache, device_id);
    257 
    258         if (device) {
    259                 if (device->service != service) {
    260                         printf("Device %d already exists\n", device->device_id);
    261                         fibril_mutex_unlock(&arp_globals.lock);
    262                         return EEXIST;
    263                 }
    264                 proto = arp_protos_find(&device->protos, protocol);
    265                 if (proto) {
    266                         free(proto->addr);
    267                         free(proto->addr_data);
    268                         proto->addr = address;
    269                         proto->addr_data = address->value;
    270                 } else {
    271                         rc = arp_proto_create(&proto, protocol, address);
    272                         if (rc != EOK) {
    273                                 fibril_mutex_unlock(&arp_globals.lock);
    274                                 return rc;
    275                         }
    276                         index = arp_protos_add(&device->protos, proto->service,
    277                             proto);
    278                         if (index < 0) {
    279                                 fibril_mutex_unlock(&arp_globals.lock);
    280                                 free(proto);
    281                                 return index;
    282                         }
    283                         printf("New protocol added:\n\tdevice id\t= "
    284                             "%d\n\tproto\t= %d", device_id, protocol);
    285                 }
    286         } else {
    287                 hardware = hardware_map(service);
    288                 if (!hardware)
    289                         return ENOENT;
    290                
    291                 /* Create a new device */
    292                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    293                 if (!device) {
    294                         fibril_mutex_unlock(&arp_globals.lock);
    295                         return ENOMEM;
    296                 }
    297                 device->hardware = hardware;
    298                 device->device_id = device_id;
    299                 rc = arp_protos_initialize(&device->protos);
    300                 if (rc != EOK) {
    301                         fibril_mutex_unlock(&arp_globals.lock);
    302                         free(device);
    303                         return rc;
    304                 }
    305                 rc = arp_proto_create(&proto, protocol, address);
    306                 if (rc != EOK) {
    307                         fibril_mutex_unlock(&arp_globals.lock);
    308                         free(device);
    309                         return rc;
    310                 }
    311                 index = arp_protos_add(&device->protos, proto->service, proto);
    312                 if (index < 0) {
    313                         fibril_mutex_unlock(&arp_globals.lock);
    314                         arp_protos_destroy(&device->protos);
    315                         free(device);
    316                         return index;
    317                 }
    318                 device->service = service;
    319                
    320                 /* Bind the new one */
    321                 device->phone = nil_bind_service(device->service,
    322                     (sysarg_t) device->device_id, SERVICE_ARP,
    323                     arp_globals.client_connection);
    324                 if (device->phone < 0) {
    325                         fibril_mutex_unlock(&arp_globals.lock);
    326                         arp_protos_destroy(&device->protos);
    327                         free(device);
    328                         return EREFUSED;
    329                 }
    330                
    331                 /* Get packet dimensions */
    332                 rc = nil_packet_size_req(device->phone, device_id,
    333                     &device->packet_dimension);
    334                 if (rc != EOK) {
    335                         fibril_mutex_unlock(&arp_globals.lock);
    336                         arp_protos_destroy(&device->protos);
    337                         free(device);
    338                         return rc;
    339                 }
    340                
    341                 /* Get hardware address */
    342                 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
    343                     &device->addr_data);
    344                 if (rc != EOK) {
    345                         fibril_mutex_unlock(&arp_globals.lock);
    346                         arp_protos_destroy(&device->protos);
    347                         free(device);
    348                         return rc;
    349                 }
    350                
    351                 /* Get broadcast address */
    352                 rc = nil_get_broadcast_addr_req(device->phone, device_id,
    353                     &device->broadcast_addr, &device->broadcast_data);
    354                 if (rc != EOK) {
    355                         fibril_mutex_unlock(&arp_globals.lock);
    356                         free(device->addr);
    357                         free(device->addr_data);
    358                         arp_protos_destroy(&device->protos);
    359                         free(device);
    360                         return rc;
    361                 }
    362                
    363                 rc = arp_cache_add(&arp_globals.cache, device->device_id,
    364                     device);
    365                 if (rc != EOK) {
    366                         fibril_mutex_unlock(&arp_globals.lock);
    367                         free(device->addr);
    368                         free(device->addr_data);
    369                         free(device->broadcast_addr);
    370                         free(device->broadcast_data);
    371                         arp_protos_destroy(&device->protos);
    372                         free(device);
    373                         return rc;
    374                 }
    375                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
    376                     " proto: %d)\n", NAME, device->device_id, device->hardware,
    377                     device->service, protocol);
    378         }
    379         fibril_mutex_unlock(&arp_globals.lock);
    380        
    381         return EOK;
    382 }
    383 
    384 /** Initializes the ARP module.
    385  *
    386  *  @param[in] client_connection The client connection processing function.
    387  *                      The module skeleton propagates its own one.
    388  *  @return             EOK on success.
    389  *  @return             ENOMEM if there is not enough memory left.
    390  */
    391 int arp_initialize(async_client_conn_t client_connection)
    392 {
    393         int rc;
    394 
    395         fibril_mutex_initialize(&arp_globals.lock);
    396         fibril_mutex_lock(&arp_globals.lock);
    397         arp_globals.client_connection = client_connection;
    398         rc = arp_cache_initialize(&arp_globals.cache);
    399         fibril_mutex_unlock(&arp_globals.lock);
    400        
    401         return rc;
    402 }
    403 
    404 /** Updates the device content length according to the new MTU value.
    405  *
    406  * @param[in] device_id The device identifier.
    407  * @param[in] mtu       The new mtu value.
    408  * @return              ENOENT if device is not found.
    409  * @return              EOK on success.
    410  */
    411 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    412 {
    413         arp_device_t *device;
    414 
    415         fibril_mutex_lock(&arp_globals.lock);
    416         device = arp_cache_find(&arp_globals.cache, device_id);
    417         if (!device) {
    418                 fibril_mutex_unlock(&arp_globals.lock);
    419                 return ENOENT;
    420         }
    421         device->packet_dimension.content = mtu;
    422         fibril_mutex_unlock(&arp_globals.lock);
    423         printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
    424         return EOK;
    425 }
    426 
    427 /** Processes the received ARP packet.
    428  *
    429  * Updates the source hardware address if the source entry exists or the packet
    430  * is targeted to my protocol address.
    431  * Responses to the ARP request if the packet is the ARP request and is
    432  * targeted to my address.
    433  *
    434  * @param[in] device_id The source device identifier.
    435  * @param[in,out] packet The received packet.
    436  * @return              EOK on success and the packet is no longer needed.
    437  * @return              One on success and the packet has been reused.
    438  * @return              EINVAL if the packet is too small to carry an ARP
    439  *                      packet.
    440  * @return              EINVAL if the received address lengths differs from
    441  *                      the registered values.
    442  * @return              ENOENT if the device is not found in the cache.
    443  * @return              ENOENT if the protocol for the device is not found in
    444  *                      the cache.
    445  * @return              ENOMEM if there is not enough memory left.
    446  */
    447 static int arp_receive_message(device_id_t device_id, packet_t *packet)
    448 {
    449         size_t length;
    450         arp_header_t *header;
    451         arp_device_t *device;
    452         arp_proto_t *proto;
    453         arp_trans_t *trans;
    454         uint8_t *src_hw;
    455         uint8_t *src_proto;
    456         uint8_t *des_hw;
    457         uint8_t *des_proto;
    458         int rc;
    459 
    460         length = packet_get_data_length(packet);
     294       
     295        size_t length = packet_get_data_length(packet);
    461296        if (length <= sizeof(arp_header_t))
    462297                return EINVAL;
    463 
    464         device = arp_cache_find(&arp_globals.cache, device_id);
     298       
     299        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    465300        if (!device)
    466301                return ENOENT;
    467 
    468         header = (arp_header_t *) packet_get_data(packet);
     302       
     303        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
    469304        if ((ntohs(header->hardware) != device->hardware) ||
    470305            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    472307                return EINVAL;
    473308        }
    474 
    475         proto = arp_protos_find(&device->protos,
     309       
     310        arp_proto_t *proto = arp_protos_find(&device->protos,
    476311            protocol_unmap(device->service, ntohs(header->protocol)));
    477312        if (!proto)
    478313                return ENOENT;
    479 
    480         src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    481         src_proto = src_hw + header->hardware_length;
    482         des_hw = src_proto + header->protocol_length;
    483         des_proto = des_hw + header->hardware_length;
    484         trans = arp_addr_find(&proto->addresses, src_proto,
     314       
     315        uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     316        uint8_t *src_proto = src_hw + header->hardware_length;
     317        uint8_t *des_hw = src_proto + header->protocol_length;
     318        uint8_t *des_proto = des_hw + header->hardware_length;
     319       
     320        arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
    485321            header->protocol_length);
    486         /* Exists? */
    487         if (trans && trans->hw_addr) {
     322       
     323        if ((trans) && (trans->hw_addr)) {
     324                /* Translation exists */
    488325                if (trans->hw_addr->length != header->hardware_length)
    489326                        return EINVAL;
     327               
    490328                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    491329        }
     330       
    492331        /* Is my protocol address? */
    493332        if (proto->addr->length != header->protocol_length)
     
    495334       
    496335        if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
    497                 /* Not already updated? */
    498336                if (!trans) {
     337                        /* Update the translation */
    499338                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    500339                        if (!trans)
    501340                                return ENOMEM;
     341                       
    502342                        trans->hw_addr = NULL;
    503343                        fibril_condvar_initialize(&trans->cv);
     
    509349                        }
    510350                }
     351               
    511352                if (!trans->hw_addr) {
    512353                        trans->hw_addr = measured_string_create_bulk(src_hw,
     
    518359                        fibril_condvar_broadcast(&trans->cv);
    519360                }
     361               
    520362                if (ntohs(header->operation) == ARPOP_REQUEST) {
    521363                        header->operation = htons(ARPOP_REPLY);
     
    538380                }
    539381        }
    540 
     382       
    541383        return EOK;
    542384}
    543385
    544 
    545 /** Returns the hardware address for the given protocol address.
    546  *
    547  * Sends the ARP request packet if the hardware address is not found in the
    548  * cache.
    549  *
    550  * @param[in] device_id The device identifier.
    551  * @param[in] protocol  The protocol service.
    552  * @param[in] target    The target protocol address.
    553  * @param[out] translation Where the hardware address of the target is stored.
    554  * @return              EOK on success.
    555  * @return              EAGAIN if the caller should try again.
    556  * @return              Other error codes in case of error.
    557  */
    558 static int
    559 arp_translate_message(device_id_t device_id, services_t protocol,
    560     measured_string_t *target, measured_string_t **translation)
    561 {
    562         arp_device_t *device;
    563         arp_proto_t *proto;
    564         arp_trans_t *trans;
    565         size_t length;
     386/** Update the device content length according to the new MTU value.
     387 *
     388 * @param[in] device_id Device identifier.
     389 * @param[in] mtu       New MTU value.
     390 *
     391 * @return ENOENT if device is not found.
     392 * @return EOK on success.
     393 *
     394 */
     395static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     396{
     397        fibril_mutex_lock(&arp_globals.lock);
     398       
     399        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     400        if (!device) {
     401                fibril_mutex_unlock(&arp_globals.lock);
     402                return ENOENT;
     403        }
     404       
     405        device->packet_dimension.content = mtu;
     406       
     407        fibril_mutex_unlock(&arp_globals.lock);
     408       
     409        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     410       
     411        return EOK;
     412}
     413
     414/** Process IPC messages from the registered device driver modules
     415 *
     416 * @param[in]     iid   Message identifier.
     417 * @param[in,out] icall Message parameters.
     418 *
     419 */
     420static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     421{
    566422        packet_t *packet;
    567         arp_header_t *header;
    568         bool retry = false;
    569423        int rc;
    570 
    571 restart:
    572         if (!target || !translation)
    573                 return EBADMEM;
    574 
    575         device = arp_cache_find(&arp_globals.cache, device_id);
    576         if (!device)
    577                 return ENOENT;
    578 
    579         proto = arp_protos_find(&device->protos, protocol);
    580         if (!proto || (proto->addr->length != target->length))
    581                 return ENOENT;
    582 
    583         trans = arp_addr_find(&proto->addresses, target->value, target->length);
    584         if (trans) {
    585                 if (trans->hw_addr) {
    586                         *translation = trans->hw_addr;
    587                         return EOK;
    588                 }
    589                 if (retry)
    590                         return EAGAIN;
    591                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    592                     ARP_TRANS_WAIT);
    593                 if (rc == ETIMEOUT)
     424       
     425        while (true) {
     426                switch (IPC_GET_IMETHOD(*icall)) {
     427                case NET_IL_DEVICE_STATE:
     428                        /* Do nothing - keep the cache */
     429                        async_answer_0(iid, (sysarg_t) EOK);
     430                        break;
     431               
     432                case NET_IL_RECEIVED:
     433                        rc = packet_translate_remote(arp_globals.net_phone, &packet,
     434                            IPC_GET_PACKET(*icall));
     435                        if (rc == EOK) {
     436                                fibril_mutex_lock(&arp_globals.lock);
     437                                do {
     438                                        packet_t *next = pq_detach(packet);
     439                                        rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
     440                                        if (rc != 1) {
     441                                                pq_release_remote(arp_globals.net_phone,
     442                                                    packet_get_id(packet));
     443                                        }
     444                                       
     445                                        packet = next;
     446                                } while (packet);
     447                                fibril_mutex_unlock(&arp_globals.lock);
     448                        }
     449                        async_answer_0(iid, (sysarg_t) rc);
     450                        break;
     451               
     452                case NET_IL_MTU_CHANGED:
     453                        rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
     454                            IPC_GET_MTU(*icall));
     455                        async_answer_0(iid, (sysarg_t) rc);
     456                        break;
     457               
     458                default:
     459                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     460                }
     461               
     462                iid = async_get_call(icall);
     463        }
     464}
     465
     466/** Register the device.
     467 *
     468 * Create new device entry in the cache or update the protocol address if the
     469 * device with the device identifier and the driver service exists.
     470 *
     471 * @param[in] device_id Device identifier.
     472 * @param[in] service   Device driver service.
     473 * @param[in] protocol  Protocol service.
     474 * @param[in] address   Actual device protocol address.
     475 *
     476 * @return EOK on success.
     477 * @return EEXIST if another device with the same device identifier
     478 *         and different driver service exists.
     479 * @return ENOMEM if there is not enough memory left.
     480 * @return Other error codes as defined for the
     481 *         measured_strings_return() function.
     482 *
     483 */
     484static int arp_device_message(device_id_t device_id, services_t service,
     485    services_t protocol, measured_string_t *address)
     486{
     487        int index;
     488        int rc;
     489       
     490        fibril_mutex_lock(&arp_globals.lock);
     491       
     492        /* An existing device? */
     493        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     494        if (device) {
     495                if (device->service != service) {
     496                        printf("%s: Device %d already exists\n", NAME,
     497                            device->device_id);
     498                        fibril_mutex_unlock(&arp_globals.lock);
     499                        return EEXIST;
     500                }
     501               
     502                arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     503                if (proto) {
     504                        free(proto->addr);
     505                        free(proto->addr_data);
     506                        proto->addr = address;
     507                        proto->addr_data = address->value;
     508                } else {
     509                        rc = arp_proto_create(&proto, protocol, address);
     510                        if (rc != EOK) {
     511                                fibril_mutex_unlock(&arp_globals.lock);
     512                                return rc;
     513                        }
     514                       
     515                        index = arp_protos_add(&device->protos, proto->service,
     516                            proto);
     517                        if (index < 0) {
     518                                fibril_mutex_unlock(&arp_globals.lock);
     519                                free(proto);
     520                                return index;
     521                        }
     522                       
     523                        printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
     524                            device_id, protocol);
     525                }
     526        } else {
     527                hw_type_t hardware = hardware_map(service);
     528                if (!hardware)
    594529                        return ENOENT;
    595                 retry = true;
    596                 goto restart;
    597         }
    598         if (retry)
    599                 return EAGAIN;
    600 
     530               
     531                /* Create new device */
     532                device = (arp_device_t *) malloc(sizeof(arp_device_t));
     533                if (!device) {
     534                        fibril_mutex_unlock(&arp_globals.lock);
     535                        return ENOMEM;
     536                }
     537               
     538                device->hardware = hardware;
     539                device->device_id = device_id;
     540                rc = arp_protos_initialize(&device->protos);
     541                if (rc != EOK) {
     542                        fibril_mutex_unlock(&arp_globals.lock);
     543                        free(device);
     544                        return rc;
     545                }
     546               
     547                arp_proto_t *proto;
     548                rc = arp_proto_create(&proto, protocol, address);
     549                if (rc != EOK) {
     550                        fibril_mutex_unlock(&arp_globals.lock);
     551                        free(device);
     552                        return rc;
     553                }
     554               
     555                index = arp_protos_add(&device->protos, proto->service, proto);
     556                if (index < 0) {
     557                        fibril_mutex_unlock(&arp_globals.lock);
     558                        arp_protos_destroy(&device->protos);
     559                        free(device);
     560                        return index;
     561                }
     562               
     563                device->service = service;
     564               
     565                /* Bind */
     566                device->phone = nil_bind_service(device->service,
     567                    (sysarg_t) device->device_id, SERVICE_ARP,
     568                    arp_receiver);
     569                if (device->phone < 0) {
     570                        fibril_mutex_unlock(&arp_globals.lock);
     571                        arp_protos_destroy(&device->protos);
     572                        free(device);
     573                        return EREFUSED;
     574                }
     575               
     576                /* Get packet dimensions */
     577                rc = nil_packet_size_req(device->phone, device_id,
     578                    &device->packet_dimension);
     579                if (rc != EOK) {
     580                        fibril_mutex_unlock(&arp_globals.lock);
     581                        arp_protos_destroy(&device->protos);
     582                        free(device);
     583                        return rc;
     584                }
     585               
     586                /* Get hardware address */
     587                rc = nil_get_addr_req(device->phone, device_id, &device->addr,
     588                    &device->addr_data);
     589                if (rc != EOK) {
     590                        fibril_mutex_unlock(&arp_globals.lock);
     591                        arp_protos_destroy(&device->protos);
     592                        free(device);
     593                        return rc;
     594                }
     595               
     596                /* Get broadcast address */
     597                rc = nil_get_broadcast_addr_req(device->phone, device_id,
     598                    &device->broadcast_addr, &device->broadcast_data);
     599                if (rc != EOK) {
     600                        fibril_mutex_unlock(&arp_globals.lock);
     601                        free(device->addr);
     602                        free(device->addr_data);
     603                        arp_protos_destroy(&device->protos);
     604                        free(device);
     605                        return rc;
     606                }
     607               
     608                rc = arp_cache_add(&arp_globals.cache, device->device_id,
     609                    device);
     610                if (rc != EOK) {
     611                        fibril_mutex_unlock(&arp_globals.lock);
     612                        free(device->addr);
     613                        free(device->addr_data);
     614                        free(device->broadcast_addr);
     615                        free(device->broadcast_data);
     616                        arp_protos_destroy(&device->protos);
     617                        free(device);
     618                        return rc;
     619                }
     620                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     621                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     622                    device->service, protocol);
     623        }
     624       
     625        fibril_mutex_unlock(&arp_globals.lock);
     626        return EOK;
     627}
     628
     629int il_initialize(int net_phone)
     630{
     631        fibril_mutex_initialize(&arp_globals.lock);
     632       
     633        fibril_mutex_lock(&arp_globals.lock);
     634        arp_globals.net_phone = net_phone;
     635        int rc = arp_cache_initialize(&arp_globals.cache);
     636        fibril_mutex_unlock(&arp_globals.lock);
     637       
     638        return rc;
     639}
     640
     641static int arp_send_request(device_id_t device_id, services_t protocol,
     642    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
     643{
    601644        /* ARP packet content size = header + (address + translation) * 2 */
    602         length = 8 + 2 * (proto->addr->length + device->addr->length);
     645        size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
    603646        if (length > device->packet_dimension.content)
    604647                return ELIMIT;
    605 
    606         packet = packet_get_4_remote(arp_globals.net_phone,
     648       
     649        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
    607650            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    608651            length, device->packet_dimension.suffix);
    609652        if (!packet)
    610653                return ENOMEM;
    611 
    612         header = (arp_header_t *) packet_suffix(packet, length);
     654       
     655        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
    613656        if (!header) {
    614657                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    615658                return ENOMEM;
    616659        }
    617 
     660       
    618661        header->hardware = htons(device->hardware);
    619662        header->hardware_length = (uint8_t) device->addr->length;
     
    621664        header->protocol_length = (uint8_t) proto->addr->length;
    622665        header->operation = htons(ARPOP_REQUEST);
     666       
    623667        length = sizeof(arp_header_t);
     668       
    624669        memcpy(((uint8_t *) header) + length, device->addr->value,
    625670            device->addr->length);
     
    631676        length += device->addr->length;
    632677        memcpy(((uint8_t *) header) + length, target->value, target->length);
    633 
    634         rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     678       
     679        int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    635680            (uint8_t *) device->broadcast_addr->value, device->addr->length);
    636681        if (rc != EOK) {
     
    638683                return rc;
    639684        }
    640 
     685       
    641686        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    642 
     687        return EOK;
     688}
     689
     690/** Return the hardware address for the given protocol address.
     691 *
     692 * Send the ARP request packet if the hardware address is not found in the
     693 * cache.
     694 *
     695 * @param[in]  device_id   Device identifier.
     696 * @param[in]  protocol    Protocol service.
     697 * @param[in]  target      Target protocol address.
     698 * @param[out] translation Where the hardware address of the target is stored.
     699 *
     700 * @return EOK on success.
     701 * @return EAGAIN if the caller should try again.
     702 * @return Other error codes in case of error.
     703 *
     704 */
     705static int arp_translate_message(device_id_t device_id, services_t protocol,
     706    measured_string_t *target, measured_string_t **translation)
     707{
     708        bool retry = false;
     709        int rc;
     710
     711        assert(fibril_mutex_is_locked(&arp_globals.lock));
     712       
     713restart:
     714        if ((!target) || (!translation))
     715                return EBADMEM;
     716       
     717        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     718        if (!device)
     719                return ENOENT;
     720       
     721        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     722        if ((!proto) || (proto->addr->length != target->length))
     723                return ENOENT;
     724       
     725        arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
     726            target->length);
     727        if (trans) {
     728                if (trans->hw_addr) {
     729                        /* The translation is in place. */
     730                        *translation = trans->hw_addr;
     731                        return EOK;
     732                }
     733               
     734                if (retry) {
     735                        /*
     736                         * We may get here as a result of being signalled for
     737                         * some reason while waiting for the translation (e.g.
     738                         * translation becoming available, record being removed
     739                         * from the table) and then losing the race for
     740                         * the arp_globals.lock with someone else who modified
     741                         * the table.
     742                         *
     743                         * Remove the incomplete record so that it is possible
     744                         * to make new ARP requests.
     745                         */
     746                        arp_clear_trans(trans);
     747                        arp_addr_exclude(&proto->addresses, target->value,
     748                            target->length);
     749                        return EAGAIN;
     750                }
     751               
     752                /*
     753                 * We are a random passer-by who merely joins an already waiting
     754                 * fibril in waiting for the translation.
     755                 */
     756                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     757                    ARP_TRANS_WAIT);
     758                if (rc == ETIMEOUT)
     759                        return ENOENT;
     760               
     761                /*
     762                 * Need to recheck because we did not hold the lock while
     763                 * sleeping on the condition variable.
     764                 */
     765                retry = true;
     766                goto restart;
     767        }
     768       
     769        if (retry)
     770                return EAGAIN;
     771
     772        /*
     773         * We are under the protection of arp_globals.lock, so we can afford to
     774         * first send the ARP request and then insert an incomplete ARP record.
     775         * The incomplete record is used to tell any other potential waiter
     776         * that this fibril has already sent the request and that it is waiting
     777         * for the answer. Lastly, any fibril which sees the incomplete request
     778         * can perform a timed wait on its condition variable to wait for the
     779         * ARP reply to arrive.
     780         */
     781
     782        rc = arp_send_request(device_id, protocol, target, device, proto);
     783        if (rc != EOK)
     784                return rc;
     785       
    643786        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    644787        if (!trans)
    645788                return ENOMEM;
     789       
    646790        trans->hw_addr = NULL;
    647791        fibril_condvar_initialize(&trans->cv);
     792       
    648793        rc = arp_addr_add(&proto->addresses, target->value, target->length,
    649794            trans);
     
    655800        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    656801            ARP_TRANS_WAIT);
    657         if (rc == ETIMEOUT)
     802        if (rc == ETIMEOUT) {
     803                /*
     804                 * Remove the incomplete record so that it is possible to make
     805                 * new ARP requests.
     806                 */
     807                arp_clear_trans(trans);
     808                arp_addr_exclude(&proto->addresses, target->value,
     809                    target->length);
    658810                return ENOENT;
     811        }
     812       
     813        /*
     814         * We need to recheck that the translation has indeed become available,
     815         * because we dropped the arp_globals.lock while sleeping on the
     816         * condition variable and someone else might have e.g. removed the
     817         * translation before we managed to lock arp_globals.lock again.
     818         */
     819
    659820        retry = true;
    660821        goto restart;
    661822}
    662823
    663 
    664 /** Processes the ARP message.
    665  *
    666  * @param[in] callid    The message identifier.
    667  * @param[in] call      The message parameters.
    668  * @param[out] answer   The message answer parameters.
    669  * @param[out] answer_count The last parameter for the actual answer in the
    670  *                      answer parameter.
    671  * @return              EOK on success.
    672  * @return              ENOTSUP if the message is not known.
     824/** Process the ARP message.
     825 *
     826 * @param[in]  callid Message identifier.
     827 * @param[in]  call   Message parameters.
     828 * @param[out] answer Answer.
     829 * @param[out] count  Number of arguments of the answer.
     830 *
     831 * @return EOK on success.
     832 * @return ENOTSUP if the message is not known.
    673833 *
    674834 * @see arp_interface.h
    675835 * @see IS_NET_ARP_MESSAGE()
    676  */
    677 int
    678 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    679     ipc_call_t *answer, int *answer_count)
     836 *
     837 */
     838int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     839    size_t *count)
    680840{
    681841        measured_string_t *address;
    682842        measured_string_t *translation;
    683843        uint8_t *data;
    684         packet_t *packet;
    685         packet_t *next;
    686844        int rc;
    687845       
    688         *answer_count = 0;
     846        *count = 0;
    689847        switch (IPC_GET_IMETHOD(*call)) {
    690848        case IPC_M_PHONE_HUNGUP:
     
    696854                        return rc;
    697855               
    698                 rc = arp_device_message(IPC_GET_DEVICE(call),
    699                     IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
     856                rc = arp_device_message(IPC_GET_DEVICE(*call),
     857                    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
    700858                if (rc != EOK) {
    701859                        free(address);
    702860                        free(data);
    703861                }
     862               
    704863                return rc;
    705864       
     
    710869               
    711870                fibril_mutex_lock(&arp_globals.lock);
    712                 rc = arp_translate_message(IPC_GET_DEVICE(call),
    713                     IPC_GET_SERVICE(call), address, &translation);
     871                rc = arp_translate_message(IPC_GET_DEVICE(*call),
     872                    IPC_GET_SERVICE(*call), address, &translation);
    714873                free(address);
    715874                free(data);
     875               
    716876                if (rc != EOK) {
    717877                        fibril_mutex_unlock(&arp_globals.lock);
    718878                        return rc;
    719879                }
     880               
    720881                if (!translation) {
    721882                        fibril_mutex_unlock(&arp_globals.lock);
    722883                        return ENOENT;
    723884                }
     885               
    724886                rc = measured_strings_reply(translation, 1);
    725887                fibril_mutex_unlock(&arp_globals.lock);
    726888                return rc;
    727 
     889       
    728890        case NET_ARP_CLEAR_DEVICE:
    729                 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    730 
     891                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
     892       
    731893        case NET_ARP_CLEAR_ADDRESS:
    732894                rc = measured_strings_receive(&address, &data, 1);
     
    734896                        return rc;
    735897               
    736                 arp_clear_address_req(0, IPC_GET_DEVICE(call),
    737                     IPC_GET_SERVICE(call), address);
     898                arp_clear_address_req(0, IPC_GET_DEVICE(*call),
     899                    IPC_GET_SERVICE(*call), address);
    738900                free(address);
    739901                free(data);
     
    742904        case NET_ARP_CLEAN_CACHE:
    743905                return arp_clean_cache_req(0);
    744        
    745         case NET_IL_DEVICE_STATE:
    746                 /* Do nothing - keep the cache */
    747                 return EOK;
    748        
    749         case NET_IL_RECEIVED:
    750                
    751                 rc = packet_translate_remote(arp_globals.net_phone, &packet,
    752                     IPC_GET_PACKET(call));
    753                 if (rc != EOK)
    754                         return rc;
    755                
    756                 fibril_mutex_lock(&arp_globals.lock);
    757                 do {
    758                         next = pq_detach(packet);
    759                         rc = arp_receive_message(IPC_GET_DEVICE(call), packet);
    760                         if (rc != 1) {
    761                                 pq_release_remote(arp_globals.net_phone,
    762                                     packet_get_id(packet));
    763                         }
    764                         packet = next;
    765                 } while (packet);
    766                 fibril_mutex_unlock(&arp_globals.lock);
    767                
    768                 return EOK;
    769        
    770         case NET_IL_MTU_CHANGED:
    771                 return arp_mtu_changed_message(IPC_GET_DEVICE(call),
    772                     IPC_GET_MTU(call));
    773906        }
    774907       
     
    776909}
    777910
    778 /** Default thread for new connections.
    779  *
    780  * @param[in] iid       The initial message identifier.
    781  * @param[in] icall     The initial message call structure.
    782  */
    783 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    784 {
    785         /*
    786          * Accept the connection
    787          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    788          */
    789         ipc_answer_0(iid, EOK);
    790        
    791         while (true) {
    792                 ipc_call_t answer;
    793                 int answer_count;
    794                
    795                 /* Clear the answer structure */
    796                 refresh_answer(&answer, &answer_count);
    797                
    798                 /* Fetch the next message */
    799                 ipc_call_t call;
    800                 ipc_callid_t callid = async_get_call(&call);
    801                
    802                 /* Process the message */
    803                 int res = il_module_message_standalone(callid, &call, &answer,
    804                     &answer_count);
    805                
    806                 /*
    807                  * End if told to either by the message or the processing
    808                  * result.
    809                  */
    810                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    811                     (res == EHANGUP))
    812                         return;
    813                
    814                 /* Answer the message */
    815                 answer_call(callid, res, &answer, answer_count);
    816         }
    817 }
    818 
    819 /** Starts the module.
    820  *
    821  * @return              EOK on success.
    822  * @return              Other error codes as defined for each specific module
    823  *                      start function.
    824  */
    825911int main(int argc, char *argv[])
    826912{
    827         int rc;
    828        
    829913        /* Start the module */
    830         rc = il_module_start_standalone(il_client_connection);
    831         return rc;
     914        return il_module_start(SERVICE_ARP);
    832915}
    833916
    834917/** @}
    835918 */
    836 
Note: See TracChangeset for help on using the changeset viewer.