Changeset 973ef9fc in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2010-12-25T21:20:28Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
631ee0c
Parents:
1bfd3d3 (diff), 09178b7f (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

    r1bfd3d3 r973ef9fc  
    7272#define NAME  "arp"
    7373
     74/** Number of microseconds to wait for an ARP reply. */
     75#define ARP_TRANS_WAIT  1000000
     76
    7477/** ARP global data. */
    7578arp_globals_t arp_globals;
     
    7780DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    7881INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
     82GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
     83
     84static void arp_clear_trans(arp_trans_t *trans)
     85{
     86        if (trans->hw_addr) {
     87                free(trans->hw_addr);
     88                trans->hw_addr = NULL;
     89        }
     90        fibril_condvar_broadcast(&trans->cv);
     91}
     92
     93static void arp_clear_addr(arp_addr_t *addresses)
     94{
     95        int count;
     96        arp_trans_t *trans;
     97
     98        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
     99                trans = arp_addr_items_get_index(&addresses->values, count);
     100                if (trans)
     101                        arp_clear_trans(trans);
     102        }
     103}
     104
    80105
    81106/** Clears the device specific data.
     
    96121                        if (proto->addr_data)
    97122                                free(proto->addr_data);
     123                        arp_clear_addr(&proto->addresses);
    98124                        arp_addr_destroy(&proto->addresses);
    99125                }
     
    107133        arp_device_t *device;
    108134
    109         fibril_rwlock_write_lock(&arp_globals.lock);
     135        fibril_mutex_lock(&arp_globals.lock);
    110136        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    111137            count--) {
     
    120146        }
    121147        arp_cache_clear(&arp_globals.cache);
    122         fibril_rwlock_write_unlock(&arp_globals.lock);
     148        fibril_mutex_unlock(&arp_globals.lock);
    123149        printf("Cache cleaned\n");
    124150        return EOK;
     
    130156        arp_device_t *device;
    131157        arp_proto_t *proto;
    132 
    133         fibril_rwlock_write_lock(&arp_globals.lock);
     158        arp_trans_t *trans;
     159
     160        fibril_mutex_lock(&arp_globals.lock);
    134161        device = arp_cache_find(&arp_globals.cache, device_id);
    135162        if (!device) {
    136                 fibril_rwlock_write_unlock(&arp_globals.lock);
     163                fibril_mutex_unlock(&arp_globals.lock);
    137164                return ENOENT;
    138165        }
    139166        proto = arp_protos_find(&device->protos, protocol);
    140167        if (!proto) {
    141                 fibril_rwlock_write_unlock(&arp_globals.lock);
     168                fibril_mutex_unlock(&arp_globals.lock);
    142169                return ENOENT;
    143170        }
     171        trans = arp_addr_find(&proto->addresses, address->value, address->length);
     172        if (trans)
     173                arp_clear_trans(trans);
    144174        arp_addr_exclude(&proto->addresses, address->value, address->length);
    145         fibril_rwlock_write_unlock(&arp_globals.lock);
     175        fibril_mutex_unlock(&arp_globals.lock);
    146176        return EOK;
    147177}
     
    152182        arp_device_t *device;
    153183
    154         fibril_rwlock_write_lock(&arp_globals.lock);
     184        fibril_mutex_lock(&arp_globals.lock);
    155185        device = arp_cache_find(&arp_globals.cache, device_id);
    156186        if (!device) {
    157                 fibril_rwlock_write_unlock(&arp_globals.lock);
     187                fibril_mutex_unlock(&arp_globals.lock);
    158188                return ENOENT;
    159189        }
    160190        arp_clear_device(device);
    161191        printf("Device %d cleared\n", device_id);
    162         fibril_rwlock_write_unlock(&arp_globals.lock);
     192        fibril_mutex_unlock(&arp_globals.lock);
    163193        return EOK;
    164194}
     
    221251        int rc;
    222252
    223         fibril_rwlock_write_lock(&arp_globals.lock);
     253        fibril_mutex_lock(&arp_globals.lock);
    224254
    225255        /* An existing device? */
     
    229259                if (device->service != service) {
    230260                        printf("Device %d already exists\n", device->device_id);
    231                         fibril_rwlock_write_unlock(&arp_globals.lock);
     261                        fibril_mutex_unlock(&arp_globals.lock);
    232262                        return EEXIST;
    233263                }
     
    241271                        rc = arp_proto_create(&proto, protocol, address);
    242272                        if (rc != EOK) {
    243                                 fibril_rwlock_write_unlock(&arp_globals.lock);
     273                                fibril_mutex_unlock(&arp_globals.lock);
    244274                                return rc;
    245275                        }
     
    247277                            proto);
    248278                        if (index < 0) {
    249                                 fibril_rwlock_write_unlock(&arp_globals.lock);
     279                                fibril_mutex_unlock(&arp_globals.lock);
    250280                                free(proto);
    251281                                return index;
     
    262292                device = (arp_device_t *) malloc(sizeof(arp_device_t));
    263293                if (!device) {
    264                         fibril_rwlock_write_unlock(&arp_globals.lock);
     294                        fibril_mutex_unlock(&arp_globals.lock);
    265295                        return ENOMEM;
    266296                }
     
    269299                rc = arp_protos_initialize(&device->protos);
    270300                if (rc != EOK) {
    271                         fibril_rwlock_write_unlock(&arp_globals.lock);
     301                        fibril_mutex_unlock(&arp_globals.lock);
    272302                        free(device);
    273303                        return rc;
     
    275305                rc = arp_proto_create(&proto, protocol, address);
    276306                if (rc != EOK) {
    277                         fibril_rwlock_write_unlock(&arp_globals.lock);
     307                        fibril_mutex_unlock(&arp_globals.lock);
    278308                        free(device);
    279309                        return rc;
     
    281311                index = arp_protos_add(&device->protos, proto->service, proto);
    282312                if (index < 0) {
    283                         fibril_rwlock_write_unlock(&arp_globals.lock);
     313                        fibril_mutex_unlock(&arp_globals.lock);
    284314                        arp_protos_destroy(&device->protos);
    285315                        free(device);
     
    290320                /* Bind the new one */
    291321                device->phone = nil_bind_service(device->service,
    292                     (ipcarg_t) device->device_id, SERVICE_ARP,
     322                    (sysarg_t) device->device_id, SERVICE_ARP,
    293323                    arp_globals.client_connection);
    294324                if (device->phone < 0) {
    295                         fibril_rwlock_write_unlock(&arp_globals.lock);
     325                        fibril_mutex_unlock(&arp_globals.lock);
    296326                        arp_protos_destroy(&device->protos);
    297327                        free(device);
     
    303333                    &device->packet_dimension);
    304334                if (rc != EOK) {
    305                         fibril_rwlock_write_unlock(&arp_globals.lock);
     335                        fibril_mutex_unlock(&arp_globals.lock);
    306336                        arp_protos_destroy(&device->protos);
    307337                        free(device);
     
    313343                    &device->addr_data);
    314344                if (rc != EOK) {
    315                         fibril_rwlock_write_unlock(&arp_globals.lock);
     345                        fibril_mutex_unlock(&arp_globals.lock);
    316346                        arp_protos_destroy(&device->protos);
    317347                        free(device);
     
    323353                    &device->broadcast_addr, &device->broadcast_data);
    324354                if (rc != EOK) {
    325                         fibril_rwlock_write_unlock(&arp_globals.lock);
     355                        fibril_mutex_unlock(&arp_globals.lock);
    326356                        free(device->addr);
    327357                        free(device->addr_data);
     
    334364                    device);
    335365                if (rc != EOK) {
    336                         fibril_rwlock_write_unlock(&arp_globals.lock);
     366                        fibril_mutex_unlock(&arp_globals.lock);
    337367                        free(device->addr);
    338368                        free(device->addr_data);
     
    347377                    device->service, protocol);
    348378        }
    349         fibril_rwlock_write_unlock(&arp_globals.lock);
     379        fibril_mutex_unlock(&arp_globals.lock);
    350380       
    351381        return EOK;
     
    363393        int rc;
    364394
    365         fibril_rwlock_initialize(&arp_globals.lock);
    366         fibril_rwlock_write_lock(&arp_globals.lock);
     395        fibril_mutex_initialize(&arp_globals.lock);
     396        fibril_mutex_lock(&arp_globals.lock);
    367397        arp_globals.client_connection = client_connection;
    368398        rc = arp_cache_initialize(&arp_globals.cache);
    369         fibril_rwlock_write_unlock(&arp_globals.lock);
     399        fibril_mutex_unlock(&arp_globals.lock);
    370400       
    371401        return rc;
     
    383413        arp_device_t *device;
    384414
    385         fibril_rwlock_write_lock(&arp_globals.lock);
     415        fibril_mutex_lock(&arp_globals.lock);
    386416        device = arp_cache_find(&arp_globals.cache, device_id);
    387417        if (!device) {
    388                 fibril_rwlock_write_unlock(&arp_globals.lock);
     418                fibril_mutex_unlock(&arp_globals.lock);
    389419                return ENOENT;
    390420        }
    391421        device->packet_dimension.content = mtu;
    392         fibril_rwlock_write_unlock(&arp_globals.lock);
    393         printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
     422        fibril_mutex_unlock(&arp_globals.lock);
     423        printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
    394424        return EOK;
    395425}
     
    415445 * @return              ENOMEM if there is not enough memory left.
    416446 */
    417 static int arp_receive_message(device_id_t device_id, packet_t packet)
     447static int arp_receive_message(device_id_t device_id, packet_t *packet)
    418448{
    419449        size_t length;
     
    421451        arp_device_t *device;
    422452        arp_proto_t *proto;
    423         measured_string_t *hw_source;
     453        arp_trans_t *trans;
    424454        uint8_t *src_hw;
    425455        uint8_t *src_proto;
     
    452482        des_hw = src_proto + header->protocol_length;
    453483        des_proto = des_hw + header->hardware_length;
    454         hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
    455             CONVERT_SIZE(uint8_t, char, header->protocol_length));
     484        trans = arp_addr_find(&proto->addresses, (char *) src_proto,
     485            header->protocol_length);
    456486        /* Exists? */
    457         if (hw_source) {
    458                 if (hw_source->length != CONVERT_SIZE(uint8_t, char,
    459                     header->hardware_length)) {
     487        if (trans && trans->hw_addr) {
     488                if (trans->hw_addr->length != header->hardware_length)
    460489                        return EINVAL;
    461                 }
    462                 memcpy(hw_source->value, src_hw, hw_source->length);
     490                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    463491        }
    464492        /* Is my protocol address? */
    465         if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
    466             header->protocol_length)) {
     493        if (proto->addr->length != header->protocol_length)
    467494                return EINVAL;
    468         }
    469495        if (!str_lcmp(proto->addr->value, (char *) des_proto,
    470496            proto->addr->length)) {
    471497                /* Not already updated? */
    472                 if (!hw_source) {
    473                         hw_source = measured_string_create_bulk((char *) src_hw,
    474                             CONVERT_SIZE(uint8_t, char,
    475                             header->hardware_length));
    476                         if (!hw_source)
     498                if (!trans) {
     499                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     500                        if (!trans)
    477501                                return ENOMEM;
    478 
     502                        trans->hw_addr = NULL;
     503                        fibril_condvar_initialize(&trans->cv);
    479504                        rc = arp_addr_add(&proto->addresses, (char *) src_proto,
    480                             CONVERT_SIZE(uint8_t, char,
    481                             header->protocol_length), hw_source);
    482                         if (rc != EOK)
     505                            header->protocol_length, trans);
     506                        if (rc != EOK) {
     507                                /* The generic char map has already freed trans! */
    483508                                return rc;
     509                        }
     510                }
     511                if (!trans->hw_addr) {
     512                        trans->hw_addr = measured_string_create_bulk(
     513                            (char *) src_hw, header->hardware_length);
     514                        if (!trans->hw_addr)
     515                                return ENOMEM;
     516
     517                        /* Notify the fibrils that wait for the translation. */
     518                        fibril_condvar_broadcast(&trans->cv);
    484519                }
    485520                if (ntohs(header->operation) == ARPOP_REQUEST) {
     
    490525                        memcpy(src_hw, device->addr->value,
    491526                            device->packet_dimension.addr_len);
    492                         memcpy(des_hw, hw_source->value,
     527                        memcpy(des_hw, trans->hw_addr->value,
    493528                            header->hardware_length);
    494529                       
     
    516551 * @param[in] protocol  The protocol service.
    517552 * @param[in] target    The target protocol address.
    518  * @return              The hardware address of the target.
    519  * @return              NULL if the target parameter is NULL.
    520  * @return              NULL if the device is not found.
    521  * @return              NULL if the device packet is too small to send a
    522  *                      request.
    523  * @return              NULL if the hardware address is not found in the cache.
    524  */
    525 static measured_string_t *
     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 */
     558static int
    526559arp_translate_message(device_id_t device_id, services_t protocol,
    527     measured_string_t *target)
     560    measured_string_t *target, measured_string_t **translation)
    528561{
    529562        arp_device_t *device;
    530563        arp_proto_t *proto;
    531         measured_string_t *addr;
     564        arp_trans_t *trans;
    532565        size_t length;
    533         packet_t packet;
     566        packet_t *packet;
    534567        arp_header_t *header;
    535 
    536         if (!target)
    537                 return NULL;
     568        bool retry = false;
     569        int rc;
     570
     571restart:
     572        if (!target || !translation)
     573                return EBADMEM;
    538574
    539575        device = arp_cache_find(&arp_globals.cache, device_id);
    540576        if (!device)
    541                 return NULL;
     577                return ENOENT;
    542578
    543579        proto = arp_protos_find(&device->protos, protocol);
    544580        if (!proto || (proto->addr->length != target->length))
    545                 return NULL;
    546 
    547         addr = arp_addr_find(&proto->addresses, target->value, target->length);
    548         if (addr)
    549                 return addr;
     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)
     594                        return ENOENT;
     595                retry = true;
     596                goto restart;
     597        }
     598        if (retry)
     599                return EAGAIN;
    550600
    551601        /* ARP packet content size = header + (address + translation) * 2 */
    552         length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
    553             CONVERT_SIZE(char, uint8_t, device->addr->length));
     602        length = 8 + 2 * (proto->addr->length + device->addr->length);
    554603        if (length > device->packet_dimension.content)
    555                 return NULL;
     604                return ELIMIT;
    556605
    557606        packet = packet_get_4_remote(arp_globals.net_phone,
     
    559608            length, device->packet_dimension.suffix);
    560609        if (!packet)
    561                 return NULL;
     610                return ENOMEM;
    562611
    563612        header = (arp_header_t *) packet_suffix(packet, length);
    564613        if (!header) {
    565614                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    566                 return NULL;
     615                return ENOMEM;
    567616        }
    568617
     
    583632        memcpy(((uint8_t *) header) + length, target->value, target->length);
    584633
    585         if (packet_set_addr(packet, (uint8_t *) device->addr->value,
    586             (uint8_t *) device->broadcast_addr->value,
    587             CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
     634        rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     635            (uint8_t *) device->broadcast_addr->value, device->addr->length);
     636        if (rc != EOK) {
    588637                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    589                 return NULL;
     638                return rc;
    590639        }
    591640
    592641        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    593         return NULL;
     642
     643        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     644        if (!trans)
     645                return ENOMEM;
     646        trans->hw_addr = NULL;
     647        fibril_condvar_initialize(&trans->cv);
     648        rc = arp_addr_add(&proto->addresses, target->value, target->length,
     649            trans);
     650        if (rc != EOK) {
     651                /* The generic char map has already freed trans! */
     652                return rc;
     653        }
     654       
     655        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     656            ARP_TRANS_WAIT);
     657        if (rc == ETIMEOUT)
     658                return ENOENT;
     659        retry = true;
     660        goto restart;
    594661}
    595662
     
    615682        measured_string_t *translation;
    616683        char *data;
    617         packet_t packet;
    618         packet_t next;
     684        packet_t *packet;
     685        packet_t *next;
    619686        int rc;
    620687       
    621688        *answer_count = 0;
    622         switch (IPC_GET_METHOD(*call)) {
     689        switch (IPC_GET_IMETHOD(*call)) {
    623690        case IPC_M_PHONE_HUNGUP:
    624691                return EOK;
     
    642709                        return rc;
    643710               
    644                 fibril_rwlock_read_lock(&arp_globals.lock);
    645                 translation = arp_translate_message(IPC_GET_DEVICE(call),
    646                     IPC_GET_SERVICE(call), address);
     711                fibril_mutex_lock(&arp_globals.lock);
     712                rc = arp_translate_message(IPC_GET_DEVICE(call),
     713                    IPC_GET_SERVICE(call), address, &translation);
    647714                free(address);
    648715                free(data);
     716                if (rc != EOK) {
     717                        fibril_mutex_unlock(&arp_globals.lock);
     718                        return rc;
     719                }
    649720                if (!translation) {
    650                         fibril_rwlock_read_unlock(&arp_globals.lock);
     721                        fibril_mutex_unlock(&arp_globals.lock);
    651722                        return ENOENT;
    652723                }
    653724                rc = measured_strings_reply(translation, 1);
    654                 fibril_rwlock_read_unlock(&arp_globals.lock);
     725                fibril_mutex_unlock(&arp_globals.lock);
    655726                return rc;
    656727
     
    682753                        return rc;
    683754               
    684                 fibril_rwlock_read_lock(&arp_globals.lock);
     755                fibril_mutex_lock(&arp_globals.lock);
    685756                do {
    686757                        next = pq_detach(packet);
     
    692763                        packet = next;
    693764                } while (packet);
    694                 fibril_rwlock_read_unlock(&arp_globals.lock);
     765                fibril_mutex_unlock(&arp_globals.lock);
    695766               
    696767                return EOK;
     
    736807                 * result.
    737808                 */
    738                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     809                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    739810                    (res == EHANGUP))
    740811                        return;
Note: See TracChangeset for help on using the changeset viewer.