Ignore:
File:
1 edited

Legend:

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

    r7837101 r1bfd3d3  
    7272#define NAME  "arp"
    7373
    74 /** Number of microseconds to wait for an ARP reply. */
    75 #define ARP_TRANS_WAIT  1000000
    76 
    7774/** ARP global data. */
    7875arp_globals_t arp_globals;
     
    8077DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    8178INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    82 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
    83 
    84 static 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 
    93 static 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 
     79GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
    10580
    10681/** Clears the device specific data.
     
    12196                        if (proto->addr_data)
    12297                                free(proto->addr_data);
    123                         arp_clear_addr(&proto->addresses);
    12498                        arp_addr_destroy(&proto->addresses);
    12599                }
     
    133107        arp_device_t *device;
    134108
    135         fibril_mutex_lock(&arp_globals.lock);
     109        fibril_rwlock_write_lock(&arp_globals.lock);
    136110        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    137111            count--) {
     
    146120        }
    147121        arp_cache_clear(&arp_globals.cache);
    148         fibril_mutex_unlock(&arp_globals.lock);
     122        fibril_rwlock_write_unlock(&arp_globals.lock);
    149123        printf("Cache cleaned\n");
    150124        return EOK;
     
    156130        arp_device_t *device;
    157131        arp_proto_t *proto;
    158         arp_trans_t *trans;
    159 
    160         fibril_mutex_lock(&arp_globals.lock);
     132
     133        fibril_rwlock_write_lock(&arp_globals.lock);
    161134        device = arp_cache_find(&arp_globals.cache, device_id);
    162135        if (!device) {
    163                 fibril_mutex_unlock(&arp_globals.lock);
     136                fibril_rwlock_write_unlock(&arp_globals.lock);
    164137                return ENOENT;
    165138        }
    166139        proto = arp_protos_find(&device->protos, protocol);
    167140        if (!proto) {
    168                 fibril_mutex_unlock(&arp_globals.lock);
     141                fibril_rwlock_write_unlock(&arp_globals.lock);
    169142                return ENOENT;
    170143        }
    171         trans = arp_addr_find(&proto->addresses, address->value, address->length);
    172         if (trans)
    173                 arp_clear_trans(trans);
    174144        arp_addr_exclude(&proto->addresses, address->value, address->length);
    175         fibril_mutex_unlock(&arp_globals.lock);
     145        fibril_rwlock_write_unlock(&arp_globals.lock);
    176146        return EOK;
    177147}
     
    182152        arp_device_t *device;
    183153
    184         fibril_mutex_lock(&arp_globals.lock);
     154        fibril_rwlock_write_lock(&arp_globals.lock);
    185155        device = arp_cache_find(&arp_globals.cache, device_id);
    186156        if (!device) {
    187                 fibril_mutex_unlock(&arp_globals.lock);
     157                fibril_rwlock_write_unlock(&arp_globals.lock);
    188158                return ENOENT;
    189159        }
    190160        arp_clear_device(device);
    191161        printf("Device %d cleared\n", device_id);
    192         fibril_mutex_unlock(&arp_globals.lock);
     162        fibril_rwlock_write_unlock(&arp_globals.lock);
    193163        return EOK;
    194164}
     
    251221        int rc;
    252222
    253         fibril_mutex_lock(&arp_globals.lock);
     223        fibril_rwlock_write_lock(&arp_globals.lock);
    254224
    255225        /* An existing device? */
     
    259229                if (device->service != service) {
    260230                        printf("Device %d already exists\n", device->device_id);
    261                         fibril_mutex_unlock(&arp_globals.lock);
     231                        fibril_rwlock_write_unlock(&arp_globals.lock);
    262232                        return EEXIST;
    263233                }
     
    271241                        rc = arp_proto_create(&proto, protocol, address);
    272242                        if (rc != EOK) {
    273                                 fibril_mutex_unlock(&arp_globals.lock);
     243                                fibril_rwlock_write_unlock(&arp_globals.lock);
    274244                                return rc;
    275245                        }
     
    277247                            proto);
    278248                        if (index < 0) {
    279                                 fibril_mutex_unlock(&arp_globals.lock);
     249                                fibril_rwlock_write_unlock(&arp_globals.lock);
    280250                                free(proto);
    281251                                return index;
     
    292262                device = (arp_device_t *) malloc(sizeof(arp_device_t));
    293263                if (!device) {
    294                         fibril_mutex_unlock(&arp_globals.lock);
     264                        fibril_rwlock_write_unlock(&arp_globals.lock);
    295265                        return ENOMEM;
    296266                }
     
    299269                rc = arp_protos_initialize(&device->protos);
    300270                if (rc != EOK) {
    301                         fibril_mutex_unlock(&arp_globals.lock);
     271                        fibril_rwlock_write_unlock(&arp_globals.lock);
    302272                        free(device);
    303273                        return rc;
     
    305275                rc = arp_proto_create(&proto, protocol, address);
    306276                if (rc != EOK) {
    307                         fibril_mutex_unlock(&arp_globals.lock);
     277                        fibril_rwlock_write_unlock(&arp_globals.lock);
    308278                        free(device);
    309279                        return rc;
     
    311281                index = arp_protos_add(&device->protos, proto->service, proto);
    312282                if (index < 0) {
    313                         fibril_mutex_unlock(&arp_globals.lock);
     283                        fibril_rwlock_write_unlock(&arp_globals.lock);
    314284                        arp_protos_destroy(&device->protos);
    315285                        free(device);
     
    320290                /* Bind the new one */
    321291                device->phone = nil_bind_service(device->service,
    322                     (sysarg_t) device->device_id, SERVICE_ARP,
     292                    (ipcarg_t) device->device_id, SERVICE_ARP,
    323293                    arp_globals.client_connection);
    324294                if (device->phone < 0) {
    325                         fibril_mutex_unlock(&arp_globals.lock);
     295                        fibril_rwlock_write_unlock(&arp_globals.lock);
    326296                        arp_protos_destroy(&device->protos);
    327297                        free(device);
     
    333303                    &device->packet_dimension);
    334304                if (rc != EOK) {
    335                         fibril_mutex_unlock(&arp_globals.lock);
     305                        fibril_rwlock_write_unlock(&arp_globals.lock);
    336306                        arp_protos_destroy(&device->protos);
    337307                        free(device);
     
    343313                    &device->addr_data);
    344314                if (rc != EOK) {
    345                         fibril_mutex_unlock(&arp_globals.lock);
     315                        fibril_rwlock_write_unlock(&arp_globals.lock);
    346316                        arp_protos_destroy(&device->protos);
    347317                        free(device);
     
    353323                    &device->broadcast_addr, &device->broadcast_data);
    354324                if (rc != EOK) {
    355                         fibril_mutex_unlock(&arp_globals.lock);
     325                        fibril_rwlock_write_unlock(&arp_globals.lock);
    356326                        free(device->addr);
    357327                        free(device->addr_data);
     
    364334                    device);
    365335                if (rc != EOK) {
    366                         fibril_mutex_unlock(&arp_globals.lock);
     336                        fibril_rwlock_write_unlock(&arp_globals.lock);
    367337                        free(device->addr);
    368338                        free(device->addr_data);
     
    377347                    device->service, protocol);
    378348        }
    379         fibril_mutex_unlock(&arp_globals.lock);
     349        fibril_rwlock_write_unlock(&arp_globals.lock);
    380350       
    381351        return EOK;
     
    393363        int rc;
    394364
    395         fibril_mutex_initialize(&arp_globals.lock);
    396         fibril_mutex_lock(&arp_globals.lock);
     365        fibril_rwlock_initialize(&arp_globals.lock);
     366        fibril_rwlock_write_lock(&arp_globals.lock);
    397367        arp_globals.client_connection = client_connection;
    398368        rc = arp_cache_initialize(&arp_globals.cache);
    399         fibril_mutex_unlock(&arp_globals.lock);
     369        fibril_rwlock_write_unlock(&arp_globals.lock);
    400370       
    401371        return rc;
     
    413383        arp_device_t *device;
    414384
    415         fibril_mutex_lock(&arp_globals.lock);
     385        fibril_rwlock_write_lock(&arp_globals.lock);
    416386        device = arp_cache_find(&arp_globals.cache, device_id);
    417387        if (!device) {
    418                 fibril_mutex_unlock(&arp_globals.lock);
     388                fibril_rwlock_write_unlock(&arp_globals.lock);
    419389                return ENOENT;
    420390        }
    421391        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);
     392        fibril_rwlock_write_unlock(&arp_globals.lock);
     393        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
    424394        return EOK;
    425395}
     
    445415 * @return              ENOMEM if there is not enough memory left.
    446416 */
    447 static int arp_receive_message(device_id_t device_id, packet_t *packet)
     417static int arp_receive_message(device_id_t device_id, packet_t packet)
    448418{
    449419        size_t length;
     
    451421        arp_device_t *device;
    452422        arp_proto_t *proto;
    453         arp_trans_t *trans;
     423        measured_string_t *hw_source;
    454424        uint8_t *src_hw;
    455425        uint8_t *src_proto;
     
    482452        des_hw = src_proto + header->protocol_length;
    483453        des_proto = des_hw + header->hardware_length;
    484         trans = arp_addr_find(&proto->addresses, (char *) src_proto,
    485             header->protocol_length);
     454        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
     455            CONVERT_SIZE(uint8_t, char, header->protocol_length));
    486456        /* Exists? */
    487         if (trans && trans->hw_addr) {
    488                 if (trans->hw_addr->length != header->hardware_length)
     457        if (hw_source) {
     458                if (hw_source->length != CONVERT_SIZE(uint8_t, char,
     459                    header->hardware_length)) {
    489460                        return EINVAL;
    490                 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
     461                }
     462                memcpy(hw_source->value, src_hw, hw_source->length);
    491463        }
    492464        /* Is my protocol address? */
    493         if (proto->addr->length != header->protocol_length)
     465        if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
     466            header->protocol_length)) {
    494467                return EINVAL;
     468        }
    495469        if (!str_lcmp(proto->addr->value, (char *) des_proto,
    496470            proto->addr->length)) {
    497471                /* Not already updated? */
    498                 if (!trans) {
    499                         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    500                         if (!trans)
     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)
    501477                                return ENOMEM;
    502                         trans->hw_addr = NULL;
    503                         fibril_condvar_initialize(&trans->cv);
     478
    504479                        rc = arp_addr_add(&proto->addresses, (char *) src_proto,
    505                             header->protocol_length, trans);
    506                         if (rc != EOK) {
    507                                 /* The generic char map has already freed trans! */
     480                            CONVERT_SIZE(uint8_t, char,
     481                            header->protocol_length), hw_source);
     482                        if (rc != EOK)
    508483                                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);
    519484                }
    520485                if (ntohs(header->operation) == ARPOP_REQUEST) {
     
    525490                        memcpy(src_hw, device->addr->value,
    526491                            device->packet_dimension.addr_len);
    527                         memcpy(des_hw, trans->hw_addr->value,
     492                        memcpy(des_hw, hw_source->value,
    528493                            header->hardware_length);
    529494                       
     
    551516 * @param[in] protocol  The protocol service.
    552517 * @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
     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 */
     525static measured_string_t *
    559526arp_translate_message(device_id_t device_id, services_t protocol,
    560     measured_string_t *target, measured_string_t **translation)
     527    measured_string_t *target)
    561528{
    562529        arp_device_t *device;
    563530        arp_proto_t *proto;
    564         arp_trans_t *trans;
     531        measured_string_t *addr;
    565532        size_t length;
    566         packet_t *packet;
     533        packet_t packet;
    567534        arp_header_t *header;
    568         bool retry = false;
    569         int rc;
    570 
    571 restart:
    572         if (!target || !translation)
    573                 return EBADMEM;
     535
     536        if (!target)
     537                return NULL;
    574538
    575539        device = arp_cache_find(&arp_globals.cache, device_id);
    576540        if (!device)
    577                 return ENOENT;
     541                return NULL;
    578542
    579543        proto = arp_protos_find(&device->protos, protocol);
    580544        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)
    594                         return ENOENT;
    595                 retry = true;
    596                 goto restart;
    597         }
    598         if (retry)
    599                 return EAGAIN;
     545                return NULL;
     546
     547        addr = arp_addr_find(&proto->addresses, target->value, target->length);
     548        if (addr)
     549                return addr;
    600550
    601551        /* ARP packet content size = header + (address + translation) * 2 */
    602         length = 8 + 2 * (proto->addr->length + device->addr->length);
     552        length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
     553            CONVERT_SIZE(char, uint8_t, device->addr->length));
    603554        if (length > device->packet_dimension.content)
    604                 return ELIMIT;
     555                return NULL;
    605556
    606557        packet = packet_get_4_remote(arp_globals.net_phone,
     
    608559            length, device->packet_dimension.suffix);
    609560        if (!packet)
    610                 return ENOMEM;
     561                return NULL;
    611562
    612563        header = (arp_header_t *) packet_suffix(packet, length);
    613564        if (!header) {
    614565                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    615                 return ENOMEM;
     566                return NULL;
    616567        }
    617568
     
    632583        memcpy(((uint8_t *) header) + length, target->value, target->length);
    633584
    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) {
     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) {
    637588                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    638                 return rc;
     589                return NULL;
    639590        }
    640591
    641592        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    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;
     593        return NULL;
    661594}
    662595
     
    682615        measured_string_t *translation;
    683616        char *data;
    684         packet_t *packet;
    685         packet_t *next;
     617        packet_t packet;
     618        packet_t next;
    686619        int rc;
    687620       
    688621        *answer_count = 0;
    689         switch (IPC_GET_IMETHOD(*call)) {
     622        switch (IPC_GET_METHOD(*call)) {
    690623        case IPC_M_PHONE_HUNGUP:
    691624                return EOK;
     
    709642                        return rc;
    710643               
    711                 fibril_mutex_lock(&arp_globals.lock);
    712                 rc = arp_translate_message(IPC_GET_DEVICE(call),
    713                     IPC_GET_SERVICE(call), address, &translation);
     644                fibril_rwlock_read_lock(&arp_globals.lock);
     645                translation = arp_translate_message(IPC_GET_DEVICE(call),
     646                    IPC_GET_SERVICE(call), address);
    714647                free(address);
    715648                free(data);
    716                 if (rc != EOK) {
    717                         fibril_mutex_unlock(&arp_globals.lock);
    718                         return rc;
    719                 }
    720649                if (!translation) {
    721                         fibril_mutex_unlock(&arp_globals.lock);
     650                        fibril_rwlock_read_unlock(&arp_globals.lock);
    722651                        return ENOENT;
    723652                }
    724653                rc = measured_strings_reply(translation, 1);
    725                 fibril_mutex_unlock(&arp_globals.lock);
     654                fibril_rwlock_read_unlock(&arp_globals.lock);
    726655                return rc;
    727656
     
    753682                        return rc;
    754683               
    755                 fibril_mutex_lock(&arp_globals.lock);
     684                fibril_rwlock_read_lock(&arp_globals.lock);
    756685                do {
    757686                        next = pq_detach(packet);
     
    763692                        packet = next;
    764693                } while (packet);
    765                 fibril_mutex_unlock(&arp_globals.lock);
     694                fibril_rwlock_read_unlock(&arp_globals.lock);
    766695               
    767696                return EOK;
     
    807736                 * result.
    808737                 */
    809                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
     738                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    810739                    (res == EHANGUP))
    811740                        return;
Note: See TracChangeset for help on using the changeset viewer.