Ignore:
File:
1 edited

Legend:

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

    r4ee7364 r6b82009  
    11/*
    22 * Copyright (c) 2009 Lukas Mejdrech
    3  * Copyright (c) 2011 Radim Vansa
    43 * All rights reserved.
    54 *
     
    3736 */
    3837
    39 #include <assert.h>
    4038#include <async.h>
    4139#include <malloc.h>
     
    5452#include <protocol_map.h>
    5553#include <net/device.h>
     54#include <netif_remote.h>
    5655#include <net_interface.h>
    5756#include <il_remote.h>
     
    5958#include <packet_client.h>
    6059#include <packet_remote.h>
    61 #include <device/nic.h>
    6260#include <nil_skel.h>
    6361#include "eth.h"
     
    169167INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
    170168
    171 int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state)
     169int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
    172170{
    173171        int index;
     
    197195        fibril_rwlock_write_lock(&eth_globals.devices_lock);
    198196        fibril_rwlock_write_lock(&eth_globals.protos_lock);
    199        
    200197        eth_globals.net_sess = sess;
    201         memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
    202                         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        }
    203205
    204206        rc = eth_devices_initialize(&eth_globals.devices);
     
    213215                eth_devices_destroy(&eth_globals.devices, free);
    214216        }
    215        
    216217out:
    217218        fibril_rwlock_write_unlock(&eth_globals.protos_lock);
     
    221222}
    222223
    223 /** Register new device or updates the MTU of an existing one.
    224  *
    225  * Determine the device local hardware address.
    226  *
    227  * @param[in] device_id New device identifier.
    228  * @param[in] handle    Device driver handle.
    229  * @param[in] mtu       Device maximum transmission unit.
    230  *
    231  * @return EOK on success.
    232  * @return EEXIST if the device with the different service exists.
    233  * @return ENOMEM if there is not enough memory left.
    234  *
    235  */
    236 static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle,
     224/** Process IPC messages from the registered device driver modules in an
     225 * infinite loop.
     226 *
     227 * @param[in]     iid   Message identifier.
     228 * @param[in,out] icall Message parameters.
     229 * @param[in]     arg   Local argument.
     230 *
     231 */
     232static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     233{
     234        packet_t *packet;
     235        int rc;
     236
     237        while (true) {
     238                switch (IPC_GET_IMETHOD(*icall)) {
     239                case NET_NIL_DEVICE_STATE:
     240                        nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
     241                            IPC_GET_STATE(*icall));
     242                        async_answer_0(iid, EOK);
     243                        break;
     244                case NET_NIL_RECEIVED:
     245                        rc = packet_translate_remote(eth_globals.net_sess,
     246                            &packet, IPC_GET_PACKET(*icall));
     247                        if (rc == EOK)
     248                                rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
     249                                    packet, 0);
     250                       
     251                        async_answer_0(iid, (sysarg_t) rc);
     252                        break;
     253                default:
     254                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     255                }
     256               
     257                iid = async_get_call(icall);
     258        }
     259}
     260
     261/** Registers new device or updates the MTU of an existing one.
     262 *
     263 * Determines the device local hardware address.
     264 *
     265 * @param[in] device_id The new device identifier.
     266 * @param[in] service   The device driver service.
     267 * @param[in] mtu       The device maximum transmission unit.
     268 * @return              EOK on success.
     269 * @return              EEXIST if the device with the different service exists.
     270 * @return              ENOMEM if there is not enough memory left.
     271 * @return              Other error codes as defined for the
     272 *                      net_get_device_conf_req() function.
     273 * @return              Other error codes as defined for the
     274 *                      netif_bind_service() function.
     275 * @return              Other error codes as defined for the
     276 *                      netif_get_addr_req() function.
     277 */
     278static int eth_device_message(device_id_t device_id, services_t service,
    237279    size_t mtu)
    238280{
     
    259301        device = eth_devices_find(&eth_globals.devices, device_id);
    260302        if (device) {
    261                 if (device->handle != handle) {
     303                if (device->service != service) {
    262304                        printf("Device %d already exists\n", device->device_id);
    263305                        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    298340
    299341        device->device_id = device_id;
    300         device->handle = handle;
     342        device->service = service;
    301343        device->flags = 0;
    302344        if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
     
    335377       
    336378        /* Bind the device driver */
    337         device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
    338             IPC_FLAG_BLOCKING);
     379        device->sess = netif_bind_service(device->service, device->device_id,
     380            SERVICE_ETHERNET, eth_receiver);
    339381        if (device->sess == NULL) {
    340382                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    343385        }
    344386       
    345         nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);
    346        
    347387        /* Get hardware address */
    348         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);
    349390        if (rc != EOK) {
    350391                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    358399        if (index < 0) {
    359400                fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     401                free(device->addr);
     402                free(device->addr_data);
    360403                free(device);
    361404                return index;
    362405        }
    363406       
    364         printf("%s: Device registered (id: %d, handle: %zu: mtu: %zu, "
    365             "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
    366             device->device_id, device->handle, device->mtu,
    367             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);
    368413
    369414        fibril_rwlock_write_unlock(&eth_globals.devices_lock);
     
    411456                fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
    412457                length -= sizeof(eth_fcs_t);
    413         } else if (type <= ETH_MAX_CONTENT) {
     458        } else if(type <= ETH_MAX_CONTENT) {
    414459                /* Translate "LSAP" values */
    415460                if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
     
    417462                        /* Raw packet -- discard */
    418463                        return NULL;
    419                 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
     464                } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
    420465                    (header->lsap.ssap == ETH_LSAP_SNAP)) {
    421466                        /*
     
    424469                         */
    425470                        type = ntohs(header->snap.ethertype);
    426                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
     471                        prefix = sizeof(eth_header_t) +
     472                            sizeof(eth_header_lsap_t) +
    427473                            sizeof(eth_header_snap_t);
    428474                } else {
    429475                        /* IEEE 802.3 + 802.2 LSAP */
    430476                        type = lsap_map(header->lsap.dsap);
    431                         prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
     477                        prefix = sizeof(eth_header_t) +
     478                            sizeof(eth_header_lsap_t);
    432479                }
    433480
     
    459506}
    460507
    461 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)
    462510{
    463511        eth_proto_t *proto;
     
    475523        flags = device->flags;
    476524        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
     525       
    477526        fibril_rwlock_read_lock(&eth_globals.protos_lock);
    478        
    479527        do {
    480528                next = pq_detach(packet);
     
    489537                }
    490538                packet = next;
    491         } while (packet);
     539        } while(packet);
    492540
    493541        fibril_rwlock_read_unlock(&eth_globals.protos_lock);
     
    506554 * @return              ENOENT if there is no such device.
    507555 */
    508 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,
    509557    size_t *prefix, size_t *content, size_t *suffix)
    510558{
     
    531579}
    532580
    533 /** Send the device hardware address.
     581/** Returns the device hardware address.
    534582 *
    535583 * @param[in] device_id The device identifier.
    536584 * @param[in] type      Type of the desired address.
     585 * @param[out] address  The device hardware address.
    537586 * @return              EOK on success.
    538587 * @return              EBADMEM if the address parameter is NULL.
    539588 * @return              ENOENT if there no such device.
    540589 */
    541 static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
    542 {
    543         eth_device_t *device = NULL;
    544         uint8_t *address;
    545         size_t max_len;
    546         ipc_callid_t callid;
    547        
    548         if (type == ETH_BROADCAST_ADDR)
    549                 address = eth_globals.broadcast_addr;
    550         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 {
    551601                fibril_rwlock_read_lock(&eth_globals.devices_lock);
    552602                device = eth_devices_find(&eth_globals.devices, device_id);
     
    555605                        return ENOENT;
    556606                }
    557                
    558                 address = (uint8_t *) &device->addr.address;
    559         }
    560        
    561         int rc = EOK;
    562         if (!async_data_read_receive(&callid, &max_len)) {
    563                 rc = EREFUSED;
    564                 goto end;
    565         }
    566        
    567         if (max_len < ETH_ADDR) {
    568                 async_data_read_finalize(callid, NULL, 0);
    569                 rc = ELIMIT;
    570                 goto end;
    571         }
    572        
    573         rc = async_data_read_finalize(callid, address, ETH_ADDR);
    574         if (rc != EOK)
    575                 goto end;
    576        
    577 end:
    578        
    579         if (type == ETH_LOCAL_ADDR)
     607                *address = device->addr;
    580608                fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    581        
    582         return rc;
     609        }
     610       
     611        return (*address) ? EOK : ENOENT;
    583612}
    584613
     
    630659        }
    631660       
    632         printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
     661        printf("%s: Protocol registered (protocol: %d, service: %d)\n",
    633662            NAME, proto->protocol, proto->service);
    634663       
     
    668697        if (i < 0)
    669698                return i;
    670        
    671699        if (i != ETH_ADDR)
    672700                return EINVAL;
    673        
    674         for (i = 0; i < ETH_ADDR; i++) {
    675                 if (src[i]) {
    676                         src_addr = src;
    677                         break;
    678                 }
    679         }
    680701
    681702        length = packet_get_data_length(packet);
     
    701722                memcpy(header_dix->destination_address, dest, ETH_ADDR);
    702723                src = &header_dix->destination_address[0];
    703         } else if (IS_8023_2_LSAP(flags)) {
     724        } else if(IS_8023_2_LSAP(flags)) {
    704725                header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
    705726                if (!header_lsap)
     
    714735                memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
    715736                src = &header_lsap->header.destination_address[0];
    716         } else if (IS_8023_2_SNAP(flags)) {
     737        } else if(IS_8023_2_SNAP(flags)) {
    717738                header = PACKET_PREFIX(packet, eth_header_snap_t);
    718739                if (!header)
     
    725746                header->lsap.ctrl = IEEE_8023_2_UI;
    726747               
    727                 for (i = 0; i < 3; i++)
     748                for (i = 0; i < 3; ++ i)
    728749                        header->snap.protocol[i] = 0;
    729750               
     
    739760                        return ENOMEM;
    740761               
    741                 for (i = 0; i < 7; i++)
     762                for (i = 0; i < 7; ++ i)
    742763                        preamble->preamble[i] = ETH_PREAMBLE;
    743764               
     
    766787 * @return              EINVAL if the service parameter is not known.
    767788 */
    768 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,
    769790    services_t sender)
    770791{
     
    792813        do {
    793814                rc = eth_prepare_packet(device->flags, next,
    794                     (uint8_t *) &device->addr.address, ethertype, device->mtu);
     815                    (uint8_t *) device->addr->value, ethertype, device->mtu);
    795816                if (rc != EOK) {
    796817                        /* Release invalid packet */
     
    804825                        next = pq_next(next);
    805826                }
    806         } while (next);
     827        } while(next);
    807828       
    808829        /* Send packet queue */
    809         if (packet)
    810                 nic_send_message(device->sess, packet_get_id(packet));
    811        
     830        if (packet) {
     831                netif_send_msg(device->sess, device_id, packet,
     832                    SERVICE_ETHERNET);
     833        }
     834
    812835        fibril_rwlock_read_unlock(&eth_globals.devices_lock);
    813836        return EOK;
    814837}
    815838
    816 static int eth_addr_changed(nic_device_id_t device_id)
    817 {
    818         nic_address_t address;
    819         size_t length;
    820         ipc_callid_t data_callid;
    821         if (!async_data_write_receive(&data_callid, &length)) {
    822                 async_answer_0(data_callid, EINVAL);
    823                 return EINVAL;
    824         }
    825         if (length > sizeof (nic_address_t)) {
    826                 async_answer_0(data_callid, ELIMIT);
    827                 return ELIMIT;
    828         }
    829         if (async_data_write_finalize(data_callid, &address, length) != EOK) {
    830                 return EINVAL;
    831         }
    832 
    833         fibril_rwlock_write_lock(&eth_globals.devices_lock);
    834         /* An existing device? */
    835         eth_device_t *device = eth_devices_find(&eth_globals.devices, device_id);
    836         if (device) {
    837                 printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
    838                         device_id, ARGSMAC(device->addr.address), ARGSMAC(address.address));
    839                 memcpy(&device->addr, &address, sizeof (nic_address_t));
    840                 fibril_rwlock_write_unlock(&eth_globals.devices_lock);
    841 
    842                 /* Notify all upper layer modules */
    843                 fibril_rwlock_read_lock(&eth_globals.protos_lock);
    844                 int index;
    845                 for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
    846                         eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
    847                         if (proto->sess != NULL) {
    848                                 il_addr_changed_msg(proto->sess, device->device_id,
    849                                                 ETH_ADDR, address.address);
    850                         }
    851                 }
    852 
    853                 fibril_rwlock_read_unlock(&eth_globals.protos_lock);
    854                 return EOK;
    855         } else {
    856                 return ENOENT;
    857         }
    858 }
    859 
    860839int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
    861840    ipc_call_t *answer, size_t *answer_count)
    862841{
     842        measured_string_t *address;
    863843        packet_t *packet;
    864844        size_t addrlen;
     
    881861        case NET_NIL_DEVICE:
    882862                return eth_device_message(IPC_GET_DEVICE(*call),
    883                     IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
     863                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    884864        case NET_NIL_SEND:
    885865                rc = packet_translate_remote(eth_globals.net_sess, &packet,
     
    887867                if (rc != EOK)
    888868                        return rc;
    889                
    890869                return eth_send_message(IPC_GET_DEVICE(*call), packet,
    891870                    IPC_GET_SERVICE(*call));
     
    895874                if (rc != EOK)
    896875                        return rc;
    897                
    898876                IPC_SET_ADDR(*answer, addrlen);
    899877                IPC_SET_PREFIX(*answer, prefix);
     
    901879                IPC_SET_SUFFIX(*answer, suffix);
    902880                *answer_count = 4;
    903                
    904881                return EOK;
    905882        case NET_NIL_ADDR:
    906                 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);
    907885                if (rc != EOK)
    908886                        return rc;
    909                
    910                 IPC_SET_ADDR(*answer, ETH_ADDR);
    911                 *answer_count = 1;
    912                
    913                 return EOK;
     887                return measured_strings_reply(address, 1);
    914888        case NET_NIL_BROADCAST_ADDR:
    915                 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);
    916891                if (rc != EOK)
    917                         return rc;
    918                
    919                 IPC_SET_ADDR(*answer, ETH_ADDR);
    920                 *answer_count = 1;
    921                
    922                 return EOK;
    923         case NET_NIL_DEVICE_STATE:
    924                 nil_device_state_msg_local(IPC_GET_DEVICE(*call), IPC_GET_STATE(*call));
    925                 async_answer_0(callid, EOK);
    926                 return EOK;
    927         case NET_NIL_RECEIVED:
    928                 rc = packet_translate_remote(eth_globals.net_sess, &packet,
    929                     IPC_GET_ARG2(*call));
    930                 if (rc == EOK)
    931                         rc = nil_received_msg_local(IPC_GET_ARG1(*call), packet);
    932                
    933                 async_answer_0(callid, (sysarg_t) rc);
    934                 return rc;
    935         case NET_NIL_ADDR_CHANGED:
    936                 rc = eth_addr_changed(IPC_GET_DEVICE(*call));
    937                 async_answer_0(callid, (sysarg_t) rc);
    938                 return rc;
     892                        return EOK;
     893                return measured_strings_reply(address, 1);
    939894        }
    940895       
Note: See TracChangeset for help on using the changeset viewer.