Ignore:
File:
1 edited

Legend:

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

    r6b82009 r4ee7364  
    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>
     
    5254#include <protocol_map.h>
    5355#include <net/device.h>
    54 #include <netif_remote.h>
    5556#include <net_interface.h>
    5657#include <il_remote.h>
     
    5859#include <packet_client.h>
    5960#include <packet_remote.h>
     61#include <device/nic.h>
    6062#include <nil_skel.h>
    6163#include "eth.h"
     
    167169INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    168170
    169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
     171int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
    170172{
    171173        int index;
     
    195197        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    196198        fibril_rwlock_write_lock(&eth_globals.protos_lock);
     199       
    197200        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         }
     201        memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
     202                        ETH_ADDR);
    205203
    206204        rc = eth_devices_initialize(&eth_globals.devices);
     
    215213                eth_devices_destroy(&eth_globals.devices, free);
    216214        }
     215       
    217216out:
    218217        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    222221}
    223222
    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,
     223/** Register new device or updates the MTU of an existing one.
     224 *
     225 * Determine the device local hardware address.
     226 *
     227 * @param[in] device_id New device identifier.
     228 * @param[in] handle    Device driver handle.
     229 * @param[in] mtu       Device maximum transmission unit.
     230 *
     231 * @return EOK on success.
     232 * @return EEXIST if the device with the different service exists.
     233 * @return ENOMEM if there is not enough memory left.
     234 *
     235 */
     236static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
    279237    size_t mtu)
    280238{
     
    301259        device = eth_devices_find(&eth_globals.devices, device_id);
    302260        if (device) {
    303                 if (device->service != service) {
     261                if (device->handle != handle) {
    304262                        printf("Device %d already exists\n", device->device_id);
    305263                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    340298
    341299        device->device_id = device_id;
    342         device->service = service;
     300        device->handle = handle;
    343301        device->flags = 0;
    344302        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    377335       
    378336        /* Bind the device driver */
    379         device->sess = netif_bind_service(device->service, device->device_id,
    380             SERVICE_ETHERNET, eth_receiver);
     337        device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
     338            IPC_FLAG_BLOCKING);
    381339        if (device->sess == NULL) {
    382340                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    385343        }
    386344       
     345        nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
     346       
    387347        /* Get hardware address */
    388         rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
    389             &device->addr_data);
     348        rc = nic_get_address(device->sess, &device->addr);
    390349        if (rc != EOK) {
    391350                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    399358        if (index < 0) {
    400359                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    401                 free(device->addr);
    402                 free(device->addr_data);
    403360                free(device);
    404361                return index;
    405362        }
    406363       
    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);
     364        printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
     365            "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
     366            device->device_id, device->handle, device->mtu,
     367            ARGSMAC(device->addr.address), device->flags);
    413368
    414369        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    456411                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    457412                length -= sizeof(eth_fcs_t);
    458         } else if(type <= ETH_MAX_CONTENT) {
     413        } else if (type <= ETH_MAX_CONTENT) {
    459414                /* Translate "LSAP" values */
    460415                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    462417                        /* Raw packet -- discard */
    463418                        return NULL;
    464                 } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
     419                } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
    465420                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    466421                        /*
     
    469424                         */
    470425                        type = ntohs(header->snap.ethertype);
    471                         prefix = sizeof(eth_header_t) +
    472                             sizeof(eth_header_lsap_t) +
     426                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
    473427                            sizeof(eth_header_snap_t);
    474428                } else {
    475429                        /* IEEE 802.3 + 802.2 LSAP */
    476430                        type = lsap_map(header->lsap.dsap);
    477                         prefix = sizeof(eth_header_t) +
    478                             sizeof(eth_header_lsap_t);
     431                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
    479432                }
    480433
     
    506459}
    507460
    508 int nil_received_msg_local(device_id_t device_id, packet_t *packet,
    509     services_t target)
     461int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
    510462{
    511463        eth_proto_t *proto;
     
    523475        flags = device->flags;
    524476        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    525        
    526477        fibril_rwlock_read_lock(&eth_globals.protos_lock);
     478       
    527479        do {
    528480                next = pq_detach(packet);
     
    537489                }
    538490                packet = next;
    539         } while(packet);
     491        } while (packet);
    540492
    541493        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    554506 * @return              ENOENT if there is no such device.
    555507 */
    556 static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
     508static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
    557509    size_t *prefix, size_t *content, size_t *suffix)
    558510{
     
    579531}
    580532
    581 /** Returns the device hardware address.
     533/** Send the device hardware address.
    582534 *
    583535 * @param[in] device_id The device identifier.
    584536 * @param[in] type      Type of the desired address.
    585  * @param[out] address  The device hardware address.
    586537 * @return              EOK on success.
    587538 * @return              EBADMEM if the address parameter is NULL.
    588539 * @return              ENOENT if there no such device.
    589540 */
    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 {
     541static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
     542{
     543        eth_device_t *device = NULL;
     544        uint8_t *address;
     545        size_t max_len;
     546        ipc_callid_t callid;
     547       
     548        if (type == ETH_BROADCAST_ADDR)
     549                address = eth_globals.broadcast_addr;
     550        else {
    601551                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    602552                device = eth_devices_find(&eth_globals.devices, device_id);
     
    605555                        return ENOENT;
    606556                }
    607                 *address = device->addr;
     557               
     558                address = (uint8_t *) &device->addr.address;
     559        }
     560       
     561        int rc = EOK;
     562        if (!async_data_read_receive(&callid, &max_len)) {
     563                rc = EREFUSED;
     564                goto end;
     565        }
     566       
     567        if (max_len < ETH_ADDR) {
     568                async_data_read_finalize(callid, NULL, 0);
     569                rc = ELIMIT;
     570                goto end;
     571        }
     572       
     573        rc = async_data_read_finalize(callid, address, ETH_ADDR);
     574        if (rc != EOK)
     575                goto end;
     576       
     577end:
     578       
     579        if (type == ETH_LOCAL_ADDR)
    608580                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    609         }
    610        
    611         return (*address) ? EOK : ENOENT;
     581       
     582        return rc;
    612583}
    613584
     
    659630        }
    660631       
    661         printf("%s: Protocol registered (protocol: %d, service: %d)\n",
     632        printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
    662633            NAME, proto->protocol, proto->service);
    663634       
     
    697668        if (i < 0)
    698669                return i;
     670       
    699671        if (i != ETH_ADDR)
    700672                return EINVAL;
     673       
     674        for (i = 0; i < ETH_ADDR; i++) {
     675                if (src[i]) {
     676                        src_addr = src;
     677                        break;
     678                }
     679        }
    701680
    702681        length = packet_get_data_length(packet);
     
    722701                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    723702                src = &header_dix->destination_address[0];
    724         } else if(IS_8023_2_LSAP(flags)) {
     703        } else if (IS_8023_2_LSAP(flags)) {
    725704                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    726705                if (!header_lsap)
     
    735714                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    736715                src = &header_lsap->header.destination_address[0];
    737         } else if(IS_8023_2_SNAP(flags)) {
     716        } else if (IS_8023_2_SNAP(flags)) {
    738717                header = PACKET_PREFIX(packet, eth_header_snap_t);
    739718                if (!header)
     
    746725                header->lsap.ctrl = IEEE_8023_2_UI;
    747726               
    748                 for (i = 0; i < 3; ++ i)
     727                for (i = 0; i < 3; i++)
    749728                        header->snap.protocol[i] = 0;
    750729               
     
    760739                        return ENOMEM;
    761740               
    762                 for (i = 0; i < 7; ++ i)
     741                for (i = 0; i < 7; i++)
    763742                        preamble->preamble[i] = ETH_PREAMBLE;
    764743               
     
    787766 * @return              EINVAL if the service parameter is not known.
    788767 */
    789 static int eth_send_message(device_id_t device_id, packet_t *packet,
     768static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
    790769    services_t sender)
    791770{
     
    813792        do {
    814793                rc = eth_prepare_packet(device->flags, next,
    815                     (uint8_t *) device->addr->value, ethertype, device->mtu);
     794                    (uint8_t *) &device->addr.address, ethertype, device->mtu);
    816795                if (rc != EOK) {
    817796                        /* Release invalid packet */
     
    825804                        next = pq_next(next);
    826805                }
    827         } while(next);
     806        } while (next);
    828807       
    829808        /* Send packet queue */
    830         if (packet) {
    831                 netif_send_msg(device->sess, device_id, packet,
    832                     SERVICE_ETHERNET);
    833         }
    834 
     809        if (packet)
     810                nic_send_message(device->sess, packet_get_id(packet));
     811       
    835812        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    836813        return EOK;
    837814}
    838815
     816static int eth_addr_changed(nic_device_id_t device_id)
     817{
     818        nic_address_t address;
     819        size_t length;
     820        ipc_callid_t data_callid;
     821        if (!async_data_write_receive(&data_callid, &length)) {
     822                async_answer_0(data_callid, EINVAL);
     823                return EINVAL;
     824        }
     825        if (length > sizeof (nic_address_t)) {
     826                async_answer_0(data_callid, ELIMIT);
     827                return ELIMIT;
     828        }
     829        if (async_data_write_finalize(data_callid, &address, length) != EOK) {
     830                return EINVAL;
     831        }
     832
     833        fibril_rwlock_write_lock(&eth_globals.devices_lock);
     834        /* An existing device? */
     835        eth_device_t *device = eth_devices_find(&eth_globals.devices, device_id);
     836        if (device) {
     837                printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
     838                        device_id, ARGSMAC(device->addr.address), ARGSMAC(address.address));
     839                memcpy(&device->addr, &address, sizeof (nic_address_t));
     840                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     841
     842                /* Notify all upper layer modules */
     843                fibril_rwlock_read_lock(&eth_globals.protos_lock);
     844                int index;
     845                for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
     846                        eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
     847                        if (proto->sess != NULL) {
     848                                il_addr_changed_msg(proto->sess, device->device_id,
     849                                                ETH_ADDR, address.address);
     850                        }
     851                }
     852
     853                fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     854                return EOK;
     855        } else {
     856                return ENOENT;
     857        }
     858}
     859
    839860int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    840861    ipc_call_t *answer, size_t *answer_count)
    841862{
    842         measured_string_t *address;
    843863        packet_t *packet;
    844864        size_t addrlen;
     
    861881        case NET_NIL_DEVICE:
    862882                return eth_device_message(IPC_GET_DEVICE(*call),
    863                     IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
     883                    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
    864884        case NET_NIL_SEND:
    865885                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    867887                if (rc != EOK)
    868888                        return rc;
     889               
    869890                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    870891                    IPC_GET_SERVICE(*call));
     
    874895                if (rc != EOK)
    875896                        return rc;
     897               
    876898                IPC_SET_ADDR(*answer, addrlen);
    877899                IPC_SET_PREFIX(*answer, prefix);
     
    879901                IPC_SET_SUFFIX(*answer, suffix);
    880902                *answer_count = 4;
     903               
    881904                return EOK;
    882905        case NET_NIL_ADDR:
    883                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
    884                     &address);
     906                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
    885907                if (rc != EOK)
    886908                        return rc;
    887                 return measured_strings_reply(address, 1);
     909               
     910                IPC_SET_ADDR(*answer, ETH_ADDR);
     911                *answer_count = 1;
     912               
     913                return EOK;
    888914        case NET_NIL_BROADCAST_ADDR:
    889                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
    890                     &address);
     915                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
    891916                if (rc != EOK)
    892                         return EOK;
    893                 return measured_strings_reply(address, 1);
     917                        return rc;
     918               
     919                IPC_SET_ADDR(*answer, ETH_ADDR);
     920                *answer_count = 1;
     921               
     922                return EOK;
     923        case NET_NIL_DEVICE_STATE:
     924                nil_device_state_msg_local(IPC_GET_DEVICE(*call), IPC_GET_STATE(*call));
     925                async_answer_0(callid, EOK);
     926                return EOK;
     927        case NET_NIL_RECEIVED:
     928                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     929                    IPC_GET_ARG2(*call));
     930                if (rc == EOK)
     931                        rc = nil_received_msg_local(IPC_GET_ARG1(*call), packet);
     932               
     933                async_answer_0(callid, (sysarg_t) rc);
     934                return rc;
     935        case NET_NIL_ADDR_CHANGED:
     936                rc = eth_addr_changed(IPC_GET_DEVICE(*call));
     937                async_answer_0(callid, (sysarg_t) rc);
     938                return rc;
    894939        }
    895940       
Note: See TracChangeset for help on using the changeset viewer.