Ignore:
File:
1 edited

Legend:

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

    r28a3e74 r00d7e1b  
    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>
    61 
    6263#include "eth.h"
    6364
     
    168169INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    169170
    170 int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
     171int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
    171172{
    172173        int index;
     
    177178            index--) {
    178179                proto = eth_protos_get_index(&eth_globals.protos, index);
    179                 if (proto && proto->phone) {
    180                         il_device_state_msg(proto->phone, device_id, state,
     180                if ((proto) && (proto->sess)) {
     181                        il_device_state_msg(proto->sess, device_id, state,
    181182                            proto->service);
    182183                }
     
    187188}
    188189
    189 int nil_initialize(int net_phone)
     190int nil_initialize(async_sess_t *sess)
    190191{
    191192        int rc;
     
    196197        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    197198        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    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         }
     199        eth_globals.net_sess = sess;
     200        memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
     201                        ETH_ADDR);
    206202
    207203        rc = eth_devices_initialize(&eth_globals.devices);
     
    216212                eth_devices_destroy(&eth_globals.devices, free);
    217213        }
     214       
    218215out:
    219216        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    223220}
    224221
    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  */
    231 static 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  */
    277 static int eth_device_message(device_id_t device_id, services_t service,
     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 */
     235static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
    278236    size_t mtu)
    279237{
     
    300258        device = eth_devices_find(&eth_globals.devices, device_id);
    301259        if (device) {
    302                 if (device->service != service) {
     260                if (device->handle != handle) {
    303261                        printf("Device %d already exists\n", device->device_id);
    304262                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    322280                        proto = eth_protos_get_index(&eth_globals.protos,
    323281                            index);
    324                         if (proto->phone) {
    325                                 il_mtu_changed_msg(proto->phone,
     282                        if (proto->sess) {
     283                                il_mtu_changed_msg(proto->sess,
    326284                                    device->device_id, device->mtu,
    327285                                    proto->service);
     
    339297
    340298        device->device_id = device_id;
    341         device->service = service;
     299        device->handle = handle;
    342300        device->flags = 0;
    343301        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    347305
    348306        configuration = &names[0];
    349         rc = net_get_device_conf_req(eth_globals.net_phone, device->device_id,
     307        rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
    350308            &configuration, count, &data);
    351309        if (rc != EOK) {
     
    376334       
    377335        /* Bind the device driver */
    378         device->phone = netif_bind_service(device->service, device->device_id,
    379             SERVICE_ETHERNET, eth_receiver);
    380         if (device->phone < 0) {
     336        device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
     337            IPC_FLAG_BLOCKING);
     338        if (device->sess == NULL) {
    381339                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    382340                free(device);
    383                 return device->phone;
    384         }
     341                return ENOENT;
     342        }
     343       
     344        nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
    385345       
    386346        /* Get hardware address */
    387         rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
    388             &device->addr_data);
     347        rc = nic_get_address(device->sess, &device->addr);
    389348        if (rc != EOK) {
    390349                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    398357        if (index < 0) {
    399358                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    400                 free(device->addr);
    401                 free(device->addr_data);
    402359                free(device);
    403360                return index;
    404361        }
    405362       
    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);
     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);
    412367
    413368        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    455410                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    456411                length -= sizeof(eth_fcs_t);
    457         } else if(type <= ETH_MAX_CONTENT) {
     412        } else if (type <= ETH_MAX_CONTENT) {
    458413                /* Translate "LSAP" values */
    459414                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    461416                        /* Raw packet -- discard */
    462417                        return NULL;
    463                 } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
     418                } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
    464419                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    465420                        /*
     
    468423                         */
    469424                        type = ntohs(header->snap.ethertype);
    470                         prefix = sizeof(eth_header_t) +
    471                             sizeof(eth_header_lsap_t) +
     425                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
    472426                            sizeof(eth_header_snap_t);
    473427                } else {
    474428                        /* IEEE 802.3 + 802.2 LSAP */
    475429                        type = lsap_map(header->lsap.dsap);
    476                         prefix = sizeof(eth_header_t) +
    477                             sizeof(eth_header_lsap_t);
     430                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
    478431                }
    479432
     
    505458}
    506459
    507 int nil_received_msg_local(int nil_phone, device_id_t device_id,
    508     packet_t *packet, services_t target)
     460int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
    509461{
    510462        eth_proto_t *proto;
     
    522474        flags = device->flags;
    523475        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    524        
    525476        fibril_rwlock_read_lock(&eth_globals.protos_lock);
     477       
    526478        do {
    527479                next = pq_detach(packet);
    528480                proto = eth_process_packet(flags, packet);
    529481                if (proto) {
    530                         il_received_msg(proto->phone, device_id, packet,
     482                        il_received_msg(proto->sess, device_id, packet,
    531483                            proto->service);
    532484                } else {
    533485                        /* Drop invalid/unknown */
    534                         pq_release_remote(eth_globals.net_phone,
     486                        pq_release_remote(eth_globals.net_sess,
    535487                            packet_get_id(packet));
    536488                }
    537489                packet = next;
    538         } while(packet);
     490        } while (packet);
    539491
    540492        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    553505 * @return              ENOENT if there is no such device.
    554506 */
    555 static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
     507static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
    556508    size_t *prefix, size_t *content, size_t *suffix)
    557509{
     
    578530}
    579531
    580 /** Returns the device hardware address.
     532/** Send the device hardware address.
    581533 *
    582534 * @param[in] device_id The device identifier.
    583535 * @param[in] type      Type of the desired address.
    584  * @param[out] address  The device hardware address.
    585536 * @return              EOK on success.
    586537 * @return              EBADMEM if the address parameter is NULL.
    587538 * @return              ENOENT if there no such device.
    588539 */
    589 static 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 {
     540static 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 {
    600550                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    601551                device = eth_devices_find(&eth_globals.devices, device_id);
     
    604554                        return ENOENT;
    605555                }
    606                 *address = device->addr;
     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       
     576end:
     577       
     578        if (type == ETH_LOCAL_ADDR)
    607579                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    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  */
    623 static int eth_register_message(services_t service, int phone)
     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 */
     596static int eth_register_message(services_t service, async_sess_t *sess)
    624597{
    625598        eth_proto_t *proto;
     
    634607        proto = eth_protos_find(&eth_globals.protos, protocol);
    635608        if (proto) {
    636                 proto->phone = phone;
     609                proto->sess = sess;
    637610                fibril_rwlock_write_unlock(&eth_globals.protos_lock);
    638611                return EOK;
     
    646619                proto->service = service;
    647620                proto->protocol = protocol;
    648                 proto->phone = phone;
     621                proto->sess = sess;
    649622
    650623                index = eth_protos_add(&eth_globals.protos, protocol, proto);
     
    656629        }
    657630       
    658         printf("%s: Protocol registered (protocol: %d, service: %d, phone: "
    659             "%d)\n", NAME, proto->protocol, proto->service, proto->phone);
     631        printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
     632            NAME, proto->protocol, proto->service);
    660633       
    661634        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    694667        if (i < 0)
    695668                return i;
     669       
    696670        if (i != ETH_ADDR)
    697671                return EINVAL;
     672       
     673        for (i = 0; i < ETH_ADDR; i++) {
     674                if (src[i]) {
     675                        src_addr = src;
     676                        break;
     677                }
     678        }
    698679
    699680        length = packet_get_data_length(packet);
     
    719700                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    720701                src = &header_dix->destination_address[0];
    721         } else if(IS_8023_2_LSAP(flags)) {
     702        } else if (IS_8023_2_LSAP(flags)) {
    722703                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    723704                if (!header_lsap)
     
    732713                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    733714                src = &header_lsap->header.destination_address[0];
    734         } else if(IS_8023_2_SNAP(flags)) {
     715        } else if (IS_8023_2_SNAP(flags)) {
    735716                header = PACKET_PREFIX(packet, eth_header_snap_t);
    736717                if (!header)
     
    743724                header->lsap.ctrl = IEEE_8023_2_UI;
    744725               
    745                 for (i = 0; i < 3; ++ i)
     726                for (i = 0; i < 3; i++)
    746727                        header->snap.protocol[i] = 0;
    747728               
     
    757738                        return ENOMEM;
    758739               
    759                 for (i = 0; i < 7; ++ i)
     740                for (i = 0; i < 7; i++)
    760741                        preamble->preamble[i] = ETH_PREAMBLE;
    761742               
     
    784765 * @return              EINVAL if the service parameter is not known.
    785766 */
    786 static int eth_send_message(device_id_t device_id, packet_t *packet,
     767static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
    787768    services_t sender)
    788769{
     
    795776        ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
    796777        if (!ethertype) {
    797                 pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
     778                pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
    798779                return EINVAL;
    799780        }
     
    810791        do {
    811792                rc = eth_prepare_packet(device->flags, next,
    812                     (uint8_t *) device->addr->value, ethertype, device->mtu);
     793                    (uint8_t *) &device->addr.address, ethertype, device->mtu);
    813794                if (rc != EOK) {
    814795                        /* Release invalid packet */
     
    816797                        if (next == packet)
    817798                                packet = tmp;
    818                         pq_release_remote(eth_globals.net_phone,
     799                        pq_release_remote(eth_globals.net_sess,
    819800                            packet_get_id(next));
    820801                        next = tmp;
     
    822803                        next = pq_next(next);
    823804                }
    824         } while(next);
     805        } while (next);
    825806       
    826807        /* Send packet queue */
    827         if (packet) {
    828                 netif_send_msg(device->phone, device_id, packet,
    829                     SERVICE_ETHERNET);
    830         }
    831 
     808        if (packet)
     809                nic_send_message(device->sess, packet_get_id(packet));
     810       
    832811        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    833812        return EOK;
    834813}
    835814
     815static 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
    836859int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    837860    ipc_call_t *answer, size_t *answer_count)
    838861{
    839         measured_string_t *address;
    840862        packet_t *packet;
    841863        size_t addrlen;
     
    846868       
    847869        *answer_count = 0;
     870       
     871        if (!IPC_GET_IMETHOD(*call))
     872                return EOK;
     873       
     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       
    848879        switch (IPC_GET_IMETHOD(*call)) {
    849         case IPC_M_PHONE_HUNGUP:
    850                 return EOK;
    851        
    852880        case NET_NIL_DEVICE:
    853881                return eth_device_message(IPC_GET_DEVICE(*call),
    854                     IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
     882                    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
    855883        case NET_NIL_SEND:
    856                 rc = packet_translate_remote(eth_globals.net_phone, &packet,
     884                rc = packet_translate_remote(eth_globals.net_sess, &packet,
    857885                    IPC_GET_PACKET(*call));
    858886                if (rc != EOK)
    859887                        return rc;
     888               
    860889                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    861890                    IPC_GET_SERVICE(*call));
     
    865894                if (rc != EOK)
    866895                        return rc;
     896               
    867897                IPC_SET_ADDR(*answer, addrlen);
    868898                IPC_SET_PREFIX(*answer, prefix);
     
    870900                IPC_SET_SUFFIX(*answer, suffix);
    871901                *answer_count = 4;
     902               
    872903                return EOK;
    873904        case NET_NIL_ADDR:
    874                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
    875                     &address);
     905                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
    876906                if (rc != EOK)
    877907                        return rc;
    878                 return measured_strings_reply(address, 1);
     908               
     909                IPC_SET_ADDR(*answer, ETH_ADDR);
     910                *answer_count = 1;
     911               
     912                return EOK;
    879913        case NET_NIL_BROADCAST_ADDR:
    880                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
    881                     &address);
     914                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
    882915                if (rc != EOK)
    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));
     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;
    888938        }
    889939       
Note: See TracChangeset for help on using the changeset viewer.