Changeset 797b704 in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2011-01-12T14:40:09Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update
Children:
014dd57b
Parents:
73ac2e9
Message:

streamline internetworking layer

  • IPC method renaming

NET_IL_DEVICE → NET_IP_DEVICE
NET_IL_PACKET_SPACE → NET_IP_PACKET_SPACE
NET_IL_SEND → NET_IP_SEND

The original methods were actually not generic methods of the IL layer (used by the lower layers), but specific methods of the IP module
and used by the higher layers. The original naming was rather confusing.

  • implelement common IL module skeleton
  • small improvements in the comments of the NETIF and NIL skeletons
  • IL modules now use a separate receiver function for the NET_IL_* calls
File:
1 edited

Legend:

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

    r73ac2e9 r797b704  
    3535 * @see arp.h
    3636 */
    37 
    38 #include "arp.h"
    39 #include "arp_header.h"
    40 #include "arp_oc.h"
    41 #include "arp_module.h"
    4237
    4338#include <async.h>
     
    6459#include <packet_client.h>
    6560#include <packet_remote.h>
    66 #include <il_interface.h>
    67 #include <il_local.h>
    68 
     61#include <il_remote.h>
     62#include <il_skel.h>
     63#include "arp.h"
    6964
    7065/** ARP module name. */
     
    7368/** Number of microseconds to wait for an ARP reply. */
    7469#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));
    75108
    76109/** ARP global data. */
     
    231264       
    232265        return EOK;
     266}
     267
     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{
     293        int rc;
     294       
     295        size_t length = packet_get_data_length(packet);
     296        if (length <= sizeof(arp_header_t))
     297                return EINVAL;
     298       
     299        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     300        if (!device)
     301                return ENOENT;
     302       
     303        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     304        if ((ntohs(header->hardware) != device->hardware) ||
     305            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     306            header->protocol_length * 2U)) {
     307                return EINVAL;
     308        }
     309       
     310        arp_proto_t *proto = arp_protos_find(&device->protos,
     311            protocol_unmap(device->service, ntohs(header->protocol)));
     312        if (!proto)
     313                return ENOENT;
     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,
     321            header->protocol_length);
     322       
     323        if ((trans) && (trans->hw_addr)) {
     324                /* Translation exists */
     325                if (trans->hw_addr->length != header->hardware_length)
     326                        return EINVAL;
     327               
     328                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
     329        }
     330       
     331        /* Is my protocol address? */
     332        if (proto->addr->length != header->protocol_length)
     333                return EINVAL;
     334       
     335        if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
     336                if (!trans) {
     337                        /* Update the translation */
     338                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     339                        if (!trans)
     340                                return ENOMEM;
     341                       
     342                        trans->hw_addr = NULL;
     343                        fibril_condvar_initialize(&trans->cv);
     344                        rc = arp_addr_add(&proto->addresses, src_proto,
     345                            header->protocol_length, trans);
     346                        if (rc != EOK) {
     347                                /* The generic char map has already freed trans! */
     348                                return rc;
     349                        }
     350                }
     351               
     352                if (!trans->hw_addr) {
     353                        trans->hw_addr = measured_string_create_bulk(src_hw,
     354                            header->hardware_length);
     355                        if (!trans->hw_addr)
     356                                return ENOMEM;
     357                       
     358                        /* Notify the fibrils that wait for the translation. */
     359                        fibril_condvar_broadcast(&trans->cv);
     360                }
     361               
     362                if (ntohs(header->operation) == ARPOP_REQUEST) {
     363                        header->operation = htons(ARPOP_REPLY);
     364                        memcpy(des_proto, src_proto, header->protocol_length);
     365                        memcpy(src_proto, proto->addr->value,
     366                            header->protocol_length);
     367                        memcpy(src_hw, device->addr->value,
     368                            device->packet_dimension.addr_len);
     369                        memcpy(des_hw, trans->hw_addr->value,
     370                            header->hardware_length);
     371                       
     372                        rc = packet_set_addr(packet, src_hw, des_hw,
     373                            header->hardware_length);
     374                        if (rc != EOK)
     375                                return rc;
     376                       
     377                        nil_send_msg(device->phone, device_id, packet,
     378                            SERVICE_ARP);
     379                        return 1;
     380                }
     381        }
     382       
     383        return EOK;
     384}
     385
     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{
     422        packet_t *packet;
     423        int rc;
     424       
     425        while (true) {
     426                switch (IPC_GET_IMETHOD(*icall)) {
     427                case NET_IL_DEVICE_STATE:
     428                        /* Do nothing - keep the cache */
     429                        ipc_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                        ipc_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                        ipc_answer_0(iid, (sysarg_t) rc);
     456                        break;
     457               
     458                default:
     459                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     460                }
     461               
     462                iid = async_get_call(icall);
     463        }
    233464}
    234465
     
    335566                device->phone = nil_bind_service(device->service,
    336567                    (sysarg_t) device->device_id, SERVICE_ARP,
    337                     arp_globals.client_connection);
     568                    arp_receiver);
    338569                if (device->phone < 0) {
    339570                        fibril_mutex_unlock(&arp_globals.lock);
     
    396627}
    397628
    398 /** Initialize the ARP module.
    399  *
    400  *  @param[in] client_connection The client connection processing function.
    401  *                               The module skeleton propagates its own one.
    402  *
    403  *  @return EOK on success.
    404  *  @return ENOMEM if there is not enough memory left.
    405  *
    406  */
    407 int arp_initialize(async_client_conn_t client_connection)
     629int il_initialize(int net_phone)
    408630{
    409631        fibril_mutex_initialize(&arp_globals.lock);
    410632       
    411633        fibril_mutex_lock(&arp_globals.lock);
    412         arp_globals.client_connection = client_connection;
     634        arp_globals.net_phone = net_phone;
    413635        int rc = arp_cache_initialize(&arp_globals.cache);
    414636        fibril_mutex_unlock(&arp_globals.lock);
    415637       
    416638        return rc;
    417 }
    418 
    419 /** Update the device content length according to the new MTU value.
    420  *
    421  * @param[in] device_id Device identifier.
    422  * @param[in] mtu       New MTU value.
    423  *
    424  * @return ENOENT if device is not found.
    425  * @return EOK on success.
    426  *
    427  */
    428 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    429 {
    430         fibril_mutex_lock(&arp_globals.lock);
    431        
    432         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    433         if (!device) {
    434                 fibril_mutex_unlock(&arp_globals.lock);
    435                 return ENOENT;
    436         }
    437        
    438         device->packet_dimension.content = mtu;
    439        
    440         fibril_mutex_unlock(&arp_globals.lock);
    441        
    442         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    443        
    444         return EOK;
    445 }
    446 
    447 /** Process the received ARP packet.
    448  *
    449  * Update the source hardware address if the source entry exists or the packet
    450  * is targeted to my protocol address.
    451  *
    452  * Respond to the ARP request if the packet is the ARP request and is
    453  * targeted to my address.
    454  *
    455  * @param[in]     device_id Source device identifier.
    456  * @param[in,out] packet    Received packet.
    457  *
    458  * @return EOK on success and the packet is no longer needed.
    459  * @return One on success and the packet has been reused.
    460  * @return EINVAL if the packet is too small to carry an ARP
    461  *         packet.
    462  * @return EINVAL if the received address lengths differs from
    463  *         the registered values.
    464  * @return ENOENT if the device is not found in the cache.
    465  * @return ENOENT if the protocol for the device is not found in
    466  *         the cache.
    467  * @return ENOMEM if there is not enough memory left.
    468  *
    469  */
    470 static int arp_receive_message(device_id_t device_id, packet_t *packet)
    471 {
    472         int rc;
    473        
    474         size_t length = packet_get_data_length(packet);
    475         if (length <= sizeof(arp_header_t))
    476                 return EINVAL;
    477        
    478         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    479         if (!device)
    480                 return ENOENT;
    481        
    482         arp_header_t *header = (arp_header_t *) packet_get_data(packet);
    483         if ((ntohs(header->hardware) != device->hardware) ||
    484             (length < sizeof(arp_header_t) + header->hardware_length * 2U +
    485             header->protocol_length * 2U)) {
    486                 return EINVAL;
    487         }
    488        
    489         arp_proto_t *proto = arp_protos_find(&device->protos,
    490             protocol_unmap(device->service, ntohs(header->protocol)));
    491         if (!proto)
    492                 return ENOENT;
    493        
    494         uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    495         uint8_t *src_proto = src_hw + header->hardware_length;
    496         uint8_t *des_hw = src_proto + header->protocol_length;
    497         uint8_t *des_proto = des_hw + header->hardware_length;
    498        
    499         arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
    500             header->protocol_length);
    501        
    502         if ((trans) && (trans->hw_addr)) {
    503                 /* Translation exists */
    504                 if (trans->hw_addr->length != header->hardware_length)
    505                         return EINVAL;
    506                
    507                 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    508         }
    509        
    510         /* Is my protocol address? */
    511         if (proto->addr->length != header->protocol_length)
    512                 return EINVAL;
    513        
    514         if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
    515                 if (!trans) {
    516                         /* Update the translation */
    517                         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    518                         if (!trans)
    519                                 return ENOMEM;
    520                        
    521                         trans->hw_addr = NULL;
    522                         fibril_condvar_initialize(&trans->cv);
    523                         rc = arp_addr_add(&proto->addresses, src_proto,
    524                             header->protocol_length, trans);
    525                         if (rc != EOK) {
    526                                 /* The generic char map has already freed trans! */
    527                                 return rc;
    528                         }
    529                 }
    530                
    531                 if (!trans->hw_addr) {
    532                         trans->hw_addr = measured_string_create_bulk(src_hw,
    533                             header->hardware_length);
    534                         if (!trans->hw_addr)
    535                                 return ENOMEM;
    536                        
    537                         /* Notify the fibrils that wait for the translation. */
    538                         fibril_condvar_broadcast(&trans->cv);
    539                 }
    540                
    541                 if (ntohs(header->operation) == ARPOP_REQUEST) {
    542                         header->operation = htons(ARPOP_REPLY);
    543                         memcpy(des_proto, src_proto, header->protocol_length);
    544                         memcpy(src_proto, proto->addr->value,
    545                             header->protocol_length);
    546                         memcpy(src_hw, device->addr->value,
    547                             device->packet_dimension.addr_len);
    548                         memcpy(des_hw, trans->hw_addr->value,
    549                             header->hardware_length);
    550                        
    551                         rc = packet_set_addr(packet, src_hw, des_hw,
    552                             header->hardware_length);
    553                         if (rc != EOK)
    554                                 return rc;
    555                        
    556                         nil_send_msg(device->phone, device_id, packet,
    557                             SERVICE_ARP);
    558                         return 1;
    559                 }
    560         }
    561        
    562         return EOK;
    563639}
    564640
     
    714790 *
    715791 */
    716 int arp_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     792int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    717793    size_t *count)
    718794{
     
    720796        measured_string_t *translation;
    721797        uint8_t *data;
    722         packet_t *packet;
    723         packet_t *next;
    724798        int rc;
    725799       
     
    784858        case NET_ARP_CLEAN_CACHE:
    785859                return arp_clean_cache_req(0);
    786        
    787         case NET_IL_DEVICE_STATE:
    788                 /* Do nothing - keep the cache */
    789                 return EOK;
    790        
    791         case NET_IL_RECEIVED:
    792                
    793                 rc = packet_translate_remote(arp_globals.net_phone, &packet,
    794                     IPC_GET_PACKET(*call));
    795                 if (rc != EOK)
    796                         return rc;
    797                
    798                 fibril_mutex_lock(&arp_globals.lock);
    799                 do {
    800                         next = pq_detach(packet);
    801                         rc = arp_receive_message(IPC_GET_DEVICE(*call), packet);
    802                         if (rc != 1) {
    803                                 pq_release_remote(arp_globals.net_phone,
    804                                     packet_get_id(packet));
    805                         }
    806                         packet = next;
    807                 } while (packet);
    808                 fibril_mutex_unlock(&arp_globals.lock);
    809                
    810                 return EOK;
    811        
    812         case NET_IL_MTU_CHANGED:
    813                 return arp_mtu_changed_message(IPC_GET_DEVICE(*call),
    814                     IPC_GET_MTU(*call));
    815860        }
    816861       
     
    818863}
    819864
    820 /** Default thread for new connections.
    821  *
    822  * @param[in] iid   Initial message identifier.
    823  * @param[in] icall Initial message call structure.
    824  */
    825 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    826 {
    827         /*
    828          * Accept the connection
    829          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    830          */
    831         ipc_answer_0(iid, EOK);
    832        
    833         while (true) {
    834                 ipc_call_t answer;
    835                 size_t count;
    836                
    837                 /* Clear the answer structure */
    838                 refresh_answer(&answer, &count);
    839                
    840                 /* Fetch the next message */
    841                 ipc_call_t call;
    842                 ipc_callid_t callid = async_get_call(&call);
    843                
    844                 /* Process the message */
    845                 int res = il_module_message(callid, &call, &answer,
    846                     &count);
    847                
    848                 /*
    849                  * End if told to either by the message or the processing
    850                  * result.
    851                  */
    852                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    853                     (res == EHANGUP))
    854                         return;
    855                
    856                 /* Answer the message */
    857                 answer_call(callid, res, &answer, count);
    858         }
    859 }
    860 
    861865int main(int argc, char *argv[])
    862866{
    863867        /* Start the module */
    864         return il_module_start(il_client_connection);
     868        return il_module_start(SERVICE_ARP);
    865869}
    866870
Note: See TracChangeset for help on using the changeset viewer.