Changes in uspace/srv/net/nil/eth/eth.c [6b82009:9cd8165] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/nil/eth/eth.c
r6b82009 r9cd8165 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> … … 46 48 #include <ipc/net.h> 47 49 #include <ipc/services.h> 50 #include <loc.h> 48 51 #include <net/modules.h> 49 52 #include <net_checksum.h> … … 52 55 #include <protocol_map.h> 53 56 #include <net/device.h> 54 #include <netif_remote.h>55 57 #include <net_interface.h> 56 58 #include <il_remote.h> … … 58 60 #include <packet_client.h> 59 61 #include <packet_remote.h> 62 #include <device/nic.h> 60 63 #include <nil_skel.h> 61 64 #include "eth.h" … … 167 170 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t); 168 171 169 int nil_device_state_msg_local(device_id_t device_id, sysarg_t state) 172 static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, 173 void *arg); 174 175 static int eth_device_state(eth_device_t *device, sysarg_t state) 170 176 { 171 177 int index; … … 177 183 proto = eth_protos_get_index(ð_globals.protos, index); 178 184 if ((proto) && (proto->sess)) { 179 il_device_state_msg(proto->sess, device _id, state,180 proto->service);185 il_device_state_msg(proto->sess, device->device_id, 186 state, proto->service); 181 187 } 182 188 } … … 195 201 fibril_rwlock_write_lock(ð_globals.devices_lock); 196 202 fibril_rwlock_write_lock(ð_globals.protos_lock); 203 197 204 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 } 205 memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF", 206 ETH_ADDR); 205 207 206 208 rc = eth_devices_initialize(ð_globals.devices); … … 215 217 eth_devices_destroy(ð_globals.devices, free); 216 218 } 219 217 220 out: 218 221 fibril_rwlock_write_unlock(ð_globals.protos_lock); … … 222 225 } 223 226 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, 227 /** Register new device or updates the MTU of an existing one. 228 * 229 * Determine the device local hardware address. 230 * 231 * @param[in] device_id New device identifier. 232 * @param[in] sid NIC service ID. 233 * @param[in] mtu Device maximum transmission unit. 234 * 235 * @return EOK on success. 236 * @return EEXIST if the device with the different service exists. 237 * @return ENOMEM if there is not enough memory left. 238 * 239 */ 240 static int eth_device_message(nic_device_id_t device_id, service_id_t sid, 279 241 size_t mtu) 280 242 { … … 301 263 device = eth_devices_find(ð_globals.devices, device_id); 302 264 if (device) { 303 if (device->s ervice != service) {265 if (device->sid != sid) { 304 266 printf("Device %d already exists\n", device->device_id); 305 267 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 340 302 341 303 device->device_id = device_id; 342 device->s ervice = service;304 device->sid = sid; 343 305 device->flags = 0; 344 306 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags))) … … 377 339 378 340 /* Bind the device driver */ 379 device->sess = netif_bind_service(device->service, device->device_id,380 SERVICE_ETHERNET, eth_receiver);341 device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 342 IPC_FLAG_BLOCKING); 381 343 if (device->sess == NULL) { 382 344 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 385 347 } 386 348 349 rc = nic_callback_create(device->sess, eth_nic_cb_connection, device); 350 if (rc != EOK) { 351 fibril_rwlock_write_unlock(ð_globals.devices_lock); 352 async_hangup(device->sess); 353 free(device); 354 return EIO; 355 } 356 387 357 /* Get hardware address */ 388 rc = netif_get_addr_req(device->sess, device->device_id, &device->addr, 389 &device->addr_data); 358 rc = nic_get_address(device->sess, &device->addr); 390 359 if (rc != EOK) { 391 360 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 399 368 if (index < 0) { 400 369 fibril_rwlock_write_unlock(ð_globals.devices_lock); 401 free(device->addr);402 free(device->addr_data);403 370 free(device); 404 371 return index; 405 372 } 406 373 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); 374 printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, " 375 "mac: " PRIMAC ", flags: 0x%x)\n", NAME, 376 device->device_id, device->sid, device->mtu, 377 ARGSMAC(device->addr.address), device->flags); 413 378 414 379 fibril_rwlock_write_unlock(ð_globals.devices_lock); … … 456 421 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t); 457 422 length -= sizeof(eth_fcs_t); 458 } else if (type <= ETH_MAX_CONTENT) {423 } else if (type <= ETH_MAX_CONTENT) { 459 424 /* Translate "LSAP" values */ 460 425 if ((header->lsap.dsap == ETH_LSAP_GLSAP) && … … 462 427 /* Raw packet -- discard */ 463 428 return NULL; 464 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&429 } else if ((header->lsap.dsap == ETH_LSAP_SNAP) && 465 430 (header->lsap.ssap == ETH_LSAP_SNAP)) { 466 431 /* … … 469 434 */ 470 435 type = ntohs(header->snap.ethertype); 471 prefix = sizeof(eth_header_t) + 472 sizeof(eth_header_lsap_t) + 436 prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + 473 437 sizeof(eth_header_snap_t); 474 438 } else { 475 439 /* IEEE 802.3 + 802.2 LSAP */ 476 440 type = lsap_map(header->lsap.dsap); 477 prefix = sizeof(eth_header_t) + 478 sizeof(eth_header_lsap_t); 441 prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t); 479 442 } 480 443 … … 506 469 } 507 470 508 int nil_received_msg_local(device_id_t device_id, packet_t *packet, 509 services_t target) 471 int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet) 510 472 { 511 473 eth_proto_t *proto; … … 523 485 flags = device->flags; 524 486 fibril_rwlock_read_unlock(ð_globals.devices_lock); 525 526 487 fibril_rwlock_read_lock(ð_globals.protos_lock); 488 527 489 do { 528 490 next = pq_detach(packet); … … 537 499 } 538 500 packet = next; 539 } while (packet);501 } while (packet); 540 502 541 503 fibril_rwlock_read_unlock(ð_globals.protos_lock); … … 554 516 * @return ENOENT if there is no such device. 555 517 */ 556 static int eth_packet_space_message( device_id_t device_id, size_t *addr_len,518 static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len, 557 519 size_t *prefix, size_t *content, size_t *suffix) 558 520 { … … 579 541 } 580 542 581 /** Returnsthe device hardware address.543 /** Send the device hardware address. 582 544 * 583 545 * @param[in] device_id The device identifier. 584 546 * @param[in] type Type of the desired address. 585 * @param[out] address The device hardware address.586 547 * @return EOK on success. 587 548 * @return EBADMEM if the address parameter is NULL. 588 549 * @return ENOENT if there no such device. 589 550 */ 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 { 551 static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type) 552 { 553 eth_device_t *device = NULL; 554 uint8_t *address; 555 size_t max_len; 556 ipc_callid_t callid; 557 558 if (type == ETH_BROADCAST_ADDR) 559 address = eth_globals.broadcast_addr; 560 else { 601 561 fibril_rwlock_read_lock(ð_globals.devices_lock); 602 562 device = eth_devices_find(ð_globals.devices, device_id); … … 605 565 return ENOENT; 606 566 } 607 *address = device->addr; 567 568 address = (uint8_t *) &device->addr.address; 569 } 570 571 int rc = EOK; 572 if (!async_data_read_receive(&callid, &max_len)) { 573 rc = EREFUSED; 574 goto end; 575 } 576 577 if (max_len < ETH_ADDR) { 578 async_data_read_finalize(callid, NULL, 0); 579 rc = ELIMIT; 580 goto end; 581 } 582 583 rc = async_data_read_finalize(callid, address, ETH_ADDR); 584 if (rc != EOK) 585 goto end; 586 587 end: 588 589 if (type == ETH_LOCAL_ADDR) 608 590 fibril_rwlock_read_unlock(ð_globals.devices_lock); 609 } 610 611 return (*address) ? EOK : ENOENT; 591 592 return rc; 612 593 } 613 594 … … 659 640 } 660 641 661 printf("%s: Protocol registered (protocol: %d, service: % d)\n",642 printf("%s: Protocol registered (protocol: %d, service: %#x)\n", 662 643 NAME, proto->protocol, proto->service); 663 644 … … 697 678 if (i < 0) 698 679 return i; 680 699 681 if (i != ETH_ADDR) 700 682 return EINVAL; 683 684 for (i = 0; i < ETH_ADDR; i++) { 685 if (src[i]) { 686 src_addr = src; 687 break; 688 } 689 } 701 690 702 691 length = packet_get_data_length(packet); … … 722 711 memcpy(header_dix->destination_address, dest, ETH_ADDR); 723 712 src = &header_dix->destination_address[0]; 724 } else if (IS_8023_2_LSAP(flags)) {713 } else if (IS_8023_2_LSAP(flags)) { 725 714 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t); 726 715 if (!header_lsap) … … 735 724 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR); 736 725 src = &header_lsap->header.destination_address[0]; 737 } else if (IS_8023_2_SNAP(flags)) {726 } else if (IS_8023_2_SNAP(flags)) { 738 727 header = PACKET_PREFIX(packet, eth_header_snap_t); 739 728 if (!header) … … 746 735 header->lsap.ctrl = IEEE_8023_2_UI; 747 736 748 for (i = 0; i < 3; ++ i)737 for (i = 0; i < 3; i++) 749 738 header->snap.protocol[i] = 0; 750 739 … … 760 749 return ENOMEM; 761 750 762 for (i = 0; i < 7; ++ i)751 for (i = 0; i < 7; i++) 763 752 preamble->preamble[i] = ETH_PREAMBLE; 764 753 … … 787 776 * @return EINVAL if the service parameter is not known. 788 777 */ 789 static int eth_send_message( device_id_t device_id, packet_t *packet,778 static int eth_send_message(nic_device_id_t device_id, packet_t *packet, 790 779 services_t sender) 791 780 { … … 813 802 do { 814 803 rc = eth_prepare_packet(device->flags, next, 815 (uint8_t *) device->addr->value, ethertype, device->mtu);804 (uint8_t *) &device->addr.address, ethertype, device->mtu); 816 805 if (rc != EOK) { 817 806 /* Release invalid packet */ … … 823 812 next = tmp; 824 813 } else { 814 nic_send_frame(device->sess, packet_get_data(next), 815 packet_get_data_length(next)); 825 816 next = pq_next(next); 826 817 } 827 } while(next); 828 829 /* Send packet queue */ 830 if (packet) { 831 netif_send_msg(device->sess, device_id, packet, 832 SERVICE_ETHERNET); 833 } 834 818 } while (next); 819 820 pq_release_remote(eth_globals.net_sess, packet_get_id(packet)); 821 835 822 fibril_rwlock_read_unlock(ð_globals.devices_lock); 836 823 return EOK; 837 824 } 838 825 826 static int eth_received(eth_device_t *device) 827 { 828 void *data; 829 size_t size; 830 int rc; 831 832 rc = async_data_write_accept(&data, false, 0, 0, 0, &size); 833 if (rc != EOK) { 834 printf("%s: data_write_accept() failed\n", NAME); 835 return rc; 836 } 837 838 packet_t *packet = packet_get_1_remote(eth_globals.net_sess, size); 839 if (packet == NULL) 840 return ENOMEM; 841 842 void *pdata = packet_suffix(packet, size); 843 memcpy(pdata, data, size); 844 free(data); 845 846 return nil_received_msg_local(device->device_id, packet); 847 } 848 849 static int eth_addr_changed(eth_device_t *device) 850 { 851 nic_address_t address; 852 size_t length; 853 ipc_callid_t data_callid; 854 if (!async_data_write_receive(&data_callid, &length)) { 855 async_answer_0(data_callid, EINVAL); 856 return EINVAL; 857 } 858 if (length > sizeof (nic_address_t)) { 859 async_answer_0(data_callid, ELIMIT); 860 return ELIMIT; 861 } 862 if (async_data_write_finalize(data_callid, &address, length) != EOK) { 863 return EINVAL; 864 } 865 866 fibril_rwlock_write_lock(ð_globals.devices_lock); 867 868 printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n", 869 device->device_id, ARGSMAC(device->addr.address), 870 ARGSMAC(address.address)); 871 memcpy(&device->addr, &address, sizeof (nic_address_t)); 872 fibril_rwlock_write_unlock(ð_globals.devices_lock); 873 874 /* Notify all upper layer modules */ 875 fibril_rwlock_read_lock(ð_globals.protos_lock); 876 int index; 877 for (index = 0; index < eth_protos_count(ð_globals.protos); index++) { 878 eth_proto_t *proto = eth_protos_get_index(ð_globals.protos, index); 879 if (proto->sess != NULL) { 880 il_addr_changed_msg(proto->sess, device->device_id, 881 ETH_ADDR, address.address); 882 } 883 } 884 885 fibril_rwlock_read_unlock(ð_globals.protos_lock); 886 return EOK; 887 } 888 839 889 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 840 890 ipc_call_t *answer, size_t *answer_count) 841 891 { 842 measured_string_t *address;843 892 packet_t *packet; 844 893 size_t addrlen; … … 861 910 case NET_NIL_DEVICE: 862 911 return eth_device_message(IPC_GET_DEVICE(*call), 863 IPC_GET_ SERVICE(*call), IPC_GET_MTU(*call));912 IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call)); 864 913 case NET_NIL_SEND: 865 914 rc = packet_translate_remote(eth_globals.net_sess, &packet, … … 867 916 if (rc != EOK) 868 917 return rc; 918 869 919 return eth_send_message(IPC_GET_DEVICE(*call), packet, 870 920 IPC_GET_SERVICE(*call)); … … 874 924 if (rc != EOK) 875 925 return rc; 926 876 927 IPC_SET_ADDR(*answer, addrlen); 877 928 IPC_SET_PREFIX(*answer, prefix); … … 879 930 IPC_SET_SUFFIX(*answer, suffix); 880 931 *answer_count = 4; 932 881 933 return EOK; 882 934 case NET_NIL_ADDR: 883 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR, 884 &address); 935 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR); 885 936 if (rc != EOK) 886 937 return rc; 887 return measured_strings_reply(address, 1); 938 939 IPC_SET_ADDR(*answer, ETH_ADDR); 940 *answer_count = 1; 941 942 return EOK; 888 943 case NET_NIL_BROADCAST_ADDR: 889 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR, 890 &address); 944 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR); 891 945 if (rc != EOK) 892 return EOK; 893 return measured_strings_reply(address, 1); 946 return rc; 947 948 IPC_SET_ADDR(*answer, ETH_ADDR); 949 *answer_count = 1; 950 951 return EOK; 894 952 } 895 953 896 954 return ENOTSUP; 955 } 956 957 static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 958 { 959 eth_device_t *device = (eth_device_t *)arg; 960 int rc; 961 962 async_answer_0(iid, EOK); 963 964 while (true) { 965 ipc_call_t call; 966 ipc_callid_t callid = async_get_call(&call); 967 968 if (!IPC_GET_IMETHOD(call)) 969 break; 970 971 switch (IPC_GET_IMETHOD(call)) { 972 case NIC_EV_DEVICE_STATE: 973 rc = eth_device_state(device, IPC_GET_ARG1(call)); 974 async_answer_0(callid, (sysarg_t) rc); 975 break; 976 case NIC_EV_RECEIVED: 977 rc = eth_received(device); 978 async_answer_0(callid, (sysarg_t) rc); 979 break; 980 case NIC_EV_ADDR_CHANGED: 981 rc = eth_addr_changed(device); 982 async_answer_0(callid, (sysarg_t) rc); 983 break; 984 default: 985 async_answer_0(callid, ENOTSUP); 986 } 987 } 897 988 } 898 989
Note:
See TracChangeset
for help on using the changeset viewer.