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