Ignore:
File:
1 edited

Legend:

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

    r9cd8165 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>
     
    4846#include <ipc/net.h>
    4947#include <ipc/services.h>
    50 #include <loc.h>
    5148#include <net/modules.h>
    5249#include <net_checksum.h>
     
    5552#include <protocol_map.h>
    5653#include <net/device.h>
     54#include <netif_remote.h>
    5755#include <net_interface.h>
    5856#include <il_remote.h>
     
    6058#include <packet_client.h>
    6159#include <packet_remote.h>
    62 #include <device/nic.h>
    6360#include <nil_skel.h>
    6461#include "eth.h"
     
    170167INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    171168
    172 static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall,
    173     void *arg);
    174 
    175 static int eth_device_state(eth_device_t *device, sysarg_t state)
     169int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
    176170{
    177171        int index;
     
    183177                proto = eth_protos_get_index(&eth_globals.protos, index);
    184178                if ((proto) && (proto->sess)) {
    185                         il_device_state_msg(proto->sess, device->device_id,
    186                             state, proto->service);
     179                        il_device_state_msg(proto->sess, device_id, state,
     180                            proto->service);
    187181                }
    188182        }
     
    201195        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    202196        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    203        
    204197        eth_globals.net_sess = sess;
    205         memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
    206                         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        }
    207205
    208206        rc = eth_devices_initialize(&eth_globals.devices);
     
    217215                eth_devices_destroy(&eth_globals.devices, free);
    218216        }
    219        
    220217out:
    221218        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    225222}
    226223
    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  */
    240 static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
     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,
    241279    size_t mtu)
    242280{
     
    263301        device = eth_devices_find(&eth_globals.devices, device_id);
    264302        if (device) {
    265                 if (device->sid != sid) {
     303                if (device->service != service) {
    266304                        printf("Device %d already exists\n", device->device_id);
    267305                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    302340
    303341        device->device_id = device_id;
    304         device->sid = sid;
     342        device->service = service;
    305343        device->flags = 0;
    306344        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    339377       
    340378        /* Bind the device driver */
    341         device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
    342             IPC_FLAG_BLOCKING);
     379        device->sess = netif_bind_service(device->service, device->device_id,
     380            SERVICE_ETHERNET, eth_receiver);
    343381        if (device->sess == NULL) {
    344382                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    347385        }
    348386       
    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        
    357387        /* Get hardware address */
    358         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);
    359390        if (rc != EOK) {
    360391                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    368399        if (index < 0) {
    369400                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     401                free(device->addr);
     402                free(device->addr_data);
    370403                free(device);
    371404                return index;
    372405        }
    373406       
    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);
     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);
    378413
    379414        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    421456                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    422457                length -= sizeof(eth_fcs_t);
    423         } else if (type <= ETH_MAX_CONTENT) {
     458        } else if(type <= ETH_MAX_CONTENT) {
    424459                /* Translate "LSAP" values */
    425460                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    427462                        /* Raw packet -- discard */
    428463                        return NULL;
    429                 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
     464                } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
    430465                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    431466                        /*
     
    434469                         */
    435470                        type = ntohs(header->snap.ethertype);
    436                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
     471                        prefix = sizeof(eth_header_t) +
     472                            sizeof(eth_header_lsap_t) +
    437473                            sizeof(eth_header_snap_t);
    438474                } else {
    439475                        /* IEEE 802.3 + 802.2 LSAP */
    440476                        type = lsap_map(header->lsap.dsap);
    441                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
     477                        prefix = sizeof(eth_header_t) +
     478                            sizeof(eth_header_lsap_t);
    442479                }
    443480
     
    469506}
    470507
    471 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)
    472510{
    473511        eth_proto_t *proto;
     
    485523        flags = device->flags;
    486524        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
     525       
    487526        fibril_rwlock_read_lock(&eth_globals.protos_lock);
    488        
    489527        do {
    490528                next = pq_detach(packet);
     
    499537                }
    500538                packet = next;
    501         } while (packet);
     539        } while(packet);
    502540
    503541        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    516554 * @return              ENOENT if there is no such device.
    517555 */
    518 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,
    519557    size_t *prefix, size_t *content, size_t *suffix)
    520558{
     
    541579}
    542580
    543 /** Send the device hardware address.
     581/** Returns the device hardware address.
    544582 *
    545583 * @param[in] device_id The device identifier.
    546584 * @param[in] type      Type of the desired address.
     585 * @param[out] address  The device hardware address.
    547586 * @return              EOK on success.
    548587 * @return              EBADMEM if the address parameter is NULL.
    549588 * @return              ENOENT if there no such device.
    550589 */
    551 static 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 {
     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 {
    561601                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    562602                device = eth_devices_find(&eth_globals.devices, device_id);
     
    565605                        return ENOENT;
    566606                }
    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        
    587 end:
    588        
    589         if (type == ETH_LOCAL_ADDR)
     607                *address = device->addr;
    590608                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    591        
    592         return rc;
     609        }
     610       
     611        return (*address) ? EOK : ENOENT;
    593612}
    594613
     
    640659        }
    641660       
    642         printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
     661        printf("%s: Protocol registered (protocol: %d, service: %d)\n",
    643662            NAME, proto->protocol, proto->service);
    644663       
     
    678697        if (i < 0)
    679698                return i;
    680        
    681699        if (i != ETH_ADDR)
    682700                return EINVAL;
    683        
    684         for (i = 0; i < ETH_ADDR; i++) {
    685                 if (src[i]) {
    686                         src_addr = src;
    687                         break;
    688                 }
    689         }
    690701
    691702        length = packet_get_data_length(packet);
     
    711722                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    712723                src = &header_dix->destination_address[0];
    713         } else if (IS_8023_2_LSAP(flags)) {
     724        } else if(IS_8023_2_LSAP(flags)) {
    714725                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    715726                if (!header_lsap)
     
    724735                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    725736                src = &header_lsap->header.destination_address[0];
    726         } else if (IS_8023_2_SNAP(flags)) {
     737        } else if(IS_8023_2_SNAP(flags)) {
    727738                header = PACKET_PREFIX(packet, eth_header_snap_t);
    728739                if (!header)
     
    735746                header->lsap.ctrl = IEEE_8023_2_UI;
    736747               
    737                 for (i = 0; i < 3; i++)
     748                for (i = 0; i < 3; ++ i)
    738749                        header->snap.protocol[i] = 0;
    739750               
     
    749760                        return ENOMEM;
    750761               
    751                 for (i = 0; i < 7; i++)
     762                for (i = 0; i < 7; ++ i)
    752763                        preamble->preamble[i] = ETH_PREAMBLE;
    753764               
     
    776787 * @return              EINVAL if the service parameter is not known.
    777788 */
    778 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,
    779790    services_t sender)
    780791{
     
    802813        do {
    803814                rc = eth_prepare_packet(device->flags, next,
    804                     (uint8_t *) &device->addr.address, ethertype, device->mtu);
     815                    (uint8_t *) device->addr->value, ethertype, device->mtu);
    805816                if (rc != EOK) {
    806817                        /* Release invalid packet */
     
    812823                        next = tmp;
    813824                } else {
    814                         nic_send_frame(device->sess, packet_get_data(next),
    815                             packet_get_data_length(next));
    816825                        next = pq_next(next);
    817826                }
    818         } while (next);
    819        
    820         pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
    821        
     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
    822835        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    823836        return EOK;
    824837}
    825838
    826 static 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 
    849 static 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 
    889839int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    890840    ipc_call_t *answer, size_t *answer_count)
    891841{
     842        measured_string_t *address;
    892843        packet_t *packet;
    893844        size_t addrlen;
     
    910861        case NET_NIL_DEVICE:
    911862                return eth_device_message(IPC_GET_DEVICE(*call),
    912                     IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
     863                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    913864        case NET_NIL_SEND:
    914865                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    916867                if (rc != EOK)
    917868                        return rc;
    918                
    919869                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    920870                    IPC_GET_SERVICE(*call));
     
    924874                if (rc != EOK)
    925875                        return rc;
    926                
    927876                IPC_SET_ADDR(*answer, addrlen);
    928877                IPC_SET_PREFIX(*answer, prefix);
     
    930879                IPC_SET_SUFFIX(*answer, suffix);
    931880                *answer_count = 4;
    932                
    933881                return EOK;
    934882        case NET_NIL_ADDR:
    935                 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);
    936885                if (rc != EOK)
    937886                        return rc;
    938                
    939                 IPC_SET_ADDR(*answer, ETH_ADDR);
    940                 *answer_count = 1;
    941                
    942                 return EOK;
     887                return measured_strings_reply(address, 1);
    943888        case NET_NIL_BROADCAST_ADDR:
    944                 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);
    945891                if (rc != EOK)
    946                         return rc;
    947                
    948                 IPC_SET_ADDR(*answer, ETH_ADDR);
    949                 *answer_count = 1;
    950                
    951                 return EOK;
     892                        return EOK;
     893                return measured_strings_reply(address, 1);
    952894        }
    953895       
    954896        return ENOTSUP;
    955 }
    956 
    957 static 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         }
    988897}
    989898
Note: See TracChangeset for help on using the changeset viewer.