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