Changeset d7ff048 in mainline for uspace/srv/net/nil/eth/eth.c
- Timestamp:
- 2011-10-08T13:08:53Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bf08ff0
- Parents:
- 8367d1d (diff), 80099c19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/nil/eth/eth.c
r8367d1d rd7ff048 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 63 #include "eth.h" … … 167 169 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t); 168 170 169 int nil_device_state_msg_local( device_id_t device_id, sysarg_t state)171 int nil_device_state_msg_local(nic_device_id_t device_id, sysarg_t state) 170 172 { 171 173 int index; … … 196 198 fibril_rwlock_write_lock(ð_globals.protos_lock); 197 199 eth_globals.net_sess = sess; 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 } 200 memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF", 201 ETH_ADDR); 205 202 206 203 rc = eth_devices_initialize(ð_globals.devices); … … 215 212 eth_devices_destroy(ð_globals.devices, free); 216 213 } 214 217 215 out: 218 216 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 222 220 } 223 221 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, 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, 279 236 size_t mtu) 280 237 { … … 301 258 device = eth_devices_find(ð_globals.devices, device_id); 302 259 if (device) { 303 if (device-> service != service) {260 if (device->handle != handle) { 304 261 printf("Device %d already exists\n", device->device_id); 305 262 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 340 297 341 298 device->device_id = device_id; 342 device-> service = service;299 device->handle = handle; 343 300 device->flags = 0; 344 301 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))) … … 377 334 378 335 /* Bind the device driver */ 379 device->sess = netif_bind_service(device->service, device->device_id,380 SERVICE_ETHERNET, eth_receiver);336 device->sess = devman_device_connect(EXCHANGE_SERIALIZE, handle, 337 IPC_FLAG_BLOCKING); 381 338 if (device->sess == NULL) { 382 339 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 385 342 } 386 343 344 nic_connect_to_nil(device->sess, SERVICE_ETHERNET, device_id); 345 387 346 /* Get hardware address */ 388 rc = netif_get_addr_req(device->sess, device->device_id, &device->addr, 389 &device->addr_data); 347 rc = nic_get_address(device->sess, &device->addr); 390 348 if (rc != EOK) { 391 349 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 399 357 if (index < 0) { 400 358 fibril_rwlock_write_unlock(ð_globals.devices_lock); 401 free(device->addr);402 free(device->addr_data);403 359 free(device); 404 360 return index; 405 361 } 406 362 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); 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); 413 367 414 368 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 456 410 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t); 457 411 length -= sizeof(eth_fcs_t); 458 } else if (type <= ETH_MAX_CONTENT) {412 } else if (type <= ETH_MAX_CONTENT) { 459 413 /* Translate "LSAP" values */ 460 414 if ((header->lsap.dsap == ETH_LSAP_GLSAP) && … … 462 416 /* Raw packet -- discard */ 463 417 return NULL; 464 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&418 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) && 465 419 (header->lsap.ssap == ETH_LSAP_SNAP)) { 466 420 /* … … 469 423 */ 470 424 type = ntohs(header->snap.ethertype); 471 prefix = sizeof(eth_header_t) + 472 sizeof(eth_header_lsap_t) + 425 prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + 473 426 sizeof(eth_header_snap_t); 474 427 } else { 475 428 /* IEEE 802.3 + 802.2 LSAP */ 476 429 type = lsap_map(header->lsap.dsap); 477 prefix = sizeof(eth_header_t) + 478 sizeof(eth_header_lsap_t); 430 prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t); 479 431 } 480 432 … … 506 458 } 507 459 508 int nil_received_msg_local(device_id_t device_id, packet_t *packet, 509 services_t target) 460 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet) 510 461 { 511 462 eth_proto_t *proto; … … 523 474 flags = device->flags; 524 475 fibril_rwlock_read_unlock(ð_globals.devices_lock); 525 526 476 fibril_rwlock_read_lock(ð_globals.protos_lock); 477 527 478 do { 528 479 next = pq_detach(packet); … … 537 488 } 538 489 packet = next; 539 } while (packet);490 } while (packet); 540 491 541 492 fibril_rwlock_read_unlock(ð_globals.protos_lock); … … 554 505 * @return ENOENT if there is no such device. 555 506 */ 556 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, 557 508 size_t *prefix, size_t *content, size_t *suffix) 558 509 { … … 579 530 } 580 531 581 /** Returnsthe device hardware address.532 /** Send the device hardware address. 582 533 * 583 534 * @param[in] device_id The device identifier. 584 535 * @param[in] type Type of the desired address. 585 * @param[out] address The device hardware address.586 536 * @return EOK on success. 587 537 * @return EBADMEM if the address parameter is NULL. 588 538 * @return ENOENT if there no such device. 589 539 */ 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 { 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 { 601 550 fibril_rwlock_read_lock(ð_globals.devices_lock); 602 551 device = eth_devices_find(ð_globals.devices, device_id); … … 605 554 return ENOENT; 606 555 } 607 *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) 608 579 fibril_rwlock_read_unlock(ð_globals.devices_lock); 609 } 610 611 return (*address) ? EOK : ENOENT; 580 581 return rc; 612 582 } 613 583 … … 659 629 } 660 630 661 printf("%s: Protocol registered (protocol: %d, service: % d)\n",631 printf("%s: Protocol registered (protocol: %d, service: %#x)\n", 662 632 NAME, proto->protocol, proto->service); 663 633 … … 697 667 if (i < 0) 698 668 return i; 669 699 670 if (i != ETH_ADDR) 700 671 return EINVAL; 672 673 for (i = 0; i < ETH_ADDR; i++) { 674 if (src[i]) { 675 src_addr = src; 676 break; 677 } 678 } 701 679 702 680 length = packet_get_data_length(packet); … … 722 700 memcpy(header_dix->destination_address, dest, ETH_ADDR); 723 701 src = &header_dix->destination_address[0]; 724 } else if (IS_8023_2_LSAP(flags)) {702 } else if (IS_8023_2_LSAP(flags)) { 725 703 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t); 726 704 if (!header_lsap) … … 735 713 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR); 736 714 src = &header_lsap->header.destination_address[0]; 737 } else if (IS_8023_2_SNAP(flags)) {715 } else if (IS_8023_2_SNAP(flags)) { 738 716 header = PACKET_PREFIX(packet, eth_header_snap_t); 739 717 if (!header) … … 746 724 header->lsap.ctrl = IEEE_8023_2_UI; 747 725 748 for (i = 0; i < 3; ++ i)726 for (i = 0; i < 3; i++) 749 727 header->snap.protocol[i] = 0; 750 728 … … 760 738 return ENOMEM; 761 739 762 for (i = 0; i < 7; ++ i)740 for (i = 0; i < 7; i++) 763 741 preamble->preamble[i] = ETH_PREAMBLE; 764 742 … … 787 765 * @return EINVAL if the service parameter is not known. 788 766 */ 789 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, 790 768 services_t sender) 791 769 { … … 813 791 do { 814 792 rc = eth_prepare_packet(device->flags, next, 815 (uint8_t *) device->addr->value, ethertype, device->mtu);793 (uint8_t *) &device->addr.address, ethertype, device->mtu); 816 794 if (rc != EOK) { 817 795 /* Release invalid packet */ … … 825 803 next = pq_next(next); 826 804 } 827 } while (next);805 } while (next); 828 806 829 807 /* Send packet queue */ 830 if (packet) { 831 netif_send_msg(device->sess, device_id, packet, 832 SERVICE_ETHERNET); 833 } 834 808 if (packet) 809 nic_send_message(device->sess, packet_get_id(packet)); 810 835 811 fibril_rwlock_read_unlock(ð_globals.devices_lock); 836 812 return EOK; 837 813 } 838 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 839 859 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 840 860 ipc_call_t *answer, size_t *answer_count) 841 861 { 842 measured_string_t *address;843 862 packet_t *packet; 844 863 size_t addrlen; … … 861 880 case NET_NIL_DEVICE: 862 881 return eth_device_message(IPC_GET_DEVICE(*call), 863 IPC_GET_ SERVICE(*call), IPC_GET_MTU(*call));882 IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call)); 864 883 case NET_NIL_SEND: 865 884 rc = packet_translate_remote(eth_globals.net_sess, &packet, … … 867 886 if (rc != EOK) 868 887 return rc; 888 869 889 return eth_send_message(IPC_GET_DEVICE(*call), packet, 870 890 IPC_GET_SERVICE(*call)); … … 874 894 if (rc != EOK) 875 895 return rc; 896 876 897 IPC_SET_ADDR(*answer, addrlen); 877 898 IPC_SET_PREFIX(*answer, prefix); … … 879 900 IPC_SET_SUFFIX(*answer, suffix); 880 901 *answer_count = 4; 902 881 903 return EOK; 882 904 case NET_NIL_ADDR: 883 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR, 884 &address); 905 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR); 885 906 if (rc != EOK) 886 907 return rc; 887 return measured_strings_reply(address, 1); 908 909 IPC_SET_ADDR(*answer, ETH_ADDR); 910 *answer_count = 1; 911 912 return EOK; 888 913 case NET_NIL_BROADCAST_ADDR: 889 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR, 890 &address); 914 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR); 891 915 if (rc != EOK) 892 return EOK; 893 return measured_strings_reply(address, 1); 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; 894 938 } 895 939
Note:
See TracChangeset
for help on using the changeset viewer.