Ignore:
File:
1 edited

Legend:

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

    r00d7e1b r28a3e74  
    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>
     61
    6362#include "eth.h"
    6463
     
    169168INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    170169
    171 int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
     170int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
    172171{
    173172        int index;
     
    178177            index--) {
    179178                proto = eth_protos_get_index(&eth_globals.protos, index);
    180                 if ((proto) && (proto->sess)) {
    181                         il_device_state_msg(proto->sess, device_id, state,
     179                if (proto && proto->phone) {
     180                        il_device_state_msg(proto->phone, device_id, state,
    182181                            proto->service);
    183182                }
     
    188187}
    189188
    190 int nil_initialize(async_sess_t *sess)
     189int nil_initialize(int net_phone)
    191190{
    192191        int rc;
     
    197196        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    198197        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    199         eth_globals.net_sess = sess;
    200         memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
    201                         ETH_ADDR);
     198        eth_globals.net_phone = net_phone;
     199
     200        eth_globals.broadcast_addr =
     201            measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
     202        if (!eth_globals.broadcast_addr) {
     203                rc = ENOMEM;
     204                goto out;
     205        }
    202206
    203207        rc = eth_devices_initialize(&eth_globals.devices);
     
    212216                eth_devices_destroy(&eth_globals.devices, free);
    213217        }
    214        
    215218out:
    216219        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    220223}
    221224
    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,
     225/** Processes IPC messages from the registered device driver modules in an
     226 * infinite loop.
     227 *
     228 * @param[in] iid       The message identifier.
     229 * @param[in,out] icall The message parameters.
     230 */
     231static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall)
     232{
     233        packet_t *packet;
     234        int rc;
     235
     236        while (true) {
     237                switch (IPC_GET_IMETHOD(*icall)) {
     238                case NET_NIL_DEVICE_STATE:
     239                        nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
     240                            IPC_GET_STATE(*icall));
     241                        async_answer_0(iid, EOK);
     242                        break;
     243                case NET_NIL_RECEIVED:
     244                        rc = packet_translate_remote(eth_globals.net_phone,
     245                            &packet, IPC_GET_PACKET(*icall));
     246                        if (rc == EOK)
     247                                rc = nil_received_msg_local(0,
     248                                    IPC_GET_DEVICE(*icall), packet, 0);
     249                       
     250                        async_answer_0(iid, (sysarg_t) rc);
     251                        break;
     252                default:
     253                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     254                }
     255               
     256                iid = async_get_call(icall);
     257        }
     258}
     259
     260/** Registers new device or updates the MTU of an existing one.
     261 *
     262 * Determines the device local hardware address.
     263 *
     264 * @param[in] device_id The new device identifier.
     265 * @param[in] service   The device driver service.
     266 * @param[in] mtu       The device maximum transmission unit.
     267 * @return              EOK on success.
     268 * @return              EEXIST if the device with the different service exists.
     269 * @return              ENOMEM if there is not enough memory left.
     270 * @return              Other error codes as defined for the
     271 *                      net_get_device_conf_req() function.
     272 * @return              Other error codes as defined for the
     273 *                      netif_bind_service() function.
     274 * @return              Other error codes as defined for the
     275 *                      netif_get_addr_req() function.
     276 */
     277static int eth_device_message(device_id_t device_id, services_t service,
    236278    size_t mtu)
    237279{
     
    258300        device = eth_devices_find(&eth_globals.devices, device_id);
    259301        if (device) {
    260                 if (device->handle != handle) {
     302                if (device->service != service) {
    261303                        printf("Device %d already exists\n", device->device_id);
    262304                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    280322                        proto = eth_protos_get_index(&eth_globals.protos,
    281323                            index);
    282                         if (proto->sess) {
    283                                 il_mtu_changed_msg(proto->sess,
     324                        if (proto->phone) {
     325                                il_mtu_changed_msg(proto->phone,
    284326                                    device->device_id, device->mtu,
    285327                                    proto->service);
     
    297339
    298340        device->device_id = device_id;
    299         device->handle = handle;
     341        device->service = service;
    300342        device->flags = 0;
    301343        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    305347
    306348        configuration = &names[0];
    307         rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
     349        rc = net_get_device_conf_req(eth_globals.net_phone, device->device_id,
    308350            &configuration, count, &data);
    309351        if (rc != EOK) {
     
    334376       
    335377        /* Bind the device driver */
    336         device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
    337             IPC_FLAG_BLOCKING);
    338         if (device->sess == NULL) {
     378        device->phone = netif_bind_service(device->service, device->device_id,
     379            SERVICE_ETHERNET, eth_receiver);
     380        if (device->phone < 0) {
    339381                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    340382                free(device);
    341                 return ENOENT;
    342         }
    343        
    344         nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
     383                return device->phone;
     384        }
    345385       
    346386        /* Get hardware address */
    347         rc = nic_get_address(device->sess, &device->addr);
     387        rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
     388            &device->addr_data);
    348389        if (rc != EOK) {
    349390                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    357398        if (index < 0) {
    358399                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     400                free(device->addr);
     401                free(device->addr_data);
    359402                free(device);
    360403                return index;
    361404        }
    362405       
    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);
     406        printf("%s: Device registered (id: %d, service: %d: mtu: %zu, "
     407            "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n",
     408            NAME, device->device_id, device->service, device->mtu,
     409            device->addr_data[0], device->addr_data[1],
     410            device->addr_data[2], device->addr_data[3],
     411            device->addr_data[4], device->addr_data[5], device->flags);
    367412
    368413        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    410455                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    411456                length -= sizeof(eth_fcs_t);
    412         } else if (type <= ETH_MAX_CONTENT) {
     457        } else if(type <= ETH_MAX_CONTENT) {
    413458                /* Translate "LSAP" values */
    414459                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    416461                        /* Raw packet -- discard */
    417462                        return NULL;
    418                 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
     463                } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
    419464                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    420465                        /*
     
    423468                         */
    424469                        type = ntohs(header->snap.ethertype);
    425                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
     470                        prefix = sizeof(eth_header_t) +
     471                            sizeof(eth_header_lsap_t) +
    426472                            sizeof(eth_header_snap_t);
    427473                } else {
    428474                        /* IEEE 802.3 + 802.2 LSAP */
    429475                        type = lsap_map(header->lsap.dsap);
    430                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
     476                        prefix = sizeof(eth_header_t) +
     477                            sizeof(eth_header_lsap_t);
    431478                }
    432479
     
    458505}
    459506
    460 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
     507int nil_received_msg_local(int nil_phone, device_id_t device_id,
     508    packet_t *packet, services_t target)
    461509{
    462510        eth_proto_t *proto;
     
    474522        flags = device->flags;
    475523        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
     524       
    476525        fibril_rwlock_read_lock(&eth_globals.protos_lock);
    477        
    478526        do {
    479527                next = pq_detach(packet);
    480528                proto = eth_process_packet(flags, packet);
    481529                if (proto) {
    482                         il_received_msg(proto->sess, device_id, packet,
     530                        il_received_msg(proto->phone, device_id, packet,
    483531                            proto->service);
    484532                } else {
    485533                        /* Drop invalid/unknown */
    486                         pq_release_remote(eth_globals.net_sess,
     534                        pq_release_remote(eth_globals.net_phone,
    487535                            packet_get_id(packet));
    488536                }
    489537                packet = next;
    490         } while (packet);
     538        } while(packet);
    491539
    492540        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    505553 * @return              ENOENT if there is no such device.
    506554 */
    507 static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
     555static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
    508556    size_t *prefix, size_t *content, size_t *suffix)
    509557{
     
    530578}
    531579
    532 /** Send the device hardware address.
     580/** Returns the device hardware address.
    533581 *
    534582 * @param[in] device_id The device identifier.
    535583 * @param[in] type      Type of the desired address.
     584 * @param[out] address  The device hardware address.
    536585 * @return              EOK on success.
    537586 * @return              EBADMEM if the address parameter is NULL.
    538587 * @return              ENOENT if there no such device.
    539588 */
    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 {
     589static int eth_addr_message(device_id_t device_id, eth_addr_type_t type,
     590    measured_string_t **address)
     591{
     592        eth_device_t *device;
     593
     594        if (!address)
     595                return EBADMEM;
     596
     597        if (type == ETH_BROADCAST_ADDR) {
     598                *address = eth_globals.broadcast_addr;
     599        } else {
    550600                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    551601                device = eth_devices_find(&eth_globals.devices, device_id);
     
    554604                        return ENOENT;
    555605                }
    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)
     606                *address = device->addr;
    579607                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    580        
    581         return rc;
    582 }
    583 
    584 /** Register receiving module service.
    585  *
    586  * Pass received packets for this service.
    587  *
    588  * @param[in] service Module service.
    589  * @param[in] sess    Service session.
    590  *
    591  * @return EOK on success.
    592  * @return ENOENT if the service is not known.
    593  * @return ENOMEM if there is not enough memory left.
    594  *
    595  */
    596 static int eth_register_message(services_t service, async_sess_t *sess)
     608        }
     609       
     610        return (*address) ? EOK : ENOENT;
     611}
     612
     613/** Registers receiving module service.
     614 *
     615 * Passes received packets for this service.
     616 *
     617 * @param[in] service   The module service.
     618 * @param[in] phone     The service phone.
     619 * @return              EOK on success.
     620 * @return              ENOENT if the service is not known.
     621 * @return              ENOMEM if there is not enough memory left.
     622 */
     623static int eth_register_message(services_t service, int phone)
    597624{
    598625        eth_proto_t *proto;
     
    607634        proto = eth_protos_find(&eth_globals.protos, protocol);
    608635        if (proto) {
    609                 proto->sess = sess;
     636                proto->phone = phone;
    610637                fibril_rwlock_write_unlock(&eth_globals.protos_lock);
    611638                return EOK;
     
    619646                proto->service = service;
    620647                proto->protocol = protocol;
    621                 proto->sess = sess;
     648                proto->phone = phone;
    622649
    623650                index = eth_protos_add(&eth_globals.protos, protocol, proto);
     
    629656        }
    630657       
    631         printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
    632             NAME, proto->protocol, proto->service);
     658        printf("%s: Protocol registered (protocol: %d, service: %d, phone: "
     659            "%d)\n", NAME, proto->protocol, proto->service, proto->phone);
    633660       
    634661        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    667694        if (i < 0)
    668695                return i;
    669        
    670696        if (i != ETH_ADDR)
    671697                return EINVAL;
    672        
    673         for (i = 0; i < ETH_ADDR; i++) {
    674                 if (src[i]) {
    675                         src_addr = src;
    676                         break;
    677                 }
    678         }
    679698
    680699        length = packet_get_data_length(packet);
     
    700719                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    701720                src = &header_dix->destination_address[0];
    702         } else if (IS_8023_2_LSAP(flags)) {
     721        } else if(IS_8023_2_LSAP(flags)) {
    703722                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    704723                if (!header_lsap)
     
    713732                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    714733                src = &header_lsap->header.destination_address[0];
    715         } else if (IS_8023_2_SNAP(flags)) {
     734        } else if(IS_8023_2_SNAP(flags)) {
    716735                header = PACKET_PREFIX(packet, eth_header_snap_t);
    717736                if (!header)
     
    724743                header->lsap.ctrl = IEEE_8023_2_UI;
    725744               
    726                 for (i = 0; i < 3; i++)
     745                for (i = 0; i < 3; ++ i)
    727746                        header->snap.protocol[i] = 0;
    728747               
     
    738757                        return ENOMEM;
    739758               
    740                 for (i = 0; i < 7; i++)
     759                for (i = 0; i < 7; ++ i)
    741760                        preamble->preamble[i] = ETH_PREAMBLE;
    742761               
     
    765784 * @return              EINVAL if the service parameter is not known.
    766785 */
    767 static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
     786static int eth_send_message(device_id_t device_id, packet_t *packet,
    768787    services_t sender)
    769788{
     
    776795        ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
    777796        if (!ethertype) {
    778                 pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
     797                pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
    779798                return EINVAL;
    780799        }
     
    791810        do {
    792811                rc = eth_prepare_packet(device->flags, next,
    793                     (uint8_t *) &device->addr.address, ethertype, device->mtu);
     812                    (uint8_t *) device->addr->value, ethertype, device->mtu);
    794813                if (rc != EOK) {
    795814                        /* Release invalid packet */
     
    797816                        if (next == packet)
    798817                                packet = tmp;
    799                         pq_release_remote(eth_globals.net_sess,
     818                        pq_release_remote(eth_globals.net_phone,
    800819                            packet_get_id(next));
    801820                        next = tmp;
     
    803822                        next = pq_next(next);
    804823                }
    805         } while (next);
     824        } while(next);
    806825       
    807826        /* Send packet queue */
    808         if (packet)
    809                 nic_send_message(device->sess, packet_get_id(packet));
    810        
     827        if (packet) {
     828                netif_send_msg(device->phone, device_id, packet,
     829                    SERVICE_ETHERNET);
     830        }
     831
    811832        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    812833        return EOK;
    813834}
    814835
    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 
    859836int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    860837    ipc_call_t *answer, size_t *answer_count)
    861838{
     839        measured_string_t *address;
    862840        packet_t *packet;
    863841        size_t addrlen;
     
    868846       
    869847        *answer_count = 0;
    870        
    871         if (!IPC_GET_IMETHOD(*call))
     848        switch (IPC_GET_IMETHOD(*call)) {
     849        case IPC_M_PHONE_HUNGUP:
    872850                return EOK;
    873851       
    874         async_sess_t *callback =
    875             async_callback_receive_start(EXCHANGE_SERIALIZE, call);
    876         if (callback)
    877                 return eth_register_message(NIL_GET_PROTO(*call), callback);
    878        
    879         switch (IPC_GET_IMETHOD(*call)) {
    880852        case NET_NIL_DEVICE:
    881853                return eth_device_message(IPC_GET_DEVICE(*call),
    882                     IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
     854                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    883855        case NET_NIL_SEND:
    884                 rc = packet_translate_remote(eth_globals.net_sess, &packet,
     856                rc = packet_translate_remote(eth_globals.net_phone, &packet,
    885857                    IPC_GET_PACKET(*call));
    886858                if (rc != EOK)
    887859                        return rc;
    888                
    889860                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    890861                    IPC_GET_SERVICE(*call));
     
    894865                if (rc != EOK)
    895866                        return rc;
    896                
    897867                IPC_SET_ADDR(*answer, addrlen);
    898868                IPC_SET_PREFIX(*answer, prefix);
     
    900870                IPC_SET_SUFFIX(*answer, suffix);
    901871                *answer_count = 4;
    902                
    903872                return EOK;
    904873        case NET_NIL_ADDR:
    905                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
     874                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
     875                    &address);
    906876                if (rc != EOK)
    907877                        return rc;
    908                
    909                 IPC_SET_ADDR(*answer, ETH_ADDR);
    910                 *answer_count = 1;
    911                
    912                 return EOK;
     878                return measured_strings_reply(address, 1);
    913879        case NET_NIL_BROADCAST_ADDR:
    914                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
     880                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
     881                    &address);
    915882                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;
     883                        return EOK;
     884                return measured_strings_reply(address, 1);
     885        case IPC_M_CONNECT_TO_ME:
     886                return eth_register_message(NIL_GET_PROTO(*call),
     887                    IPC_GET_PHONE(*call));
    938888        }
    939889       
Note: See TracChangeset for help on using the changeset viewer.