Changeset 7a68fe5 in mainline for uspace/srv/net/nil/eth/eth.c


Ignore:
Timestamp:
2011-10-10T06:58:55Z (13 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2ea6392
Parents:
e68c834 (diff), 80099c19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

File:
1 edited

Legend:

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

    re68c834 r7a68fe5  
    11/*
    22 * Copyright (c) 2009 Lukas Mejdrech
     3 * Copyright (c) 2011 Radim Vansa
    34 * All rights reserved.
    45 *
     
    3637 */
    3738
     39#include <assert.h>
    3840#include <async.h>
    3941#include <malloc.h>
     
    5254#include <protocol_map.h>
    5355#include <net/device.h>
    54 #include <netif_remote.h>
    5556#include <net_interface.h>
    5657#include <il_remote.h>
     
    5859#include <packet_client.h>
    5960#include <packet_remote.h>
     61#include <device/nic.h>
    6062#include <nil_skel.h>
    6163#include "eth.h"
     
    167169INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    168170
    169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
     171int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
    170172{
    171173        int index;
     
    196198        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    197199        eth_globals.net_sess = sess;
    198 
    199         eth_globals.broadcast_addr =
    200             measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
    201         if (!eth_globals.broadcast_addr) {
    202                 rc = ENOMEM;
    203                 goto out;
    204         }
     200        memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
     201                        ETH_ADDR);
    205202
    206203        rc = eth_devices_initialize(&eth_globals.devices);
     
    215212                eth_devices_destroy(&eth_globals.devices, free);
    216213        }
     214       
    217215out:
    218216        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    222220}
    223221
    224 /** Process IPC messages from the registered device driver modules in an
    225  * infinite loop.
    226  *
    227  * @param[in]     iid   Message identifier.
    228  * @param[in,out] icall Message parameters.
    229  * @param[in]     arg   Local argument.
    230  *
    231  */
    232 static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    233 {
    234         packet_t *packet;
    235         int rc;
    236 
    237         while (true) {
    238                 switch (IPC_GET_IMETHOD(*icall)) {
    239                 case NET_NIL_DEVICE_STATE:
    240                         nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
    241                             IPC_GET_STATE(*icall));
    242                         async_answer_0(iid, EOK);
    243                         break;
    244                 case NET_NIL_RECEIVED:
    245                         rc = packet_translate_remote(eth_globals.net_sess,
    246                             &packet, IPC_GET_PACKET(*icall));
    247                         if (rc == EOK)
    248                                 rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
    249                                     packet, 0);
    250                        
    251                         async_answer_0(iid, (sysarg_t) rc);
    252                         break;
    253                 default:
    254                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    255                 }
    256                
    257                 iid = async_get_call(icall);
    258         }
    259 }
    260 
    261 /** Registers new device or updates the MTU of an existing one.
    262  *
    263  * Determines the device local hardware address.
    264  *
    265  * @param[in] device_id The new device identifier.
    266  * @param[in] service   The device driver service.
    267  * @param[in] mtu       The device maximum transmission unit.
    268  * @return              EOK on success.
    269  * @return              EEXIST if the device with the different service exists.
    270  * @return              ENOMEM if there is not enough memory left.
    271  * @return              Other error codes as defined for the
    272  *                      net_get_device_conf_req() function.
    273  * @return              Other error codes as defined for the
    274  *                      netif_bind_service() function.
    275  * @return              Other error codes as defined for the
    276  *                      netif_get_addr_req() function.
    277  */
    278 static int eth_device_message(device_id_t device_id, services_t service,
     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,
    279236    size_t mtu)
    280237{
     
    301258        device = eth_devices_find(&eth_globals.devices, device_id);
    302259        if (device) {
    303                 if (device->service != service) {
     260                if (device->handle != handle) {
    304261                        printf("Device %d already exists\n", device->device_id);
    305262                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    340297
    341298        device->device_id = device_id;
    342         device->service = service;
     299        device->handle = handle;
    343300        device->flags = 0;
    344301        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    377334       
    378335        /* Bind the device driver */
    379         device->sess = netif_bind_service(device->service, device->device_id,
    380             SERVICE_ETHERNET, eth_receiver);
     336        device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
     337            IPC_FLAG_BLOCKING);
    381338        if (device->sess == NULL) {
    382339                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    385342        }
    386343       
     344        nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
     345       
    387346        /* Get hardware address */
    388         rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
    389             &device->addr_data);
     347        rc = nic_get_address(device->sess, &device->addr);
    390348        if (rc != EOK) {
    391349                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    399357        if (index < 0) {
    400358                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    401                 free(device->addr);
    402                 free(device->addr_data);
    403359                free(device);
    404360                return index;
    405361        }
    406362       
    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);
     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);
    413367
    414368        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    456410                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    457411                length -= sizeof(eth_fcs_t);
    458         } else if(type <= ETH_MAX_CONTENT) {
     412        } else if (type <= ETH_MAX_CONTENT) {
    459413                /* Translate "LSAP" values */
    460414                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    462416                        /* Raw packet -- discard */
    463417                        return NULL;
    464                 } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
     418                } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
    465419                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    466420                        /*
     
    469423                         */
    470424                        type = ntohs(header->snap.ethertype);
    471                         prefix = sizeof(eth_header_t) +
    472                             sizeof(eth_header_lsap_t) +
     425                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
    473426                            sizeof(eth_header_snap_t);
    474427                } else {
    475428                        /* IEEE 802.3 + 802.2 LSAP */
    476429                        type = lsap_map(header->lsap.dsap);
    477                         prefix = sizeof(eth_header_t) +
    478                             sizeof(eth_header_lsap_t);
     430                        prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
    479431                }
    480432
     
    506458}
    507459
    508 int nil_received_msg_local(device_id_t device_id, packet_t *packet,
    509     services_t target)
     460int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
    510461{
    511462        eth_proto_t *proto;
     
    523474        flags = device->flags;
    524475        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    525        
    526476        fibril_rwlock_read_lock(&eth_globals.protos_lock);
     477       
    527478        do {
    528479                next = pq_detach(packet);
     
    537488                }
    538489                packet = next;
    539         } while(packet);
     490        } while (packet);
    540491
    541492        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    554505 * @return              ENOENT if there is no such device.
    555506 */
    556 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,
    557508    size_t *prefix, size_t *content, size_t *suffix)
    558509{
     
    579530}
    580531
    581 /** Returns the device hardware address.
     532/** Send the device hardware address.
    582533 *
    583534 * @param[in] device_id The device identifier.
    584535 * @param[in] type      Type of the desired address.
    585  * @param[out] address  The device hardware address.
    586536 * @return              EOK on success.
    587537 * @return              EBADMEM if the address parameter is NULL.
    588538 * @return              ENOENT if there no such device.
    589539 */
    590 static int eth_addr_message(device_id_t device_id, eth_addr_type_t type,
    591     measured_string_t **address)
    592 {
    593         eth_device_t *device;
    594 
    595         if (!address)
    596                 return EBADMEM;
    597 
    598         if (type == ETH_BROADCAST_ADDR) {
    599                 *address = eth_globals.broadcast_addr;
    600         } else {
     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 {
    601550                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    602551                device = eth_devices_find(&eth_globals.devices, device_id);
     
    605554                        return ENOENT;
    606555                }
    607                 *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)
    608579                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    609         }
    610        
    611         return (*address) ? EOK : ENOENT;
     580       
     581        return rc;
    612582}
    613583
     
    659629        }
    660630       
    661         printf("%s: Protocol registered (protocol: %d, service: %d)\n",
     631        printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
    662632            NAME, proto->protocol, proto->service);
    663633       
     
    697667        if (i < 0)
    698668                return i;
     669       
    699670        if (i != ETH_ADDR)
    700671                return EINVAL;
     672       
     673        for (i = 0; i < ETH_ADDR; i++) {
     674                if (src[i]) {
     675                        src_addr = src;
     676                        break;
     677                }
     678        }
    701679
    702680        length = packet_get_data_length(packet);
     
    722700                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    723701                src = &header_dix->destination_address[0];
    724         } else if(IS_8023_2_LSAP(flags)) {
     702        } else if (IS_8023_2_LSAP(flags)) {
    725703                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    726704                if (!header_lsap)
     
    735713                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    736714                src = &header_lsap->header.destination_address[0];
    737         } else if(IS_8023_2_SNAP(flags)) {
     715        } else if (IS_8023_2_SNAP(flags)) {
    738716                header = PACKET_PREFIX(packet, eth_header_snap_t);
    739717                if (!header)
     
    746724                header->lsap.ctrl = IEEE_8023_2_UI;
    747725               
    748                 for (i = 0; i < 3; ++ i)
     726                for (i = 0; i < 3; i++)
    749727                        header->snap.protocol[i] = 0;
    750728               
     
    760738                        return ENOMEM;
    761739               
    762                 for (i = 0; i < 7; ++ i)
     740                for (i = 0; i < 7; i++)
    763741                        preamble->preamble[i] = ETH_PREAMBLE;
    764742               
     
    787765 * @return              EINVAL if the service parameter is not known.
    788766 */
    789 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,
    790768    services_t sender)
    791769{
     
    813791        do {
    814792                rc = eth_prepare_packet(device->flags, next,
    815                     (uint8_t *) device->addr->value, ethertype, device->mtu);
     793                    (uint8_t *) &device->addr.address, ethertype, device->mtu);
    816794                if (rc != EOK) {
    817795                        /* Release invalid packet */
     
    825803                        next = pq_next(next);
    826804                }
    827         } while(next);
     805        } while (next);
    828806       
    829807        /* Send packet queue */
    830         if (packet) {
    831                 netif_send_msg(device->sess, device_id, packet,
    832                     SERVICE_ETHERNET);
    833         }
    834 
     808        if (packet)
     809                nic_send_message(device->sess, packet_get_id(packet));
     810       
    835811        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    836812        return EOK;
    837813}
    838814
     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
    839859int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    840860    ipc_call_t *answer, size_t *answer_count)
    841861{
    842         measured_string_t *address;
    843862        packet_t *packet;
    844863        size_t addrlen;
     
    861880        case NET_NIL_DEVICE:
    862881                return eth_device_message(IPC_GET_DEVICE(*call),
    863                     IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
     882                    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
    864883        case NET_NIL_SEND:
    865884                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    867886                if (rc != EOK)
    868887                        return rc;
     888               
    869889                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    870890                    IPC_GET_SERVICE(*call));
     
    874894                if (rc != EOK)
    875895                        return rc;
     896               
    876897                IPC_SET_ADDR(*answer, addrlen);
    877898                IPC_SET_PREFIX(*answer, prefix);
     
    879900                IPC_SET_SUFFIX(*answer, suffix);
    880901                *answer_count = 4;
     902               
    881903                return EOK;
    882904        case NET_NIL_ADDR:
    883                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
    884                     &address);
     905                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
    885906                if (rc != EOK)
    886907                        return rc;
    887                 return measured_strings_reply(address, 1);
     908               
     909                IPC_SET_ADDR(*answer, ETH_ADDR);
     910                *answer_count = 1;
     911               
     912                return EOK;
    888913        case NET_NIL_BROADCAST_ADDR:
    889                 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
    890                     &address);
     914                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
    891915                if (rc != EOK)
    892                         return EOK;
    893                 return measured_strings_reply(address, 1);
     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;
    894938        }
    895939       
Note: See TracChangeset for help on using the changeset viewer.