Changes in uspace/srv/net/il/arp/arp.c [7837101:1bfd3d3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
r7837101 r1bfd3d3 72 72 #define NAME "arp" 73 73 74 /** Number of microseconds to wait for an ARP reply. */75 #define ARP_TRANS_WAIT 100000076 77 74 /** ARP global data. */ 78 75 arp_globals_t arp_globals; … … 80 77 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t); 81 78 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t); 82 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t); 83 84 static void arp_clear_trans(arp_trans_t *trans) 85 { 86 if (trans->hw_addr) { 87 free(trans->hw_addr); 88 trans->hw_addr = NULL; 89 } 90 fibril_condvar_broadcast(&trans->cv); 91 } 92 93 static void arp_clear_addr(arp_addr_t *addresses) 94 { 95 int count; 96 arp_trans_t *trans; 97 98 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 99 trans = arp_addr_items_get_index(&addresses->values, count); 100 if (trans) 101 arp_clear_trans(trans); 102 } 103 } 104 79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t); 105 80 106 81 /** Clears the device specific data. … … 121 96 if (proto->addr_data) 122 97 free(proto->addr_data); 123 arp_clear_addr(&proto->addresses);124 98 arp_addr_destroy(&proto->addresses); 125 99 } … … 133 107 arp_device_t *device; 134 108 135 fibril_ mutex_lock(&arp_globals.lock);109 fibril_rwlock_write_lock(&arp_globals.lock); 136 110 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 137 111 count--) { … … 146 120 } 147 121 arp_cache_clear(&arp_globals.cache); 148 fibril_ mutex_unlock(&arp_globals.lock);122 fibril_rwlock_write_unlock(&arp_globals.lock); 149 123 printf("Cache cleaned\n"); 150 124 return EOK; … … 156 130 arp_device_t *device; 157 131 arp_proto_t *proto; 158 arp_trans_t *trans; 159 160 fibril_mutex_lock(&arp_globals.lock); 132 133 fibril_rwlock_write_lock(&arp_globals.lock); 161 134 device = arp_cache_find(&arp_globals.cache, device_id); 162 135 if (!device) { 163 fibril_ mutex_unlock(&arp_globals.lock);136 fibril_rwlock_write_unlock(&arp_globals.lock); 164 137 return ENOENT; 165 138 } 166 139 proto = arp_protos_find(&device->protos, protocol); 167 140 if (!proto) { 168 fibril_ mutex_unlock(&arp_globals.lock);141 fibril_rwlock_write_unlock(&arp_globals.lock); 169 142 return ENOENT; 170 143 } 171 trans = arp_addr_find(&proto->addresses, address->value, address->length);172 if (trans)173 arp_clear_trans(trans);174 144 arp_addr_exclude(&proto->addresses, address->value, address->length); 175 fibril_ mutex_unlock(&arp_globals.lock);145 fibril_rwlock_write_unlock(&arp_globals.lock); 176 146 return EOK; 177 147 } … … 182 152 arp_device_t *device; 183 153 184 fibril_ mutex_lock(&arp_globals.lock);154 fibril_rwlock_write_lock(&arp_globals.lock); 185 155 device = arp_cache_find(&arp_globals.cache, device_id); 186 156 if (!device) { 187 fibril_ mutex_unlock(&arp_globals.lock);157 fibril_rwlock_write_unlock(&arp_globals.lock); 188 158 return ENOENT; 189 159 } 190 160 arp_clear_device(device); 191 161 printf("Device %d cleared\n", device_id); 192 fibril_ mutex_unlock(&arp_globals.lock);162 fibril_rwlock_write_unlock(&arp_globals.lock); 193 163 return EOK; 194 164 } … … 251 221 int rc; 252 222 253 fibril_ mutex_lock(&arp_globals.lock);223 fibril_rwlock_write_lock(&arp_globals.lock); 254 224 255 225 /* An existing device? */ … … 259 229 if (device->service != service) { 260 230 printf("Device %d already exists\n", device->device_id); 261 fibril_ mutex_unlock(&arp_globals.lock);231 fibril_rwlock_write_unlock(&arp_globals.lock); 262 232 return EEXIST; 263 233 } … … 271 241 rc = arp_proto_create(&proto, protocol, address); 272 242 if (rc != EOK) { 273 fibril_ mutex_unlock(&arp_globals.lock);243 fibril_rwlock_write_unlock(&arp_globals.lock); 274 244 return rc; 275 245 } … … 277 247 proto); 278 248 if (index < 0) { 279 fibril_ mutex_unlock(&arp_globals.lock);249 fibril_rwlock_write_unlock(&arp_globals.lock); 280 250 free(proto); 281 251 return index; … … 292 262 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 293 263 if (!device) { 294 fibril_ mutex_unlock(&arp_globals.lock);264 fibril_rwlock_write_unlock(&arp_globals.lock); 295 265 return ENOMEM; 296 266 } … … 299 269 rc = arp_protos_initialize(&device->protos); 300 270 if (rc != EOK) { 301 fibril_ mutex_unlock(&arp_globals.lock);271 fibril_rwlock_write_unlock(&arp_globals.lock); 302 272 free(device); 303 273 return rc; … … 305 275 rc = arp_proto_create(&proto, protocol, address); 306 276 if (rc != EOK) { 307 fibril_ mutex_unlock(&arp_globals.lock);277 fibril_rwlock_write_unlock(&arp_globals.lock); 308 278 free(device); 309 279 return rc; … … 311 281 index = arp_protos_add(&device->protos, proto->service, proto); 312 282 if (index < 0) { 313 fibril_ mutex_unlock(&arp_globals.lock);283 fibril_rwlock_write_unlock(&arp_globals.lock); 314 284 arp_protos_destroy(&device->protos); 315 285 free(device); … … 320 290 /* Bind the new one */ 321 291 device->phone = nil_bind_service(device->service, 322 ( sysarg_t) device->device_id, SERVICE_ARP,292 (ipcarg_t) device->device_id, SERVICE_ARP, 323 293 arp_globals.client_connection); 324 294 if (device->phone < 0) { 325 fibril_ mutex_unlock(&arp_globals.lock);295 fibril_rwlock_write_unlock(&arp_globals.lock); 326 296 arp_protos_destroy(&device->protos); 327 297 free(device); … … 333 303 &device->packet_dimension); 334 304 if (rc != EOK) { 335 fibril_ mutex_unlock(&arp_globals.lock);305 fibril_rwlock_write_unlock(&arp_globals.lock); 336 306 arp_protos_destroy(&device->protos); 337 307 free(device); … … 343 313 &device->addr_data); 344 314 if (rc != EOK) { 345 fibril_ mutex_unlock(&arp_globals.lock);315 fibril_rwlock_write_unlock(&arp_globals.lock); 346 316 arp_protos_destroy(&device->protos); 347 317 free(device); … … 353 323 &device->broadcast_addr, &device->broadcast_data); 354 324 if (rc != EOK) { 355 fibril_ mutex_unlock(&arp_globals.lock);325 fibril_rwlock_write_unlock(&arp_globals.lock); 356 326 free(device->addr); 357 327 free(device->addr_data); … … 364 334 device); 365 335 if (rc != EOK) { 366 fibril_ mutex_unlock(&arp_globals.lock);336 fibril_rwlock_write_unlock(&arp_globals.lock); 367 337 free(device->addr); 368 338 free(device->addr_data); … … 377 347 device->service, protocol); 378 348 } 379 fibril_ mutex_unlock(&arp_globals.lock);349 fibril_rwlock_write_unlock(&arp_globals.lock); 380 350 381 351 return EOK; … … 393 363 int rc; 394 364 395 fibril_ mutex_initialize(&arp_globals.lock);396 fibril_ mutex_lock(&arp_globals.lock);365 fibril_rwlock_initialize(&arp_globals.lock); 366 fibril_rwlock_write_lock(&arp_globals.lock); 397 367 arp_globals.client_connection = client_connection; 398 368 rc = arp_cache_initialize(&arp_globals.cache); 399 fibril_ mutex_unlock(&arp_globals.lock);369 fibril_rwlock_write_unlock(&arp_globals.lock); 400 370 401 371 return rc; … … 413 383 arp_device_t *device; 414 384 415 fibril_ mutex_lock(&arp_globals.lock);385 fibril_rwlock_write_lock(&arp_globals.lock); 416 386 device = arp_cache_find(&arp_globals.cache, device_id); 417 387 if (!device) { 418 fibril_ mutex_unlock(&arp_globals.lock);388 fibril_rwlock_write_unlock(&arp_globals.lock); 419 389 return ENOENT; 420 390 } 421 391 device->packet_dimension.content = mtu; 422 fibril_ mutex_unlock(&arp_globals.lock);423 printf("arp - device %d changed mtu to % zu\n\n", device_id, mtu);392 fibril_rwlock_write_unlock(&arp_globals.lock); 393 printf("arp - device %d changed mtu to %d\n\n", device_id, mtu); 424 394 return EOK; 425 395 } … … 445 415 * @return ENOMEM if there is not enough memory left. 446 416 */ 447 static int arp_receive_message(device_id_t device_id, packet_t *packet)417 static int arp_receive_message(device_id_t device_id, packet_t packet) 448 418 { 449 419 size_t length; … … 451 421 arp_device_t *device; 452 422 arp_proto_t *proto; 453 arp_trans_t *trans;423 measured_string_t *hw_source; 454 424 uint8_t *src_hw; 455 425 uint8_t *src_proto; … … 482 452 des_hw = src_proto + header->protocol_length; 483 453 des_proto = des_hw + header->hardware_length; 484 trans= arp_addr_find(&proto->addresses, (char *) src_proto,485 header->protocol_length);454 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, 455 CONVERT_SIZE(uint8_t, char, header->protocol_length)); 486 456 /* Exists? */ 487 if (trans && trans->hw_addr) { 488 if (trans->hw_addr->length != header->hardware_length) 457 if (hw_source) { 458 if (hw_source->length != CONVERT_SIZE(uint8_t, char, 459 header->hardware_length)) { 489 460 return EINVAL; 490 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 461 } 462 memcpy(hw_source->value, src_hw, hw_source->length); 491 463 } 492 464 /* Is my protocol address? */ 493 if (proto->addr->length != header->protocol_length) 465 if (proto->addr->length != CONVERT_SIZE(uint8_t, char, 466 header->protocol_length)) { 494 467 return EINVAL; 468 } 495 469 if (!str_lcmp(proto->addr->value, (char *) des_proto, 496 470 proto->addr->length)) { 497 471 /* Not already updated? */ 498 if (!trans) { 499 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 500 if (!trans) 472 if (!hw_source) { 473 hw_source = measured_string_create_bulk((char *) src_hw, 474 CONVERT_SIZE(uint8_t, char, 475 header->hardware_length)); 476 if (!hw_source) 501 477 return ENOMEM; 502 trans->hw_addr = NULL; 503 fibril_condvar_initialize(&trans->cv); 478 504 479 rc = arp_addr_add(&proto->addresses, (char *) src_proto, 505 header->protocol_length, trans);506 if (rc != EOK) {507 /* The generic char map has already freed trans! */480 CONVERT_SIZE(uint8_t, char, 481 header->protocol_length), hw_source); 482 if (rc != EOK) 508 483 return rc; 509 }510 }511 if (!trans->hw_addr) {512 trans->hw_addr = measured_string_create_bulk(513 (char *) src_hw, header->hardware_length);514 if (!trans->hw_addr)515 return ENOMEM;516 517 /* Notify the fibrils that wait for the translation. */518 fibril_condvar_broadcast(&trans->cv);519 484 } 520 485 if (ntohs(header->operation) == ARPOP_REQUEST) { … … 525 490 memcpy(src_hw, device->addr->value, 526 491 device->packet_dimension.addr_len); 527 memcpy(des_hw, trans->hw_addr->value,492 memcpy(des_hw, hw_source->value, 528 493 header->hardware_length); 529 494 … … 551 516 * @param[in] protocol The protocol service. 552 517 * @param[in] target The target protocol address. 553 * @param[out] translation Where the hardware address of the target is stored. 554 * @return EOK on success. 555 * @return EAGAIN if the caller should try again. 556 * @return Other error codes in case of error. 557 */ 558 static int 518 * @return The hardware address of the target. 519 * @return NULL if the target parameter is NULL. 520 * @return NULL if the device is not found. 521 * @return NULL if the device packet is too small to send a 522 * request. 523 * @return NULL if the hardware address is not found in the cache. 524 */ 525 static measured_string_t * 559 526 arp_translate_message(device_id_t device_id, services_t protocol, 560 measured_string_t *target , measured_string_t **translation)527 measured_string_t *target) 561 528 { 562 529 arp_device_t *device; 563 530 arp_proto_t *proto; 564 arp_trans_t *trans;531 measured_string_t *addr; 565 532 size_t length; 566 packet_t *packet;533 packet_t packet; 567 534 arp_header_t *header; 568 bool retry = false; 569 int rc; 570 571 restart: 572 if (!target || !translation) 573 return EBADMEM; 535 536 if (!target) 537 return NULL; 574 538 575 539 device = arp_cache_find(&arp_globals.cache, device_id); 576 540 if (!device) 577 return ENOENT;541 return NULL; 578 542 579 543 proto = arp_protos_find(&device->protos, protocol); 580 544 if (!proto || (proto->addr->length != target->length)) 581 return ENOENT; 582 583 trans = arp_addr_find(&proto->addresses, target->value, target->length); 584 if (trans) { 585 if (trans->hw_addr) { 586 *translation = trans->hw_addr; 587 return EOK; 588 } 589 if (retry) 590 return EAGAIN; 591 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 592 ARP_TRANS_WAIT); 593 if (rc == ETIMEOUT) 594 return ENOENT; 595 retry = true; 596 goto restart; 597 } 598 if (retry) 599 return EAGAIN; 545 return NULL; 546 547 addr = arp_addr_find(&proto->addresses, target->value, target->length); 548 if (addr) 549 return addr; 600 550 601 551 /* ARP packet content size = header + (address + translation) * 2 */ 602 length = 8 + 2 * (proto->addr->length + device->addr->length); 552 length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) + 553 CONVERT_SIZE(char, uint8_t, device->addr->length)); 603 554 if (length > device->packet_dimension.content) 604 return ELIMIT;555 return NULL; 605 556 606 557 packet = packet_get_4_remote(arp_globals.net_phone, … … 608 559 length, device->packet_dimension.suffix); 609 560 if (!packet) 610 return ENOMEM;561 return NULL; 611 562 612 563 header = (arp_header_t *) packet_suffix(packet, length); 613 564 if (!header) { 614 565 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 615 return ENOMEM;566 return NULL; 616 567 } 617 568 … … 632 583 memcpy(((uint8_t *) header) + length, target->value, target->length); 633 584 634 rc =packet_set_addr(packet, (uint8_t *) device->addr->value,635 (uint8_t *) device->broadcast_addr->value, device->addr->length);636 if (rc!= EOK) {585 if (packet_set_addr(packet, (uint8_t *) device->addr->value, 586 (uint8_t *) device->broadcast_addr->value, 587 CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) { 637 588 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 638 return rc;589 return NULL; 639 590 } 640 591 641 592 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 642 643 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 644 if (!trans) 645 return ENOMEM; 646 trans->hw_addr = NULL; 647 fibril_condvar_initialize(&trans->cv); 648 rc = arp_addr_add(&proto->addresses, target->value, target->length, 649 trans); 650 if (rc != EOK) { 651 /* The generic char map has already freed trans! */ 652 return rc; 653 } 654 655 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 656 ARP_TRANS_WAIT); 657 if (rc == ETIMEOUT) 658 return ENOENT; 659 retry = true; 660 goto restart; 593 return NULL; 661 594 } 662 595 … … 682 615 measured_string_t *translation; 683 616 char *data; 684 packet_t *packet;685 packet_t *next;617 packet_t packet; 618 packet_t next; 686 619 int rc; 687 620 688 621 *answer_count = 0; 689 switch (IPC_GET_ IMETHOD(*call)) {622 switch (IPC_GET_METHOD(*call)) { 690 623 case IPC_M_PHONE_HUNGUP: 691 624 return EOK; … … 709 642 return rc; 710 643 711 fibril_ mutex_lock(&arp_globals.lock);712 rc= arp_translate_message(IPC_GET_DEVICE(call),713 IPC_GET_SERVICE(call), address , &translation);644 fibril_rwlock_read_lock(&arp_globals.lock); 645 translation = arp_translate_message(IPC_GET_DEVICE(call), 646 IPC_GET_SERVICE(call), address); 714 647 free(address); 715 648 free(data); 716 if (rc != EOK) {717 fibril_mutex_unlock(&arp_globals.lock);718 return rc;719 }720 649 if (!translation) { 721 fibril_ mutex_unlock(&arp_globals.lock);650 fibril_rwlock_read_unlock(&arp_globals.lock); 722 651 return ENOENT; 723 652 } 724 653 rc = measured_strings_reply(translation, 1); 725 fibril_ mutex_unlock(&arp_globals.lock);654 fibril_rwlock_read_unlock(&arp_globals.lock); 726 655 return rc; 727 656 … … 753 682 return rc; 754 683 755 fibril_ mutex_lock(&arp_globals.lock);684 fibril_rwlock_read_lock(&arp_globals.lock); 756 685 do { 757 686 next = pq_detach(packet); … … 763 692 packet = next; 764 693 } while (packet); 765 fibril_ mutex_unlock(&arp_globals.lock);694 fibril_rwlock_read_unlock(&arp_globals.lock); 766 695 767 696 return EOK; … … 807 736 * result. 808 737 */ 809 if ((IPC_GET_ IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||738 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 810 739 (res == EHANGUP)) 811 740 return;
Note:
See TracChangeset
for help on using the changeset viewer.