Changes in uspace/srv/net/nil/eth/eth.c [28a3e74:00d7e1b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/nil/eth/eth.c
r28a3e74 r00d7e1b 1 1 /* 2 2 * Copyright (c) 2009 Lukas Mejdrech 3 * Copyright (c) 2011 Radim Vansa 3 4 * All rights reserved. 4 5 * … … 36 37 */ 37 38 39 #include <assert.h> 38 40 #include <async.h> 39 41 #include <malloc.h> … … 52 54 #include <protocol_map.h> 53 55 #include <net/device.h> 54 #include <netif_remote.h>55 56 #include <net_interface.h> 56 57 #include <il_remote.h> … … 58 59 #include <packet_client.h> 59 60 #include <packet_remote.h> 61 #include <device/nic.h> 60 62 #include <nil_skel.h> 61 62 63 #include "eth.h" 63 64 … … 168 169 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t); 169 170 170 int nil_device_state_msg_local( int nil_phone, device_id_t device_id, int state)171 int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state) 171 172 { 172 173 int index; … … 177 178 index--) { 178 179 proto = eth_protos_get_index(ð_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, 181 182 proto->service); 182 183 } … … 187 188 } 188 189 189 int nil_initialize( int net_phone)190 int nil_initialize(async_sess_t *sess) 190 191 { 191 192 int rc; … … 196 197 fibril_rwlock_write_lock(ð_globals.devices_lock); 197 198 fibril_rwlock_write_lock(ð_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); 206 202 207 203 rc = eth_devices_initialize(ð_globals.devices); … … 216 212 eth_devices_destroy(ð_globals.devices, free); 217 213 } 214 218 215 out: 219 216 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 223 220 } 224 221 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 */ 235 static int eth_device_message(nic_device_id_t device_id, devman_handle_t handle, 278 236 size_t mtu) 279 237 { … … 300 258 device = eth_devices_find(ð_globals.devices, device_id); 301 259 if (device) { 302 if (device-> service != service) {260 if (device->handle != handle) { 303 261 printf("Device %d already exists\n", device->device_id); 304 262 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 322 280 proto = eth_protos_get_index(ð_globals.protos, 323 281 index); 324 if (proto-> phone) {325 il_mtu_changed_msg(proto-> phone,282 if (proto->sess) { 283 il_mtu_changed_msg(proto->sess, 326 284 device->device_id, device->mtu, 327 285 proto->service); … … 339 297 340 298 device->device_id = device_id; 341 device-> service = service;299 device->handle = handle; 342 300 device->flags = 0; 343 301 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))) … … 347 305 348 306 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, 350 308 &configuration, count, &data); 351 309 if (rc != EOK) { … … 376 334 377 335 /* 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) { 381 339 fibril_rwlock_write_unlock(ð_globals.devices_lock); 382 340 free(device); 383 return device->phone; 384 } 341 return ENOENT; 342 } 343 344 nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id); 385 345 386 346 /* 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); 389 348 if (rc != EOK) { 390 349 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 398 357 if (index < 0) { 399 358 fibril_rwlock_write_unlock(ð_globals.devices_lock); 400 free(device->addr);401 free(device->addr_data);402 359 free(device); 403 360 return index; 404 361 } 405 362 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); 412 367 413 368 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 455 410 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t); 456 411 length -= sizeof(eth_fcs_t); 457 } else if (type <= ETH_MAX_CONTENT) {412 } else if (type <= ETH_MAX_CONTENT) { 458 413 /* Translate "LSAP" values */ 459 414 if ((header->lsap.dsap == ETH_LSAP_GLSAP) && … … 461 416 /* Raw packet -- discard */ 462 417 return NULL; 463 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&418 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) && 464 419 (header->lsap.ssap == ETH_LSAP_SNAP)) { 465 420 /* … … 468 423 */ 469 424 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) + 472 426 sizeof(eth_header_snap_t); 473 427 } else { 474 428 /* IEEE 802.3 + 802.2 LSAP */ 475 429 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); 478 431 } 479 432 … … 505 458 } 506 459 507 int nil_received_msg_local(int nil_phone, device_id_t device_id, 508 packet_t *packet, services_t target) 460 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet) 509 461 { 510 462 eth_proto_t *proto; … … 522 474 flags = device->flags; 523 475 fibril_rwlock_read_unlock(ð_globals.devices_lock); 524 525 476 fibril_rwlock_read_lock(ð_globals.protos_lock); 477 526 478 do { 527 479 next = pq_detach(packet); 528 480 proto = eth_process_packet(flags, packet); 529 481 if (proto) { 530 il_received_msg(proto-> phone, device_id, packet,482 il_received_msg(proto->sess, device_id, packet, 531 483 proto->service); 532 484 } else { 533 485 /* Drop invalid/unknown */ 534 pq_release_remote(eth_globals.net_ phone,486 pq_release_remote(eth_globals.net_sess, 535 487 packet_get_id(packet)); 536 488 } 537 489 packet = next; 538 } while (packet);490 } while (packet); 539 491 540 492 fibril_rwlock_read_unlock(ð_globals.protos_lock); … … 553 505 * @return ENOENT if there is no such device. 554 506 */ 555 static int eth_packet_space_message( device_id_t device_id, size_t *addr_len,507 static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len, 556 508 size_t *prefix, size_t *content, size_t *suffix) 557 509 { … … 578 530 } 579 531 580 /** Returnsthe device hardware address.532 /** Send the device hardware address. 581 533 * 582 534 * @param[in] device_id The device identifier. 583 535 * @param[in] type Type of the desired address. 584 * @param[out] address The device hardware address.585 536 * @return EOK on success. 586 537 * @return EBADMEM if the address parameter is NULL. 587 538 * @return ENOENT if there no such device. 588 539 */ 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 { 540 static 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 { 600 550 fibril_rwlock_read_lock(ð_globals.devices_lock); 601 551 device = eth_devices_find(ð_globals.devices, device_id); … … 604 554 return ENOENT; 605 555 } 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 576 end: 577 578 if (type == ETH_LOCAL_ADDR) 607 579 fibril_rwlock_read_unlock(ð_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 */ 596 static int eth_register_message(services_t service, async_sess_t *sess) 624 597 { 625 598 eth_proto_t *proto; … … 634 607 proto = eth_protos_find(ð_globals.protos, protocol); 635 608 if (proto) { 636 proto-> phone = phone;609 proto->sess = sess; 637 610 fibril_rwlock_write_unlock(ð_globals.protos_lock); 638 611 return EOK; … … 646 619 proto->service = service; 647 620 proto->protocol = protocol; 648 proto-> phone = phone;621 proto->sess = sess; 649 622 650 623 index = eth_protos_add(ð_globals.protos, protocol, proto); … … 656 629 } 657 630 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); 660 633 661 634 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 694 667 if (i < 0) 695 668 return i; 669 696 670 if (i != ETH_ADDR) 697 671 return EINVAL; 672 673 for (i = 0; i < ETH_ADDR; i++) { 674 if (src[i]) { 675 src_addr = src; 676 break; 677 } 678 } 698 679 699 680 length = packet_get_data_length(packet); … … 719 700 memcpy(header_dix->destination_address, dest, ETH_ADDR); 720 701 src = &header_dix->destination_address[0]; 721 } else if (IS_8023_2_LSAP(flags)) {702 } else if (IS_8023_2_LSAP(flags)) { 722 703 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t); 723 704 if (!header_lsap) … … 732 713 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR); 733 714 src = &header_lsap->header.destination_address[0]; 734 } else if (IS_8023_2_SNAP(flags)) {715 } else if (IS_8023_2_SNAP(flags)) { 735 716 header = PACKET_PREFIX(packet, eth_header_snap_t); 736 717 if (!header) … … 743 724 header->lsap.ctrl = IEEE_8023_2_UI; 744 725 745 for (i = 0; i < 3; ++ i)726 for (i = 0; i < 3; i++) 746 727 header->snap.protocol[i] = 0; 747 728 … … 757 738 return ENOMEM; 758 739 759 for (i = 0; i < 7; ++ i)740 for (i = 0; i < 7; i++) 760 741 preamble->preamble[i] = ETH_PREAMBLE; 761 742 … … 784 765 * @return EINVAL if the service parameter is not known. 785 766 */ 786 static int eth_send_message( device_id_t device_id, packet_t *packet,767 static int eth_send_message(nic_device_id_t device_id, packet_t *packet, 787 768 services_t sender) 788 769 { … … 795 776 ethertype = htons(protocol_map(SERVICE_ETHERNET, sender)); 796 777 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)); 798 779 return EINVAL; 799 780 } … … 810 791 do { 811 792 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); 813 794 if (rc != EOK) { 814 795 /* Release invalid packet */ … … 816 797 if (next == packet) 817 798 packet = tmp; 818 pq_release_remote(eth_globals.net_ phone,799 pq_release_remote(eth_globals.net_sess, 819 800 packet_get_id(next)); 820 801 next = tmp; … … 822 803 next = pq_next(next); 823 804 } 824 } while (next);805 } while (next); 825 806 826 807 /* 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 832 811 fibril_rwlock_read_unlock(ð_globals.devices_lock); 833 812 return EOK; 834 813 } 835 814 815 static 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(ð_globals.devices_lock); 833 /* An existing device? */ 834 eth_device_t *device = eth_devices_find(ð_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(ð_globals.devices_lock); 840 841 /* Notify all upper layer modules */ 842 fibril_rwlock_read_lock(ð_globals.protos_lock); 843 int index; 844 for (index = 0; index < eth_protos_count(ð_globals.protos); index++) { 845 eth_proto_t *proto = eth_protos_get_index(ð_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(ð_globals.protos_lock); 853 return EOK; 854 } else { 855 return ENOENT; 856 } 857 } 858 836 859 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 837 860 ipc_call_t *answer, size_t *answer_count) 838 861 { 839 measured_string_t *address;840 862 packet_t *packet; 841 863 size_t addrlen; … … 846 868 847 869 *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 848 879 switch (IPC_GET_IMETHOD(*call)) { 849 case IPC_M_PHONE_HUNGUP:850 return EOK;851 852 880 case NET_NIL_DEVICE: 853 881 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)); 855 883 case NET_NIL_SEND: 856 rc = packet_translate_remote(eth_globals.net_ phone, &packet,884 rc = packet_translate_remote(eth_globals.net_sess, &packet, 857 885 IPC_GET_PACKET(*call)); 858 886 if (rc != EOK) 859 887 return rc; 888 860 889 return eth_send_message(IPC_GET_DEVICE(*call), packet, 861 890 IPC_GET_SERVICE(*call)); … … 865 894 if (rc != EOK) 866 895 return rc; 896 867 897 IPC_SET_ADDR(*answer, addrlen); 868 898 IPC_SET_PREFIX(*answer, prefix); … … 870 900 IPC_SET_SUFFIX(*answer, suffix); 871 901 *answer_count = 4; 902 872 903 return EOK; 873 904 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); 876 906 if (rc != EOK) 877 907 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; 879 913 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); 882 915 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; 888 938 } 889 939
Note:
See TracChangeset
for help on using the changeset viewer.