Changes in uspace/srv/net/nil/eth/eth.c [9cd8165:6b82009] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/nil/eth/eth.c
r9cd8165 r6b82009 1 1 /* 2 2 * Copyright (c) 2009 Lukas Mejdrech 3 * Copyright (c) 2011 Radim Vansa4 3 * All rights reserved. 5 4 * … … 37 36 */ 38 37 39 #include <assert.h>40 38 #include <async.h> 41 39 #include <malloc.h> … … 48 46 #include <ipc/net.h> 49 47 #include <ipc/services.h> 50 #include <loc.h>51 48 #include <net/modules.h> 52 49 #include <net_checksum.h> … … 55 52 #include <protocol_map.h> 56 53 #include <net/device.h> 54 #include <netif_remote.h> 57 55 #include <net_interface.h> 58 56 #include <il_remote.h> … … 60 58 #include <packet_client.h> 61 59 #include <packet_remote.h> 62 #include <device/nic.h>63 60 #include <nil_skel.h> 64 61 #include "eth.h" … … 170 167 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t); 171 168 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) 169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state) 176 170 { 177 171 int index; … … 183 177 proto = eth_protos_get_index(ð_globals.protos, index); 184 178 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); 187 181 } 188 182 } … … 201 195 fibril_rwlock_write_lock(ð_globals.devices_lock); 202 196 fibril_rwlock_write_lock(ð_globals.protos_lock); 203 204 197 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 } 207 205 208 206 rc = eth_devices_initialize(ð_globals.devices); … … 217 215 eth_devices_destroy(ð_globals.devices, free); 218 216 } 219 220 217 out: 221 218 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 225 222 } 226 223 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 */ 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, 241 279 size_t mtu) 242 280 { … … 263 301 device = eth_devices_find(ð_globals.devices, device_id); 264 302 if (device) { 265 if (device->s id != sid) {303 if (device->service != service) { 266 304 printf("Device %d already exists\n", device->device_id); 267 305 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 302 340 303 341 device->device_id = device_id; 304 device->s id = sid;342 device->service = service; 305 343 device->flags = 0; 306 344 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))) … … 339 377 340 378 /* 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); 343 381 if (device->sess == NULL) { 344 382 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 347 385 } 348 386 349 rc = nic_callback_create(device->sess, eth_nic_cb_connection, device);350 if (rc != EOK) {351 fibril_rwlock_write_unlock(ð_globals.devices_lock);352 async_hangup(device->sess);353 free(device);354 return EIO;355 }356 357 387 /* 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); 359 390 if (rc != EOK) { 360 391 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 368 399 if (index < 0) { 369 400 fibril_rwlock_write_unlock(ð_globals.devices_lock); 401 free(device->addr); 402 free(device->addr_data); 370 403 free(device); 371 404 return index; 372 405 } 373 406 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); 378 413 379 414 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 421 456 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t); 422 457 length -= sizeof(eth_fcs_t); 423 } else if 458 } else if(type <= ETH_MAX_CONTENT) { 424 459 /* Translate "LSAP" values */ 425 460 if ((header->lsap.dsap == ETH_LSAP_GLSAP) && … … 427 462 /* Raw packet -- discard */ 428 463 return NULL; 429 } else if 464 } else if((header->lsap.dsap == ETH_LSAP_SNAP) && 430 465 (header->lsap.ssap == ETH_LSAP_SNAP)) { 431 466 /* … … 434 469 */ 435 470 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) + 437 473 sizeof(eth_header_snap_t); 438 474 } else { 439 475 /* IEEE 802.3 + 802.2 LSAP */ 440 476 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); 442 479 } 443 480 … … 469 506 } 470 507 471 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet) 508 int nil_received_msg_local(device_id_t device_id, packet_t *packet, 509 services_t target) 472 510 { 473 511 eth_proto_t *proto; … … 485 523 flags = device->flags; 486 524 fibril_rwlock_read_unlock(ð_globals.devices_lock); 525 487 526 fibril_rwlock_read_lock(ð_globals.protos_lock); 488 489 527 do { 490 528 next = pq_detach(packet); … … 499 537 } 500 538 packet = next; 501 } while 539 } while(packet); 502 540 503 541 fibril_rwlock_read_unlock(ð_globals.protos_lock); … … 516 554 * @return ENOENT if there is no such device. 517 555 */ 518 static int eth_packet_space_message( nic_device_id_t device_id, size_t *addr_len,556 static int eth_packet_space_message(device_id_t device_id, size_t *addr_len, 519 557 size_t *prefix, size_t *content, size_t *suffix) 520 558 { … … 541 579 } 542 580 543 /** Sendthe device hardware address.581 /** Returns the device hardware address. 544 582 * 545 583 * @param[in] device_id The device identifier. 546 584 * @param[in] type Type of the desired address. 585 * @param[out] address The device hardware address. 547 586 * @return EOK on success. 548 587 * @return EBADMEM if the address parameter is NULL. 549 588 * @return ENOENT if there no such device. 550 589 */ 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 { 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 { 561 601 fibril_rwlock_read_lock(ð_globals.devices_lock); 562 602 device = eth_devices_find(ð_globals.devices, device_id); … … 565 605 return ENOENT; 566 606 } 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; 590 608 fibril_rwlock_read_unlock(ð_globals.devices_lock); 591 592 return rc; 609 } 610 611 return (*address) ? EOK : ENOENT; 593 612 } 594 613 … … 640 659 } 641 660 642 printf("%s: Protocol registered (protocol: %d, service: % #x)\n",661 printf("%s: Protocol registered (protocol: %d, service: %d)\n", 643 662 NAME, proto->protocol, proto->service); 644 663 … … 678 697 if (i < 0) 679 698 return i; 680 681 699 if (i != ETH_ADDR) 682 700 return EINVAL; 683 684 for (i = 0; i < ETH_ADDR; i++) {685 if (src[i]) {686 src_addr = src;687 break;688 }689 }690 701 691 702 length = packet_get_data_length(packet); … … 711 722 memcpy(header_dix->destination_address, dest, ETH_ADDR); 712 723 src = &header_dix->destination_address[0]; 713 } else if 724 } else if(IS_8023_2_LSAP(flags)) { 714 725 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t); 715 726 if (!header_lsap) … … 724 735 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR); 725 736 src = &header_lsap->header.destination_address[0]; 726 } else if 737 } else if(IS_8023_2_SNAP(flags)) { 727 738 header = PACKET_PREFIX(packet, eth_header_snap_t); 728 739 if (!header) … … 735 746 header->lsap.ctrl = IEEE_8023_2_UI; 736 747 737 for (i = 0; i < 3; i++)748 for (i = 0; i < 3; ++ i) 738 749 header->snap.protocol[i] = 0; 739 750 … … 749 760 return ENOMEM; 750 761 751 for (i = 0; i < 7; i++)762 for (i = 0; i < 7; ++ i) 752 763 preamble->preamble[i] = ETH_PREAMBLE; 753 764 … … 776 787 * @return EINVAL if the service parameter is not known. 777 788 */ 778 static int eth_send_message( nic_device_id_t device_id, packet_t *packet,789 static int eth_send_message(device_id_t device_id, packet_t *packet, 779 790 services_t sender) 780 791 { … … 802 813 do { 803 814 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); 805 816 if (rc != EOK) { 806 817 /* Release invalid packet */ … … 812 823 next = tmp; 813 824 } else { 814 nic_send_frame(device->sess, packet_get_data(next),815 packet_get_data_length(next));816 825 next = pq_next(next); 817 826 } 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 822 835 fibril_rwlock_read_unlock(ð_globals.devices_lock); 823 836 return EOK; 824 837 } 825 838 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(ð_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(ð_globals.devices_lock);873 874 /* Notify all upper layer modules */875 fibril_rwlock_read_lock(ð_globals.protos_lock);876 int index;877 for (index = 0; index < eth_protos_count(ð_globals.protos); index++) {878 eth_proto_t *proto = eth_protos_get_index(ð_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(ð_globals.protos_lock);886 return EOK;887 }888 889 839 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 890 840 ipc_call_t *answer, size_t *answer_count) 891 841 { 842 measured_string_t *address; 892 843 packet_t *packet; 893 844 size_t addrlen; … … 910 861 case NET_NIL_DEVICE: 911 862 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)); 913 864 case NET_NIL_SEND: 914 865 rc = packet_translate_remote(eth_globals.net_sess, &packet, … … 916 867 if (rc != EOK) 917 868 return rc; 918 919 869 return eth_send_message(IPC_GET_DEVICE(*call), packet, 920 870 IPC_GET_SERVICE(*call)); … … 924 874 if (rc != EOK) 925 875 return rc; 926 927 876 IPC_SET_ADDR(*answer, addrlen); 928 877 IPC_SET_PREFIX(*answer, prefix); … … 930 879 IPC_SET_SUFFIX(*answer, suffix); 931 880 *answer_count = 4; 932 933 881 return EOK; 934 882 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); 936 885 if (rc != EOK) 937 886 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); 943 888 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); 945 891 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); 952 894 } 953 895 954 896 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 }988 897 } 989 898
Note:
See TracChangeset
for help on using the changeset viewer.