Changeset 597c948 in mainline


Ignore:
Timestamp:
2011-01-11T07:24:04Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f902d36
Parents:
bddec0c
Message:

prepare ARP translation data structure before (!) sending the ARP reply
repeat sending the ARP reply if it stays unanswered

File:
1 edited

Legend:

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

    rbddec0c r597c948  
    542542}
    543543
    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;
    566         packet_t *packet;
    567         arp_header_t *header;
    568         bool retry = false;
    569         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)
    594                         return ENOENT;
    595                 retry = true;
    596                 goto restart;
    597         }
    598         if (retry)
    599                 return EAGAIN;
    600 
     544static int arp_send_request(device_id_t device_id, services_t protocol,
     545    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
     546{
    601547        /* ARP packet content size = header + (address + translation) * 2 */
    602         length = 8 + 2 * (proto->addr->length + device->addr->length);
     548        size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
    603549        if (length > device->packet_dimension.content)
    604550                return ELIMIT;
    605 
    606         packet = packet_get_4_remote(arp_globals.net_phone,
     551       
     552        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
    607553            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    608554            length, device->packet_dimension.suffix);
    609555        if (!packet)
    610556                return ENOMEM;
    611 
    612         header = (arp_header_t *) packet_suffix(packet, length);
     557       
     558        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
    613559        if (!header) {
    614560                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    615561                return ENOMEM;
    616562        }
    617 
     563       
    618564        header->hardware = htons(device->hardware);
    619565        header->hardware_length = (uint8_t) device->addr->length;
     
    631577        length += device->addr->length;
    632578        memcpy(((uint8_t *) header) + length, target->value, target->length);
    633 
    634         rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     579       
     580        int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    635581            (uint8_t *) device->broadcast_addr->value, device->addr->length);
    636582        if (rc != EOK) {
     
    638584                return rc;
    639585        }
    640 
     586       
    641587        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    642 
     588        return EOK;
     589}
     590
     591/** Return the hardware address for the given protocol address.
     592 *
     593 * Send the ARP request packet if the hardware address is not found in the
     594 * cache.
     595 *
     596 * @param[in]  device_id   Device identifier.
     597 * @param[in]  protocol    Protocol service.
     598 * @param[in]  target      Target protocol address.
     599 * @param[out] translation Where the hardware address of the target is stored.
     600 *
     601 * @return EOK on success.
     602 * @return EAGAIN if the caller should try again.
     603 * @return Other error codes in case of error.
     604 *
     605 */
     606static int
     607arp_translate_message(device_id_t device_id, services_t protocol,
     608    measured_string_t *target, measured_string_t **translation)
     609{
     610        arp_device_t *device;
     611        arp_proto_t *proto;
     612        arp_trans_t *trans;
     613        bool retry = false;
     614        int rc;
     615       
     616restart:
     617        if ((!target) || (!translation))
     618                return EBADMEM;
     619       
     620        device = arp_cache_find(&arp_globals.cache, device_id);
     621        if (!device)
     622                return ENOENT;
     623       
     624        proto = arp_protos_find(&device->protos, protocol);
     625        if ((!proto) || (proto->addr->length != target->length))
     626                return ENOENT;
     627       
     628        trans = arp_addr_find(&proto->addresses, target->value, target->length);
     629        if (trans) {
     630                if (trans->hw_addr) {
     631                        *translation = trans->hw_addr;
     632                        return EOK;
     633                }
     634               
     635                if (retry)
     636                        return EAGAIN;
     637               
     638                rc = arp_send_request(device_id, protocol, target, device, proto);
     639                if (rc != EOK)
     640                        return rc;
     641               
     642                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     643                    ARP_TRANS_WAIT);
     644                if (rc == ETIMEOUT)
     645                        return ENOENT;
     646               
     647                retry = true;
     648                goto restart;
     649        }
     650       
     651        if (retry)
     652                return EAGAIN;
     653       
    643654        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    644655        if (!trans)
     
    653664        }
    654665       
     666        rc = arp_send_request(device_id, protocol, target, device, proto);
     667        if (rc != EOK)
     668                return rc;
     669       
    655670        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    656671            ARP_TRANS_WAIT);
    657672        if (rc == ETIMEOUT)
    658673                return ENOENT;
     674       
    659675        retry = true;
    660676        goto restart;
Note: See TracChangeset for help on using the changeset viewer.