Changes in uspace/srv/net/nil/eth/eth.c [4ee7364:6b82009] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/nil/eth/eth.c
r4ee7364 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> … … 54 52 #include <protocol_map.h> 55 53 #include <net/device.h> 54 #include <netif_remote.h> 56 55 #include <net_interface.h> 57 56 #include <il_remote.h> … … 59 58 #include <packet_client.h> 60 59 #include <packet_remote.h> 61 #include <device/nic.h>62 60 #include <nil_skel.h> 63 61 #include "eth.h" … … 169 167 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t); 170 168 171 int nil_device_state_msg_local( nic_device_id_t device_id, sysarg_t state)169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state) 172 170 { 173 171 int index; … … 197 195 fibril_rwlock_write_lock(ð_globals.devices_lock); 198 196 fibril_rwlock_write_lock(ð_globals.protos_lock); 199 200 197 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 } 203 205 204 206 rc = eth_devices_initialize(ð_globals.devices); … … 213 215 eth_devices_destroy(ð_globals.devices, free); 214 216 } 215 216 217 out: 217 218 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 221 222 } 222 223 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 */ 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, 237 279 size_t mtu) 238 280 { … … 259 301 device = eth_devices_find(ð_globals.devices, device_id); 260 302 if (device) { 261 if (device-> handle != handle) {303 if (device->service != service) { 262 304 printf("Device %d already exists\n", device->device_id); 263 305 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 298 340 299 341 device->device_id = device_id; 300 device-> handle = handle;342 device->service = service; 301 343 device->flags = 0; 302 344 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))) … … 335 377 336 378 /* 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); 339 381 if (device->sess == NULL) { 340 382 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 343 385 } 344 386 345 nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id);346 347 387 /* 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); 349 390 if (rc != EOK) { 350 391 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 358 399 if (index < 0) { 359 400 fibril_rwlock_write_unlock(ð_globals.devices_lock); 401 free(device->addr); 402 free(device->addr_data); 360 403 free(device); 361 404 return index; 362 405 } 363 406 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); 368 413 369 414 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 411 456 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t); 412 457 length -= sizeof(eth_fcs_t); 413 } else if 458 } else if(type <= ETH_MAX_CONTENT) { 414 459 /* Translate "LSAP" values */ 415 460 if ((header->lsap.dsap == ETH_LSAP_GLSAP) && … … 417 462 /* Raw packet -- discard */ 418 463 return NULL; 419 } else if 464 } else if((header->lsap.dsap == ETH_LSAP_SNAP) && 420 465 (header->lsap.ssap == ETH_LSAP_SNAP)) { 421 466 /* … … 424 469 */ 425 470 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) + 427 473 sizeof(eth_header_snap_t); 428 474 } else { 429 475 /* IEEE 802.3 + 802.2 LSAP */ 430 476 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); 432 479 } 433 480 … … 459 506 } 460 507 461 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) 462 510 { 463 511 eth_proto_t *proto; … … 475 523 flags = device->flags; 476 524 fibril_rwlock_read_unlock(ð_globals.devices_lock); 525 477 526 fibril_rwlock_read_lock(ð_globals.protos_lock); 478 479 527 do { 480 528 next = pq_detach(packet); … … 489 537 } 490 538 packet = next; 491 } while 539 } while(packet); 492 540 493 541 fibril_rwlock_read_unlock(ð_globals.protos_lock); … … 506 554 * @return ENOENT if there is no such device. 507 555 */ 508 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, 509 557 size_t *prefix, size_t *content, size_t *suffix) 510 558 { … … 531 579 } 532 580 533 /** Sendthe device hardware address.581 /** Returns the device hardware address. 534 582 * 535 583 * @param[in] device_id The device identifier. 536 584 * @param[in] type Type of the desired address. 585 * @param[out] address The device hardware address. 537 586 * @return EOK on success. 538 587 * @return EBADMEM if the address parameter is NULL. 539 588 * @return ENOENT if there no such device. 540 589 */ 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 { 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 { 551 601 fibril_rwlock_read_lock(ð_globals.devices_lock); 552 602 device = eth_devices_find(ð_globals.devices, device_id); … … 555 605 return ENOENT; 556 606 } 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; 580 608 fibril_rwlock_read_unlock(ð_globals.devices_lock); 581 582 return rc; 609 } 610 611 return (*address) ? EOK : ENOENT; 583 612 } 584 613 … … 630 659 } 631 660 632 printf("%s: Protocol registered (protocol: %d, service: % #x)\n",661 printf("%s: Protocol registered (protocol: %d, service: %d)\n", 633 662 NAME, proto->protocol, proto->service); 634 663 … … 668 697 if (i < 0) 669 698 return i; 670 671 699 if (i != ETH_ADDR) 672 700 return EINVAL; 673 674 for (i = 0; i < ETH_ADDR; i++) {675 if (src[i]) {676 src_addr = src;677 break;678 }679 }680 701 681 702 length = packet_get_data_length(packet); … … 701 722 memcpy(header_dix->destination_address, dest, ETH_ADDR); 702 723 src = &header_dix->destination_address[0]; 703 } else if 724 } else if(IS_8023_2_LSAP(flags)) { 704 725 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t); 705 726 if (!header_lsap) … … 714 735 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR); 715 736 src = &header_lsap->header.destination_address[0]; 716 } else if 737 } else if(IS_8023_2_SNAP(flags)) { 717 738 header = PACKET_PREFIX(packet, eth_header_snap_t); 718 739 if (!header) … … 725 746 header->lsap.ctrl = IEEE_8023_2_UI; 726 747 727 for (i = 0; i < 3; i++)748 for (i = 0; i < 3; ++ i) 728 749 header->snap.protocol[i] = 0; 729 750 … … 739 760 return ENOMEM; 740 761 741 for (i = 0; i < 7; i++)762 for (i = 0; i < 7; ++ i) 742 763 preamble->preamble[i] = ETH_PREAMBLE; 743 764 … … 766 787 * @return EINVAL if the service parameter is not known. 767 788 */ 768 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, 769 790 services_t sender) 770 791 { … … 792 813 do { 793 814 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); 795 816 if (rc != EOK) { 796 817 /* Release invalid packet */ … … 804 825 next = pq_next(next); 805 826 } 806 } while 827 } while(next); 807 828 808 829 /* 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 812 835 fibril_rwlock_read_unlock(ð_globals.devices_lock); 813 836 return EOK; 814 837 } 815 838 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(ð_globals.devices_lock);834 /* An existing device? */835 eth_device_t *device = eth_devices_find(ð_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(ð_globals.devices_lock);841 842 /* Notify all upper layer modules */843 fibril_rwlock_read_lock(ð_globals.protos_lock);844 int index;845 for (index = 0; index < eth_protos_count(ð_globals.protos); index++) {846 eth_proto_t *proto = eth_protos_get_index(ð_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(ð_globals.protos_lock);854 return EOK;855 } else {856 return ENOENT;857 }858 }859 860 839 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 861 840 ipc_call_t *answer, size_t *answer_count) 862 841 { 842 measured_string_t *address; 863 843 packet_t *packet; 864 844 size_t addrlen; … … 881 861 case NET_NIL_DEVICE: 882 862 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)); 884 864 case NET_NIL_SEND: 885 865 rc = packet_translate_remote(eth_globals.net_sess, &packet, … … 887 867 if (rc != EOK) 888 868 return rc; 889 890 869 return eth_send_message(IPC_GET_DEVICE(*call), packet, 891 870 IPC_GET_SERVICE(*call)); … … 895 874 if (rc != EOK) 896 875 return rc; 897 898 876 IPC_SET_ADDR(*answer, addrlen); 899 877 IPC_SET_PREFIX(*answer, prefix); … … 901 879 IPC_SET_SUFFIX(*answer, suffix); 902 880 *answer_count = 4; 903 904 881 return EOK; 905 882 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); 907 885 if (rc != EOK) 908 886 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); 914 888 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); 916 891 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); 939 894 } 940 895
Note:
See TracChangeset
for help on using the changeset viewer.