Changeset fe5a9fc in mainline for uspace/srv/net/il/arp/arp.c
- Timestamp:
- 2011-01-12T11:25:54Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 73ac2e9
- Parents:
- 77429d3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
r77429d3 rfe5a9fc 72 72 73 73 /** Number of microseconds to wait for an ARP reply. */ 74 #define ARP_TRANS_WAIT 74 #define ARP_TRANS_WAIT 1000000 75 75 76 76 /** ARP global data. */ … … 87 87 trans->hw_addr = NULL; 88 88 } 89 89 90 fibril_condvar_broadcast(&trans->cv); 90 91 } … … 93 94 { 94 95 int count; 95 arp_trans_t *trans; 96 96 97 97 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 98 trans = arp_addr_items_get_index(&addresses->values, count); 98 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values, 99 count); 99 100 if (trans) 100 101 arp_clear_trans(trans); … … 102 103 } 103 104 104 105 /** Clears the device specific data. 106 * 107 * @param[in] device The device specific data. 105 /** Clear the device specific data. 106 * 107 * @param[in] device Device specific data. 108 108 */ 109 109 static void arp_clear_device(arp_device_t *device) 110 110 { 111 111 int count; 112 arp_proto_t *proto; 113 112 114 113 for (count = arp_protos_count(&device->protos) - 1; count >= 0; 115 114 count--) { 116 proto = arp_protos_get_index(&device->protos, count); 115 arp_proto_t *proto = arp_protos_get_index(&device->protos, 116 count); 117 117 118 if (proto) { 118 119 if (proto->addr) 119 120 free(proto->addr); 121 120 122 if (proto->addr_data) 121 123 free(proto->addr_data); 124 122 125 arp_clear_addr(&proto->addresses); 123 126 arp_addr_destroy(&proto->addresses); 124 127 } 125 128 } 129 126 130 arp_protos_clear(&device->protos); 127 131 } … … 130 134 { 131 135 int count; 132 arp_device_t *device; 133 136 134 137 fibril_mutex_lock(&arp_globals.lock); 135 138 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 136 139 count--) { 137 device = arp_cache_get_index(&arp_globals.cache, count); 140 arp_device_t *device = arp_cache_get_index(&arp_globals.cache, 141 count); 142 138 143 if (device) { 139 144 arp_clear_device(device); 140 145 if (device->addr_data) 141 146 free(device->addr_data); 147 142 148 if (device->broadcast_data) 143 149 free(device->broadcast_data); 144 150 } 145 151 } 152 146 153 arp_cache_clear(&arp_globals.cache); 147 154 fibril_mutex_unlock(&arp_globals.lock); 148 printf("Cache cleaned\n");155 149 156 return EOK; 150 157 } … … 153 160 services_t protocol, measured_string_t *address) 154 161 { 155 arp_device_t *device;156 arp_proto_t *proto;157 arp_trans_t *trans;158 159 162 fibril_mutex_lock(&arp_globals.lock); 160 device = arp_cache_find(&arp_globals.cache, device_id); 163 164 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 161 165 if (!device) { 162 166 fibril_mutex_unlock(&arp_globals.lock); 163 167 return ENOENT; 164 168 } 165 proto = arp_protos_find(&device->protos, protocol); 169 170 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 166 171 if (!proto) { 167 172 fibril_mutex_unlock(&arp_globals.lock); 168 173 return ENOENT; 169 174 } 170 trans = arp_addr_find(&proto->addresses, address->value, address->length); 175 176 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value, 177 address->length); 171 178 if (trans) 172 179 arp_clear_trans(trans); 180 173 181 arp_addr_exclude(&proto->addresses, address->value, address->length); 182 174 183 fibril_mutex_unlock(&arp_globals.lock); 175 184 return EOK; 176 185 } 177 186 178 179 187 static int arp_clear_device_req(int arp_phone, device_id_t device_id) 180 188 { 181 arp_device_t *device;182 183 189 fibril_mutex_lock(&arp_globals.lock); 184 device = arp_cache_find(&arp_globals.cache, device_id); 190 191 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 185 192 if (!device) { 186 193 fibril_mutex_unlock(&arp_globals.lock); 187 194 return ENOENT; 188 195 } 196 189 197 arp_clear_device(device); 190 printf("Device %d cleared\n", device_id);198 191 199 fibril_mutex_unlock(&arp_globals.lock); 192 200 return EOK; 193 201 } 194 202 195 /** Creates new protocol specific data. 196 * 197 * Allocates and returns the needed memory block as the proto parameter. 198 * 199 * @param[out] proto The allocated protocol specific data. 200 * @param[in] service The protocol module service. 201 * @param[in] address The actual protocol device address. 202 * @return EOK on success. 203 * @return ENOMEM if there is not enough memory left. 203 /** Create new protocol specific data. 204 * 205 * Allocate and return the needed memory block as the proto parameter. 206 * 207 * @param[out] proto Allocated protocol specific data. 208 * @param[in] service Protocol module service. 209 * @param[in] address Actual protocol device address. 210 * 211 * @return EOK on success. 212 * @return ENOMEM if there is not enough memory left. 213 * 204 214 */ 205 215 static int arp_proto_create(arp_proto_t **proto, services_t service, 206 216 measured_string_t *address) 207 217 { 208 int rc;209 210 218 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t)); 211 219 if (!*proto) … … 216 224 (*proto)->addr_data = address->value; 217 225 218 rc = arp_addr_initialize(&(*proto)->addresses);226 int rc = arp_addr_initialize(&(*proto)->addresses); 219 227 if (rc != EOK) { 220 228 free(*proto); … … 225 233 } 226 234 227 /** Register sthe device.228 * 229 * Create s new device entry in the cache or updatesthe protocol address if the235 /** Register the device. 236 * 237 * Create new device entry in the cache or update the protocol address if the 230 238 * device with the device identifier and the driver service exists. 231 239 * 232 * @param[in] device_id The device identifier. 233 * @param[in] service The device driver service. 234 * @param[in] protocol The protocol service. 235 * @param[in] address The actual device protocol address. 236 * @return EOK on success. 237 * @return EEXIST if another device with the same device identifier 238 * and different driver service exists. 239 * @return ENOMEM if there is not enough memory left. 240 * @return Other error codes as defined for the 241 * measured_strings_return() function. 240 * @param[in] device_id Device identifier. 241 * @param[in] service Device driver service. 242 * @param[in] protocol Protocol service. 243 * @param[in] address Actual device protocol address. 244 * 245 * @return EOK on success. 246 * @return EEXIST if another device with the same device identifier 247 * and different driver service exists. 248 * @return ENOMEM if there is not enough memory left. 249 * @return Other error codes as defined for the 250 * measured_strings_return() function. 251 * 242 252 */ 243 253 static int arp_device_message(device_id_t device_id, services_t service, 244 254 services_t protocol, measured_string_t *address) 245 255 { 246 arp_device_t *device;247 arp_proto_t *proto;248 hw_type_t hardware;249 256 int index; 250 257 int rc; 251 258 252 259 fibril_mutex_lock(&arp_globals.lock); 253 260 254 261 /* An existing device? */ 255 device = arp_cache_find(&arp_globals.cache, device_id); 256 262 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 257 263 if (device) { 258 264 if (device->service != service) { 259 printf("Device %d already exists\n", device->device_id); 265 printf("%s: Device %d already exists\n", NAME, 266 device->device_id); 260 267 fibril_mutex_unlock(&arp_globals.lock); 261 268 return EEXIST; 262 269 } 263 proto = arp_protos_find(&device->protos, protocol); 270 271 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 264 272 if (proto) { 265 273 free(proto->addr); … … 273 281 return rc; 274 282 } 283 275 284 index = arp_protos_add(&device->protos, proto->service, 276 285 proto); … … 280 289 return index; 281 290 } 282 printf("New protocol added:\n\tdevice id\t= " 283 "%d\n\tproto\t= %d", device_id, protocol); 291 292 printf("%s: New protocol added (id: %d, proto: %d)\n", NAME, 293 device_id, protocol); 284 294 } 285 295 } else { 286 h ardware = hardware_map(service);296 hw_type_t hardware = hardware_map(service); 287 297 if (!hardware) 288 298 return ENOENT; 289 299 290 /* Create anew device */300 /* Create new device */ 291 301 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 292 302 if (!device) { … … 294 304 return ENOMEM; 295 305 } 306 296 307 device->hardware = hardware; 297 308 device->device_id = device_id; … … 302 313 return rc; 303 314 } 315 316 arp_proto_t *proto; 304 317 rc = arp_proto_create(&proto, protocol, address); 305 318 if (rc != EOK) { … … 308 321 return rc; 309 322 } 323 310 324 index = arp_protos_add(&device->protos, proto->service, proto); 311 325 if (index < 0) { … … 315 329 return index; 316 330 } 331 317 332 device->service = service; 318 333 319 /* Bind the new one*/334 /* Bind */ 320 335 device->phone = nil_bind_service(device->service, 321 336 (sysarg_t) device->device_id, SERVICE_ARP, … … 376 391 device->service, protocol); 377 392 } 393 378 394 fibril_mutex_unlock(&arp_globals.lock); 379 380 395 return EOK; 381 396 } 382 397 383 /** Initialize sthe ARP module.398 /** Initialize the ARP module. 384 399 * 385 400 * @param[in] client_connection The client connection processing function. 386 * The module skeleton propagates its own one. 387 * @return EOK on success. 388 * @return ENOMEM if there is not enough memory left. 401 * The module skeleton propagates its own one. 402 * 403 * @return EOK on success. 404 * @return ENOMEM if there is not enough memory left. 405 * 389 406 */ 390 407 int arp_initialize(async_client_conn_t client_connection) 391 408 { 392 int rc;393 394 409 fibril_mutex_initialize(&arp_globals.lock); 410 395 411 fibril_mutex_lock(&arp_globals.lock); 396 412 arp_globals.client_connection = client_connection; 397 rc = arp_cache_initialize(&arp_globals.cache);413 int rc = arp_cache_initialize(&arp_globals.cache); 398 414 fibril_mutex_unlock(&arp_globals.lock); 399 415 … … 401 417 } 402 418 403 /** Updates the device content length according to the new MTU value. 404 * 405 * @param[in] device_id The device identifier. 406 * @param[in] mtu The new mtu value. 407 * @return ENOENT if device is not found. 408 * @return EOK on success. 419 /** Update the device content length according to the new MTU value. 420 * 421 * @param[in] device_id Device identifier. 422 * @param[in] mtu New MTU value. 423 * 424 * @return ENOENT if device is not found. 425 * @return EOK on success. 426 * 409 427 */ 410 428 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 411 429 { 412 arp_device_t *device;413 414 430 fibril_mutex_lock(&arp_globals.lock); 415 device = arp_cache_find(&arp_globals.cache, device_id); 431 432 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 416 433 if (!device) { 417 434 fibril_mutex_unlock(&arp_globals.lock); 418 435 return ENOENT; 419 436 } 437 420 438 device->packet_dimension.content = mtu; 439 421 440 fibril_mutex_unlock(&arp_globals.lock); 422 printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu); 441 442 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 443 423 444 return EOK; 424 445 } 425 446 426 /** Process esthe received ARP packet.427 * 428 * Update sthe source hardware address if the source entry exists or the packet447 /** Process the received ARP packet. 448 * 449 * Update the source hardware address if the source entry exists or the packet 429 450 * is targeted to my protocol address. 430 * Responses to the ARP request if the packet is the ARP request and is 451 * 452 * Respond to the ARP request if the packet is the ARP request and is 431 453 * targeted to my address. 432 454 * 433 * @param[in] device_id The source device identifier. 434 * @param[in,out] packet The received packet. 435 * @return EOK on success and the packet is no longer needed. 436 * @return One on success and the packet has been reused. 437 * @return EINVAL if the packet is too small to carry an ARP 438 * packet. 439 * @return EINVAL if the received address lengths differs from 440 * the registered values. 441 * @return ENOENT if the device is not found in the cache. 442 * @return ENOENT if the protocol for the device is not found in 443 * the cache. 444 * @return ENOMEM if there is not enough memory left. 455 * @param[in] device_id Source device identifier. 456 * @param[in,out] packet Received packet. 457 * 458 * @return EOK on success and the packet is no longer needed. 459 * @return One on success and the packet has been reused. 460 * @return EINVAL if the packet is too small to carry an ARP 461 * packet. 462 * @return EINVAL if the received address lengths differs from 463 * the registered values. 464 * @return ENOENT if the device is not found in the cache. 465 * @return ENOENT if the protocol for the device is not found in 466 * the cache. 467 * @return ENOMEM if there is not enough memory left. 468 * 445 469 */ 446 470 static int arp_receive_message(device_id_t device_id, packet_t *packet) 447 471 { 448 size_t length;449 arp_header_t *header;450 arp_device_t *device;451 arp_proto_t *proto;452 arp_trans_t *trans;453 uint8_t *src_hw;454 uint8_t *src_proto;455 uint8_t *des_hw;456 uint8_t *des_proto;457 472 int rc; 458 473 459 length = packet_get_data_length(packet);474 size_t length = packet_get_data_length(packet); 460 475 if (length <= sizeof(arp_header_t)) 461 476 return EINVAL; 462 463 device = arp_cache_find(&arp_globals.cache, device_id);477 478 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 464 479 if (!device) 465 480 return ENOENT; 466 467 header = (arp_header_t *) packet_get_data(packet);481 482 arp_header_t *header = (arp_header_t *) packet_get_data(packet); 468 483 if ((ntohs(header->hardware) != device->hardware) || 469 484 (length < sizeof(arp_header_t) + header->hardware_length * 2U + … … 471 486 return EINVAL; 472 487 } 473 474 proto = arp_protos_find(&device->protos,488 489 arp_proto_t *proto = arp_protos_find(&device->protos, 475 490 protocol_unmap(device->service, ntohs(header->protocol))); 476 491 if (!proto) 477 492 return ENOENT; 478 479 src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 480 src_proto = src_hw + header->hardware_length; 481 des_hw = src_proto + header->protocol_length; 482 des_proto = des_hw + header->hardware_length; 483 trans = arp_addr_find(&proto->addresses, src_proto, 493 494 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 495 uint8_t *src_proto = src_hw + header->hardware_length; 496 uint8_t *des_hw = src_proto + header->protocol_length; 497 uint8_t *des_proto = des_hw + header->hardware_length; 498 499 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto, 484 500 header->protocol_length); 485 /* Exists? */ 486 if (trans && trans->hw_addr) { 501 502 if ((trans) && (trans->hw_addr)) { 503 /* Translation exists */ 487 504 if (trans->hw_addr->length != header->hardware_length) 488 505 return EINVAL; 506 489 507 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 490 508 } 509 491 510 /* Is my protocol address? */ 492 511 if (proto->addr->length != header->protocol_length) … … 494 513 495 514 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 496 /* Not already updated? */497 515 if (!trans) { 516 /* Update the translation */ 498 517 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 499 518 if (!trans) 500 519 return ENOMEM; 520 501 521 trans->hw_addr = NULL; 502 522 fibril_condvar_initialize(&trans->cv); … … 508 528 } 509 529 } 530 510 531 if (!trans->hw_addr) { 511 532 trans->hw_addr = measured_string_create_bulk(src_hw, … … 517 538 fibril_condvar_broadcast(&trans->cv); 518 539 } 540 519 541 if (ntohs(header->operation) == ARPOP_REQUEST) { 520 542 header->operation = htons(ARPOP_REPLY); … … 537 559 } 538 560 } 539 561 540 562 return EOK; 541 563 } … … 566 588 header->protocol_length = (uint8_t) proto->addr->length; 567 589 header->operation = htons(ARPOP_REQUEST); 590 568 591 length = sizeof(arp_header_t); 592 569 593 memcpy(((uint8_t *) header) + length, device->addr->value, 570 594 device->addr->length); … … 603 627 * 604 628 */ 605 static int 606 arp_translate_message(device_id_t device_id, services_t protocol, 629 static int arp_translate_message(device_id_t device_id, services_t protocol, 607 630 measured_string_t *target, measured_string_t **translation) 608 631 { 609 arp_device_t *device;610 arp_proto_t *proto;611 arp_trans_t *trans;612 632 bool retry = false; 613 633 int rc; … … 617 637 return EBADMEM; 618 638 619 device = arp_cache_find(&arp_globals.cache, device_id);639 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 620 640 if (!device) 621 641 return ENOENT; 622 642 623 proto = arp_protos_find(&device->protos, protocol);643 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 624 644 if ((!proto) || (proto->addr->length != target->length)) 625 645 return ENOENT; 626 646 627 trans = arp_addr_find(&proto->addresses, target->value, target->length); 647 arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value, 648 target->length); 628 649 if (trans) { 629 650 if (trans->hw_addr) { … … 632 653 } 633 654 634 if (retry) 655 if (retry) { 656 /* Remove the translation from the map */ 657 arp_clear_trans(trans); 658 arp_addr_exclude(&proto->addresses, target->value, 659 target->length); 635 660 return EAGAIN; 636 637 rc = arp_send_request(device_id, protocol, target, device, proto); 638 if (rc != EOK) 639 return rc; 661 } 640 662 641 663 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, … … 654 676 if (!trans) 655 677 return ENOMEM; 678 656 679 trans->hw_addr = NULL; 657 680 fibril_condvar_initialize(&trans->cv); 681 658 682 rc = arp_addr_add(&proto->addresses, target->value, target->length, 659 683 trans); … … 676 700 } 677 701 678 679 /** Processes the ARP message. 680 * 681 * @param[in] callid The message identifier. 682 * @param[in] call The message parameters. 683 * @param[out] answer The message answer parameters. 684 * @param[out] answer_count The last parameter for the actual answer in the 685 * answer parameter. 686 * @return EOK on success. 687 * @return ENOTSUP if the message is not known. 702 /** Process the ARP message. 703 * 704 * @param[in] callid Message identifier. 705 * @param[in] call Message parameters. 706 * @param[out] answer Answer. 707 * @param[out] count Number of arguments of the answer. 708 * 709 * @return EOK on success. 710 * @return ENOTSUP if the message is not known. 688 711 * 689 712 * @see arp_interface.h 690 713 * @see IS_NET_ARP_MESSAGE() 691 * /692 int 693 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,694 ipc_call_t *answer, size_t *answer_count)714 * 715 */ 716 int arp_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 717 size_t *count) 695 718 { 696 719 measured_string_t *address; … … 701 724 int rc; 702 725 703 * answer_count = 0;726 *count = 0; 704 727 switch (IPC_GET_IMETHOD(*call)) { 705 728 case IPC_M_PHONE_HUNGUP: … … 717 740 free(data); 718 741 } 742 719 743 return rc; 720 744 … … 729 753 free(address); 730 754 free(data); 755 731 756 if (rc != EOK) { 732 757 fibril_mutex_unlock(&arp_globals.lock); 733 758 return rc; 734 759 } 760 735 761 if (!translation) { 736 762 fibril_mutex_unlock(&arp_globals.lock); 737 763 return ENOENT; 738 764 } 765 739 766 rc = measured_strings_reply(translation, 1); 740 767 fibril_mutex_unlock(&arp_globals.lock); 741 768 return rc; 742 769 743 770 case NET_ARP_CLEAR_DEVICE: 744 771 return arp_clear_device_req(0, IPC_GET_DEVICE(*call)); 745 772 746 773 case NET_ARP_CLEAR_ADDRESS: 747 774 rc = measured_strings_receive(&address, &data, 1); … … 793 820 /** Default thread for new connections. 794 821 * 795 * @param[in] iid The initial message identifier.796 * @param[in] icall The initial message call structure.822 * @param[in] iid Initial message identifier. 823 * @param[in] icall Initial message call structure. 797 824 */ 798 825 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall) … … 816 843 817 844 /* Process the message */ 818 int res = il_module_message _standalone(callid, &call, &answer,845 int res = il_module_message(callid, &call, &answer, 819 846 &count); 820 847 … … 832 859 } 833 860 834 /** Starts the module.835 *836 * @return EOK on success.837 * @return Other error codes as defined for each specific module838 * start function.839 */840 861 int main(int argc, char *argv[]) 841 862 { 842 int rc;843 844 863 /* Start the module */ 845 rc = il_module_start_standalone(il_client_connection); 846 return rc; 864 return il_module_start(il_client_connection); 847 865 } 848 866 849 867 /** @} 850 868 */ 851
Note:
See TracChangeset
for help on using the changeset viewer.