Ignore:
File:
1 edited

Legend:

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

    r00d7e1b r6b82009  
    11/*
    22 * Copyright (c) 2009 Lukas Mejdrech
    3  * Copyright (c) 2011 Radim Vansa
    43 * All rights reserved.
    54 *
     
    3736 */
    3837
    39 #include <assert.h>
    4038#include <async.h>
    4139#include <malloc.h>
     
    5452#include <protocol_map.h>
    5553#include <net/device.h>
     54#include <netif_remote.h>
    5655#include <net_interface.h>
    5756#include <il_remote.h>
     
    5958#include <packet_client.h>
    6059#include <packet_remote.h>
    61 #include <device/nic.h>
    6260#include <nil_skel.h>
    6361#include "eth.h"
     
    169167INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    170168
    171 int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
     169int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
    172170{
    173171        int index;
     
    198196        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    199197        eth_globals.net_sess = sess;
    200         memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
    201                         ETH_ADDR);
     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        }
    202205
    203206        rc = eth_devices_initialize(&eth_globals.devices);
     
    212215                eth_devices_destroy(&eth_globals.devices, free);
    213216        }
    214        
    215217out:
    216218        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    220222}
    221223
    222 /** Register new device or updates the MTU of an existing one.
    223  *
    224  * Determine the device local hardware address.
    225  *
    226  * @param[in] device_id New device identifier.
    227  * @param[in] handle    Device driver handle.
    228  * @param[in] mtu       Device maximum transmission unit.
    229  *
    230  * @return EOK on success.
    231  * @return EEXIST if the device with the different service exists.
    232  * @return ENOMEM if there is not enough memory left.
    233  *
    234  */
    235 static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
     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 */
     232static 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 */
     278static int eth_device_message(device_id_t device_id, services_t service,
    236279    size_t mtu)
    237280{
     
    258301        device = eth_devices_find(&eth_globals.devices, device_id);
    259302        if (device) {
    260                 if (device->handle != handle) {
     303                if (device->service != service) {
    261304                        printf("Device %d already exists\n", device->device_id);
    262305                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    297340
    298341        device->device_id = device_id;
    299         device->handle = handle;
     342        device->service = service;
    300343        device->flags = 0;
    301344        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    334377       
    335378        /* Bind the device driver */
    336         device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
    337             IPC_FLAG_BLOCKING);
     379        device->sess = netif_bind_service(device->service, device->device_id,
     380            SERVICE_ETHERNET, eth_receiver);
    338381        if (device->sess == NULL) {
    339382                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    342385        }
    343386       
    344         nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
    345        
    346387        /* Get hardware address */
    347         rc = nic_get_address(device->sess, &device->addr);
     388        rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
     389            &device->addr_data);
    348390        if (rc != EOK) {
    349391                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    357399        if (index < 0) {
    358400                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     401                free(device->addr);
     402                free(device->addr_data);
    359403                free(device);
    360404                return index;
    361405        }
    362406       
    363         printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
    364             "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
    365             device->device_id, device->handle, device->mtu,
    366             ARGSMAC(device->addr.address), device->flags);
     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);
    367413
    368414        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    410456                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    411457                length -= sizeof(eth_fcs_t);
    412         } else if (type <= ETH_MAX_CONTENT) {
     458        } else if(type <= ETH_MAX_CONTENT) {
    413459                /* Translate "LSAP" values */
    414460                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    416462                        /* Raw packet -- discard */
    417463                        return NULL;
    418                 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
     464                } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
    419465                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    420466                        /*
     
    423469                         */
    424470                        type = ntohs(header->snap.ethertype);
    425                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
     471                        prefix = sizeof(eth_header_t) +
     472                            sizeof(eth_header_lsap_t) +
    426473                            sizeof(eth_header_snap_t);
    427474                } else {
    428475                        /* IEEE 802.3 + 802.2 LSAP */
    429476                        type = lsap_map(header->lsap.dsap);
    430                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
     477                        prefix = sizeof(eth_header_t) +
     478                            sizeof(eth_header_lsap_t);
    431479                }
    432480
     
    458506}
    459507
    460 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
     508int nil_received_msg_local(device_id_t device_id, packet_t *packet,
     509    services_t target)
    461510{
    462511        eth_proto_t *proto;
     
    474523        flags = device->flags;
    475524        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
     525       
    476526        fibril_rwlock_read_lock(&eth_globals.protos_lock);
    477        
    478527        do {
    479528                next = pq_detach(packet);
     
    488537                }
    489538                packet = next;
    490         } while (packet);
     539        } while(packet);
    491540
    492541        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    505554 * @return              ENOENT if there is no such device.
    506555 */
    507 static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
     556static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
    508557    size_t *prefix, size_t *content, size_t *suffix)
    509558{
     
    530579}
    531580
    532 /** Send the device hardware address.
     581/** Returns the device hardware address.
    533582 *
    534583 * @param[in] device_id The device identifier.
    535584 * @param[in] type      Type of the desired address.
     585 * @param[out] address  The device hardware address.
    536586 * @return              EOK on success.
    537587 * @return              EBADMEM if the address parameter is NULL.
    538588 * @return              ENOENT if there no such device.
    539589 */
    540 static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
    541 {
    542         eth_device_t *device = NULL;
    543         uint8_t *address;
    544         size_t max_len;
    545         ipc_callid_t callid;
    546        
    547         if (type == ETH_BROADCAST_ADDR)
    548                 address = eth_globals.broadcast_addr;
    549         else {
     590static 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 {
    550601                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    551602                device = eth_devices_find(&eth_globals.devices, device_id);
     
    554605                        return ENOENT;
    555606                }
    556                
    557                 address = (uint8_t *) &device->addr.address;
    558         }
    559        
    560         int rc = EOK;
    561         if (!async_data_read_receive(&callid, &max_len)) {
    562                 rc = EREFUSED;
    563                 goto end;
    564         }
    565        
    566         if (max_len < ETH_ADDR) {
    567                 async_data_read_finalize(callid, NULL, 0);
    568                 rc = ELIMIT;
    569                 goto end;
    570         }
    571        
    572         rc = async_data_read_finalize(callid, address, ETH_ADDR);
    573         if (rc != EOK)
    574                 goto end;
    575        
    576 end:
    577        
    578         if (type == ETH_LOCAL_ADDR)
     607                *address = device->addr;
    579608                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    580        
    581         return rc;
     609        }
     610       
     611        return (*address) ? EOK : ENOENT;
    582612}
    583613
     
    629659        }
    630660       
    631         printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
     661        printf("%s: Protocol registered (protocol: %d, service: %d)\n",
    632662            NAME, proto->protocol, proto->service);
    633663       
     
    667697        if (i < 0)
    668698                return i;
    669        
    670699        if (i != ETH_ADDR)
    671700                return EINVAL;
    672        
    673         for (i = 0; i < ETH_ADDR; i++) {
    674                 if (src[i]) {
    675                         src_addr = src;
    676                         break;
    677                 }
    678         }
    679701
    680702        length = packet_get_data_length(packet);
     
    700722                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    701723                src = &header_dix->destination_address[0];
    702         } else if (IS_8023_2_LSAP(flags)) {
     724        } else if(IS_8023_2_LSAP(flags)) {
    703725                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    704726                if (!header_lsap)
     
    713735                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    714736                src = &header_lsap->header.destination_address[0];
    715         } else if (IS_8023_2_SNAP(flags)) {
     737        } else if(IS_8023_2_SNAP(flags)) {
    716738                header = PACKET_PREFIX(packet, eth_header_snap_t);
    717739                if (!header)
     
    724746                header->lsap.ctrl = IEEE_8023_2_UI;
    725747               
    726                 for (i = 0; i < 3; i++)
     748                for (i = 0; i < 3; ++ i)
    727749                        header->snap.protocol[i] = 0;
    728750               
     
    738760                        return ENOMEM;
    739761               
    740                 for (i = 0; i < 7; i++)
     762                for (i = 0; i < 7; ++ i)
    741763                        preamble->preamble[i] = ETH_PREAMBLE;
    742764               
     
    765787 * @return              EINVAL if the service parameter is not known.
    766788 */
    767 static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
     789static int eth_send_message(device_id_t device_id, packet_t *packet,
    768790    services_t sender)
    769791{
     
    791813        do {
    792814                rc = eth_prepare_packet(device->flags, next,
    793                     (uint8_t *) &device->addr.address, ethertype, device->mtu);
     815                    (uint8_t *) device->addr->value, ethertype, device->mtu);
    794816                if (rc != EOK) {
    795817                        /* Release invalid packet */
     
    803825                        next = pq_next(next);
    804826                }
    805         } while (next);
     827        } while(next);
    806828       
    807829        /* Send packet queue */
    808         if (packet)
    809                 nic_send_message(device->sess, packet_get_id(packet));
    810        
     830        if (packet) {
     831                netif_send_msg(device->sess, device_id, packet,
     832                    SERVICE_ETHERNET);
     833        }
     834
    811835        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    812836        return EOK;
    813837}
    814838
    815 static int eth_addr_changed(nic_device_id_t device_id)
    816 {
    817         nic_address_t address;
    818         size_t length;
    819         ipc_callid_t data_callid;
    820         if (!async_data_write_receive(&data_callid, &length)) {
    821                 async_answer_0(data_callid, EINVAL);
    822                 return EINVAL;
    823         }
    824         if (length > sizeof (nic_address_t)) {
    825                 async_answer_0(data_callid, ELIMIT);
    826                 return ELIMIT;
    827         }
    828         if (async_data_write_finalize(data_callid, &address, length) != EOK) {
    829                 return EINVAL;
    830         }
    831 
    832         fibril_rwlock_write_lock(&eth_globals.devices_lock);
    833         /* An existing device? */
    834         eth_device_t *device = eth_devices_find(&eth_globals.devices, device_id);
    835         if (device) {
    836                 printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
    837                         device_id, ARGSMAC(device->addr.address), ARGSMAC(address.address));
    838                 memcpy(&device->addr, &address, sizeof (nic_address_t));
    839                 fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    840 
    841                 /* Notify all upper layer modules */
    842                 fibril_rwlock_read_lock(&eth_globals.protos_lock);
    843                 int index;
    844                 for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
    845                         eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
    846                         if (proto->sess != NULL) {
    847                                 il_addr_changed_msg(proto->sess, device->device_id,
    848                                                 ETH_ADDR, address.address);
    849                         }
    850                 }
    851 
    852                 fibril_rwlock_read_unlock(&eth_globals.protos_lock);
    853                 return EOK;
    854         } else {
    855                 return ENOENT;
    856         }
    857 }
    858 
    859839int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    860840    ipc_call_t *answer, size_t *answer_count)
    861841{
     842        measured_string_t *address;
    862843        packet_t *packet;
    863844        size_t addrlen;
     
    880861        case NET_NIL_DEVICE:
    881862                return eth_device_message(IPC_GET_DEVICE(*call),
    882                     IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
     863                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    883864        case NET_NIL_SEND:
    884865                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    886867                if (rc != EOK)
    887868                        return rc;
    888                
    889869                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    890870                    IPC_GET_SERVICE(*call));
     
    894874                if (rc != EOK)
    895875                        return rc;
    896                
    897876                IPC_SET_ADDR(*answer, addrlen);
    898877                IPC_SET_PREFIX(*answer, prefix);
     
    900879                IPC_SET_SUFFIX(*answer, suffix);
    901880                *answer_count = 4;
    902                
    903881                return EOK;
    904882        case NET_NIL_ADDR:
    905                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
     883                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
     884                    &address);
    906885                if (rc != EOK)
    907886                        return rc;
    908                
    909                 IPC_SET_ADDR(*answer, ETH_ADDR);
    910                 *answer_count = 1;
    911                
    912                 return EOK;
     887                return measured_strings_reply(address, 1);
    913888        case NET_NIL_BROADCAST_ADDR:
    914                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
     889                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
     890                    &address);
    915891                if (rc != EOK)
    916                         return rc;
    917                
    918                 IPC_SET_ADDR(*answer, ETH_ADDR);
    919                 *answer_count = 1;
    920                
    921                 return EOK;
    922         case NET_NIL_DEVICE_STATE:
    923                 nil_device_state_msg_local(IPC_GET_DEVICE(*call), IPC_GET_STATE(*call));
    924                 async_answer_0(callid, EOK);
    925                 return EOK;
    926         case NET_NIL_RECEIVED:
    927                 rc = packet_translate_remote(eth_globals.net_sess, &packet,
    928                     IPC_GET_ARG2(*call));
    929                 if (rc == EOK)
    930                         rc = nil_received_msg_local(IPC_GET_ARG1(*call), packet);
    931                
    932                 async_answer_0(callid, (sysarg_t) rc);
    933                 return rc;
    934         case NET_NIL_ADDR_CHANGED:
    935                 rc = eth_addr_changed(IPC_GET_DEVICE(*call));
    936                 async_answer_0(callid, (sysarg_t) rc);
    937                 return rc;
     892                        return EOK;
     893                return measured_strings_reply(address, 1);
    938894        }
    939895       
Note: See TracChangeset for help on using the changeset viewer.