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