Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/nil/eth/eth.c

    r6b82009 r9cd8165  
    11/*
    22 * Copyright (c) 2009 Lukas Mejdrech
     3 * Copyright (c) 2011 Radim Vansa
    34 * All rights reserved.
    45 *
     
    3637 */
    3738
     39#include <assert.h>
    3840#include <async.h>
    3941#include <malloc.h>
     
    4648#include <ipc/net.h>
    4749#include <ipc/services.h>
     50#include <loc.h>
    4851#include <net/modules.h>
    4952#include <net_checksum.h>
     
    5255#include <protocol_map.h>
    5356#include <net/device.h>
    54 #include <netif_remote.h>
    5557#include <net_interface.h>
    5658#include <il_remote.h>
     
    5860#include <packet_client.h>
    5961#include <packet_remote.h>
     62#include <device/nic.h>
    6063#include <nil_skel.h>
    6164#include "eth.h"
     
    167170INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    168171
    169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
     172static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall,
     173    void *arg);
     174
     175static int eth_device_state(eth_device_t *device, sysarg_t state)
    170176{
    171177        int index;
     
    177183                proto = eth_protos_get_index(&eth_globals.protos, index);
    178184                if ((proto) && (proto->sess)) {
    179                         il_device_state_msg(proto->sess, device_id, state,
    180                             proto->service);
     185                        il_device_state_msg(proto->sess, device->device_id,
     186                            state, proto->service);
    181187                }
    182188        }
     
    195201        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    196202        fibril_rwlock_write_lock(&eth_globals.protos_lock);
     203       
    197204        eth_globals.net_sess = sess;
    198 
    199         eth_globals.broadcast_addr =
    200             measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
    201         if (!eth_globals.broadcast_addr) {
    202                 rc = ENOMEM;
    203                 goto out;
    204         }
     205        memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
     206                        ETH_ADDR);
    205207
    206208        rc = eth_devices_initialize(&eth_globals.devices);
     
    215217                eth_devices_destroy(&eth_globals.devices, free);
    216218        }
     219       
    217220out:
    218221        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    222225}
    223226
    224 /** Process IPC messages from the registered device driver modules in an
    225  * infinite loop.
    226  *
    227  * @param[in]     iid   Message identifier.
    228  * @param[in,out] icall Message parameters.
    229  * @param[in]     arg   Local argument.
    230  *
    231  */
    232 static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    233 {
    234         packet_t *packet;
    235         int rc;
    236 
    237         while (true) {
    238                 switch (IPC_GET_IMETHOD(*icall)) {
    239                 case NET_NIL_DEVICE_STATE:
    240                         nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
    241                             IPC_GET_STATE(*icall));
    242                         async_answer_0(iid, EOK);
    243                         break;
    244                 case NET_NIL_RECEIVED:
    245                         rc = packet_translate_remote(eth_globals.net_sess,
    246                             &packet, IPC_GET_PACKET(*icall));
    247                         if (rc == EOK)
    248                                 rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
    249                                     packet, 0);
    250                        
    251                         async_answer_0(iid, (sysarg_t) rc);
    252                         break;
    253                 default:
    254                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    255                 }
    256                
    257                 iid = async_get_call(icall);
    258         }
    259 }
    260 
    261 /** Registers new device or updates the MTU of an existing one.
    262  *
    263  * Determines the device local hardware address.
    264  *
    265  * @param[in] device_id The new device identifier.
    266  * @param[in] service   The device driver service.
    267  * @param[in] mtu       The device maximum transmission unit.
    268  * @return              EOK on success.
    269  * @return              EEXIST if the device with the different service exists.
    270  * @return              ENOMEM if there is not enough memory left.
    271  * @return              Other error codes as defined for the
    272  *                      net_get_device_conf_req() function.
    273  * @return              Other error codes as defined for the
    274  *                      netif_bind_service() function.
    275  * @return              Other error codes as defined for the
    276  *                      netif_get_addr_req() function.
    277  */
    278 static int eth_device_message(device_id_t device_id, services_t service,
     227/** Register new device or updates the MTU of an existing one.
     228 *
     229 * Determine the device local hardware address.
     230 *
     231 * @param[in] device_id New device identifier.
     232 * @param[in] sid       NIC service ID.
     233 * @param[in] mtu       Device maximum transmission unit.
     234 *
     235 * @return EOK on success.
     236 * @return EEXIST if the device with the different service exists.
     237 * @return ENOMEM if there is not enough memory left.
     238 *
     239 */
     240static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
    279241    size_t mtu)
    280242{
     
    301263        device = eth_devices_find(&eth_globals.devices, device_id);
    302264        if (device) {
    303                 if (device->service != service) {
     265                if (device->sid != sid) {
    304266                        printf("Device %d already exists\n", device->device_id);
    305267                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    340302
    341303        device->device_id = device_id;
    342         device->service = service;
     304        device->sid = sid;
    343305        device->flags = 0;
    344306        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    377339       
    378340        /* Bind the device driver */
    379         device->sess = netif_bind_service(device->service, device->device_id,
    380             SERVICE_ETHERNET, eth_receiver);
     341        device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
     342            IPC_FLAG_BLOCKING);
    381343        if (device->sess == NULL) {
    382344                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    385347        }
    386348       
     349        rc = nic_callback_create(device->sess, eth_nic_cb_connection, device);
     350        if (rc != EOK) {
     351                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     352                async_hangup(device->sess);
     353                free(device);
     354                return EIO;
     355        }
     356       
    387357        /* Get hardware address */
    388         rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
    389             &device->addr_data);
     358        rc = nic_get_address(device->sess, &device->addr);
    390359        if (rc != EOK) {
    391360                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    399368        if (index < 0) {
    400369                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    401                 free(device->addr);
    402                 free(device->addr_data);
    403370                free(device);
    404371                return index;
    405372        }
    406373       
    407         printf("%s: Device registered (id: %d, service: %d: mtu: %zu, "
    408             "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n",
    409             NAME, device->device_id, device->service, device->mtu,
    410             device->addr_data[0], device->addr_data[1],
    411             device->addr_data[2], device->addr_data[3],
    412             device->addr_data[4], device->addr_data[5], device->flags);
     374        printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, "
     375            "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
     376            device->device_id, device->sid, device->mtu,
     377            ARGSMAC(device->addr.address), device->flags);
    413378
    414379        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    456421                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    457422                length -= sizeof(eth_fcs_t);
    458         } else if(type <= ETH_MAX_CONTENT) {
     423        } else if (type <= ETH_MAX_CONTENT) {
    459424                /* Translate "LSAP" values */
    460425                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    462427                        /* Raw packet -- discard */
    463428                        return NULL;
    464                 } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
     429                } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
    465430                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    466431                        /*
     
    469434                         */
    470435                        type = ntohs(header->snap.ethertype);
    471                         prefix = sizeof(eth_header_t) +
    472                             sizeof(eth_header_lsap_t) +
     436                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
    473437                            sizeof(eth_header_snap_t);
    474438                } else {
    475439                        /* IEEE 802.3 + 802.2 LSAP */
    476440                        type = lsap_map(header->lsap.dsap);
    477                         prefix = sizeof(eth_header_t) +
    478                             sizeof(eth_header_lsap_t);
     441                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
    479442                }
    480443
     
    506469}
    507470
    508 int nil_received_msg_local(device_id_t device_id, packet_t *packet,
    509     services_t target)
     471int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
    510472{
    511473        eth_proto_t *proto;
     
    523485        flags = device->flags;
    524486        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    525        
    526487        fibril_rwlock_read_lock(&eth_globals.protos_lock);
     488       
    527489        do {
    528490                next = pq_detach(packet);
     
    537499                }
    538500                packet = next;
    539         } while(packet);
     501        } while (packet);
    540502
    541503        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    554516 * @return              ENOENT if there is no such device.
    555517 */
    556 static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
     518static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
    557519    size_t *prefix, size_t *content, size_t *suffix)
    558520{
     
    579541}
    580542
    581 /** Returns the device hardware address.
     543/** Send the device hardware address.
    582544 *
    583545 * @param[in] device_id The device identifier.
    584546 * @param[in] type      Type of the desired address.
    585  * @param[out] address  The device hardware address.
    586547 * @return              EOK on success.
    587548 * @return              EBADMEM if the address parameter is NULL.
    588549 * @return              ENOENT if there no such device.
    589550 */
    590 static int eth_addr_message(device_id_t device_id, eth_addr_type_t type,
    591     measured_string_t **address)
    592 {
    593         eth_device_t *device;
    594 
    595         if (!address)
    596                 return EBADMEM;
    597 
    598         if (type == ETH_BROADCAST_ADDR) {
    599                 *address = eth_globals.broadcast_addr;
    600         } else {
     551static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
     552{
     553        eth_device_t *device = NULL;
     554        uint8_t *address;
     555        size_t max_len;
     556        ipc_callid_t callid;
     557       
     558        if (type == ETH_BROADCAST_ADDR)
     559                address = eth_globals.broadcast_addr;
     560        else {
    601561                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    602562                device = eth_devices_find(&eth_globals.devices, device_id);
     
    605565                        return ENOENT;
    606566                }
    607                 *address = device->addr;
     567               
     568                address = (uint8_t *) &device->addr.address;
     569        }
     570       
     571        int rc = EOK;
     572        if (!async_data_read_receive(&callid, &max_len)) {
     573                rc = EREFUSED;
     574                goto end;
     575        }
     576       
     577        if (max_len < ETH_ADDR) {
     578                async_data_read_finalize(callid, NULL, 0);
     579                rc = ELIMIT;
     580                goto end;
     581        }
     582       
     583        rc = async_data_read_finalize(callid, address, ETH_ADDR);
     584        if (rc != EOK)
     585                goto end;
     586       
     587end:
     588       
     589        if (type == ETH_LOCAL_ADDR)
    608590                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    609         }
    610        
    611         return (*address) ? EOK : ENOENT;
     591       
     592        return rc;
    612593}
    613594
     
    659640        }
    660641       
    661         printf("%s: Protocol registered (protocol: %d, service: %d)\n",
     642        printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
    662643            NAME, proto->protocol, proto->service);
    663644       
     
    697678        if (i < 0)
    698679                return i;
     680       
    699681        if (i != ETH_ADDR)
    700682                return EINVAL;
     683       
     684        for (i = 0; i < ETH_ADDR; i++) {
     685                if (src[i]) {
     686                        src_addr = src;
     687                        break;
     688                }
     689        }
    701690
    702691        length = packet_get_data_length(packet);
     
    722711                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    723712                src = &header_dix->destination_address[0];
    724         } else if(IS_8023_2_LSAP(flags)) {
     713        } else if (IS_8023_2_LSAP(flags)) {
    725714                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    726715                if (!header_lsap)
     
    735724                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    736725                src = &header_lsap->header.destination_address[0];
    737         } else if(IS_8023_2_SNAP(flags)) {
     726        } else if (IS_8023_2_SNAP(flags)) {
    738727                header = PACKET_PREFIX(packet, eth_header_snap_t);
    739728                if (!header)
     
    746735                header->lsap.ctrl = IEEE_8023_2_UI;
    747736               
    748                 for (i = 0; i < 3; ++ i)
     737                for (i = 0; i < 3; i++)
    749738                        header->snap.protocol[i] = 0;
    750739               
     
    760749                        return ENOMEM;
    761750               
    762                 for (i = 0; i < 7; ++ i)
     751                for (i = 0; i < 7; i++)
    763752                        preamble->preamble[i] = ETH_PREAMBLE;
    764753               
     
    787776 * @return              EINVAL if the service parameter is not known.
    788777 */
    789 static int eth_send_message(device_id_t device_id, packet_t *packet,
     778static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
    790779    services_t sender)
    791780{
     
    813802        do {
    814803                rc = eth_prepare_packet(device->flags, next,
    815                     (uint8_t *) device->addr->value, ethertype, device->mtu);
     804                    (uint8_t *) &device->addr.address, ethertype, device->mtu);
    816805                if (rc != EOK) {
    817806                        /* Release invalid packet */
     
    823812                        next = tmp;
    824813                } else {
     814                        nic_send_frame(device->sess, packet_get_data(next),
     815                            packet_get_data_length(next));
    825816                        next = pq_next(next);
    826817                }
    827         } while(next);
    828        
    829         /* Send packet queue */
    830         if (packet) {
    831                 netif_send_msg(device->sess, device_id, packet,
    832                     SERVICE_ETHERNET);
    833         }
    834 
     818        } while (next);
     819       
     820        pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
     821       
    835822        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    836823        return EOK;
    837824}
    838825
     826static int eth_received(eth_device_t *device)
     827{
     828        void *data;
     829        size_t size;
     830        int rc;
     831       
     832        rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
     833        if (rc != EOK) {
     834                printf("%s: data_write_accept() failed\n", NAME);
     835                return rc;
     836        }
     837       
     838        packet_t *packet = packet_get_1_remote(eth_globals.net_sess, size);
     839        if (packet == NULL)
     840                return ENOMEM;
     841       
     842        void *pdata = packet_suffix(packet, size);
     843        memcpy(pdata, data, size);
     844        free(data);
     845       
     846        return nil_received_msg_local(device->device_id, packet);
     847}
     848
     849static int eth_addr_changed(eth_device_t *device)
     850{
     851        nic_address_t address;
     852        size_t length;
     853        ipc_callid_t data_callid;
     854        if (!async_data_write_receive(&data_callid, &length)) {
     855                async_answer_0(data_callid, EINVAL);
     856                return EINVAL;
     857        }
     858        if (length > sizeof (nic_address_t)) {
     859                async_answer_0(data_callid, ELIMIT);
     860                return ELIMIT;
     861        }
     862        if (async_data_write_finalize(data_callid, &address, length) != EOK) {
     863                return EINVAL;
     864        }
     865
     866        fibril_rwlock_write_lock(&eth_globals.devices_lock);
     867
     868        printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
     869                device->device_id, ARGSMAC(device->addr.address),
     870                ARGSMAC(address.address));
     871        memcpy(&device->addr, &address, sizeof (nic_address_t));
     872        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     873
     874        /* Notify all upper layer modules */
     875        fibril_rwlock_read_lock(&eth_globals.protos_lock);
     876        int index;
     877        for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
     878                eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
     879                if (proto->sess != NULL) {
     880                        il_addr_changed_msg(proto->sess, device->device_id,
     881                                        ETH_ADDR, address.address);
     882                }
     883        }
     884
     885        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     886        return EOK;
     887}
     888
    839889int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    840890    ipc_call_t *answer, size_t *answer_count)
    841891{
    842         measured_string_t *address;
    843892        packet_t *packet;
    844893        size_t addrlen;
     
    861910        case NET_NIL_DEVICE:
    862911                return eth_device_message(IPC_GET_DEVICE(*call),
    863                     IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
     912                    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
    864913        case NET_NIL_SEND:
    865914                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    867916                if (rc != EOK)
    868917                        return rc;
     918               
    869919                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    870920                    IPC_GET_SERVICE(*call));
     
    874924                if (rc != EOK)
    875925                        return rc;
     926               
    876927                IPC_SET_ADDR(*answer, addrlen);
    877928                IPC_SET_PREFIX(*answer, prefix);
     
    879930                IPC_SET_SUFFIX(*answer, suffix);
    880931                *answer_count = 4;
     932               
    881933                return EOK;
    882934        case NET_NIL_ADDR:
    883                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
    884                     &address);
     935                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
    885936                if (rc != EOK)
    886937                        return rc;
    887                 return measured_strings_reply(address, 1);
     938               
     939                IPC_SET_ADDR(*answer, ETH_ADDR);
     940                *answer_count = 1;
     941               
     942                return EOK;
    888943        case NET_NIL_BROADCAST_ADDR:
    889                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
    890                     &address);
     944                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
    891945                if (rc != EOK)
    892                         return EOK;
    893                 return measured_strings_reply(address, 1);
     946                        return rc;
     947               
     948                IPC_SET_ADDR(*answer, ETH_ADDR);
     949                *answer_count = 1;
     950               
     951                return EOK;
    894952        }
    895953       
    896954        return ENOTSUP;
     955}
     956
     957static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     958{
     959        eth_device_t *device = (eth_device_t *)arg;
     960        int rc;
     961       
     962        async_answer_0(iid, EOK);
     963       
     964        while (true) {
     965                ipc_call_t call;
     966                ipc_callid_t callid = async_get_call(&call);
     967               
     968                if (!IPC_GET_IMETHOD(call))
     969                        break;
     970               
     971                switch (IPC_GET_IMETHOD(call)) {
     972                case NIC_EV_DEVICE_STATE:
     973                        rc = eth_device_state(device, IPC_GET_ARG1(call));
     974                        async_answer_0(callid, (sysarg_t) rc);
     975                        break;
     976                case NIC_EV_RECEIVED:
     977                        rc = eth_received(device);
     978                        async_answer_0(callid, (sysarg_t) rc);
     979                        break;
     980                case NIC_EV_ADDR_CHANGED:
     981                        rc = eth_addr_changed(device);
     982                        async_answer_0(callid, (sysarg_t) rc);
     983                        break;
     984                default:
     985                        async_answer_0(callid, ENOTSUP);
     986                }
     987        }
    897988}
    898989
Note: See TracChangeset for help on using the changeset viewer.