aboutsummaryrefslogtreecommitdiff
path: root/src/ats/gnunet-service-ats-solver_proportional.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2013-06-07 13:13:09 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2013-06-07 13:13:09 +0000
commit9c9196222870c908b7b3391880bb9787e8880808 (patch)
tree7171b3ba97e268a711e3c15048beea66c5b2dce8 /src/ats/gnunet-service-ats-solver_proportional.c
parenta819c7cd70f869e374dd2c515c19ff8cd4204359 (diff)
downloadgnunet-9c9196222870c908b7b3391880bb9787e8880808.tar.gz
gnunet-9c9196222870c908b7b3391880bb9787e8880808.zip
restructure
Diffstat (limited to 'src/ats/gnunet-service-ats-solver_proportional.c')
-rw-r--r--src/ats/gnunet-service-ats-solver_proportional.c1023
1 files changed, 537 insertions, 486 deletions
diff --git a/src/ats/gnunet-service-ats-solver_proportional.c b/src/ats/gnunet-service-ats-solver_proportional.c
index 1632e6fc0..474806c44 100644
--- a/src/ats/gnunet-service-ats-solver_proportional.c
+++ b/src/ats/gnunet-service-ats-solver_proportional.c
@@ -214,7 +214,7 @@
214/** 214/**
215 * A handle for the simplistic solver 215 * A handle for the simplistic solver
216 */ 216 */
217struct GAS_SIMPLISTIC_Handle 217struct GAS_PROPORTIONAL_Handle
218{ 218{
219 /** 219 /**
220 * Statistics handle 220 * Statistics handle
@@ -258,6 +258,9 @@ struct GAS_SIMPLISTIC_Handle
258 struct PreferenceClient *pc_tail; 258 struct PreferenceClient *pc_tail;
259}; 259};
260 260
261/**
262 * Representation of a network
263 */
261struct Network 264struct Network
262{ 265{
263 /** 266 /**
@@ -306,6 +309,7 @@ struct Network
306 struct AddressWrapper *tail; 309 struct AddressWrapper *tail;
307}; 310};
308 311
312
309struct AddressWrapper 313struct AddressWrapper
310{ 314{
311 struct AddressWrapper *next; 315 struct AddressWrapper *next;
@@ -333,7 +337,7 @@ struct PreferencePeer
333 struct PreferencePeer *next; 337 struct PreferencePeer *next;
334 struct PreferencePeer *prev; 338 struct PreferencePeer *prev;
335 struct PreferenceClient *client; 339 struct PreferenceClient *client;
336 struct GAS_SIMPLISTIC_Handle *s; 340 struct GAS_PROPORTIONAL_Handle *s;
337 struct GNUNET_PeerIdentity id; 341 struct GNUNET_PeerIdentity id;
338 342
339 double f[GNUNET_ATS_PreferenceCount]; 343 double f[GNUNET_ATS_PreferenceCount];
@@ -343,78 +347,43 @@ struct PreferencePeer
343 GNUNET_SCHEDULER_TaskIdentifier aging_task; 347 GNUNET_SCHEDULER_TaskIdentifier aging_task;
344}; 348};
345 349
346/**
347 * Get the prefered address for a specific peer
348 *
349 * @param solver the solver handle
350 * @param addresses the address hashmap containing all addresses
351 * @param peer the identity of the peer
352 */
353const struct ATS_Address *
354GAS_simplistic_get_preferred_address (void *solver,
355 struct GNUNET_CONTAINER_MultiHashMap * addresses,
356 const struct GNUNET_PeerIdentity *peer);
357
358
359 350
360/** 351/**
361 * Important solver functions 352 * Important solver functions
362 * --------------------------- 353 * ---------------------------
363 */ 354 */
364 355
365
366
367
368/** 356/**
369 * Helper functions 357 * Test if bandwidth is available in this network to add an additional address
370 * ---------------------------
371 */
372
373static int
374free_pref (void *cls,
375 const struct GNUNET_HashCode * key,
376 void *value)
377{
378 float *v = value;
379 GNUNET_free (v);
380 return GNUNET_OK;
381}
382
383
384
385
386/**
387 * Test if bandwidth is available in this network
388 * 358 *
389 * @param net the network type to update 359 * @param net the network type to update
390 * @return GNUNET_YES or GNUNET_NO 360 * @return GNUNET_YES or GNUNET_NO
391 */ 361 */
392
393static int 362static int
394bw_available_in_network (struct Network *net) 363is_bandwidth_available_in_network (struct Network *net)
395{ 364{
396 unsigned int na = net->active_addresses + 1; 365 unsigned int na = net->active_addresses + 1;
397 uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); 366 uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
398 if (((net->total_quota_in / na) > min_bw) && 367 if (((net->total_quota_in / na) > min_bw) &&
399 ((net->total_quota_out / na) > min_bw)) 368 ((net->total_quota_out / na) > min_bw))
400 { 369 {
401 LOG (GNUNET_ERROR_TYPE_DEBUG, 370 LOG (GNUNET_ERROR_TYPE_DEBUG,
402 "Enough bandwidth available for %u active addresses in network `%s'\n", 371 "Enough bandwidth available for %u active addresses in network `%s'\n",
403 na, 372 na,
404 net->desc); 373 net->desc);
405 374
406 return GNUNET_YES; 375 return GNUNET_YES;
407 } 376 }
408 LOG (GNUNET_ERROR_TYPE_DEBUG, 377 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 "Not enough bandwidth available for %u active addresses in network `%s'\n", 378 "Not enough bandwidth available for %u active addresses in network `%s'\n",
410 na, 379 na,
411 net->desc); 380 net->desc);
412 return GNUNET_NO; 381 return GNUNET_NO;
413} 382}
414 383
415 384
416/** 385/**
417 * Update the quotas for a network type 386 * Update bandwidth assigned to peers in this network
418 * 387 *
419 * @param s the solver handle 388 * @param s the solver handle
420 * @param net the network type to update 389 * @param net the network type to update
@@ -422,7 +391,7 @@ bw_available_in_network (struct Network *net)
422 * this address 391 * this address
423 */ 392 */
424static void 393static void
425update_quota_per_network (struct GAS_SIMPLISTIC_Handle *s, 394update_quota_per_network (struct GAS_PROPORTIONAL_Handle *s,
426 struct Network *net, 395 struct Network *net,
427 struct ATS_Address *address_except) 396 struct ATS_Address *address_except)
428{ 397{
@@ -548,8 +517,21 @@ update_quota_per_network (struct GAS_SIMPLISTIC_Handle *s,
548 } 517 }
549} 518}
550 519
520
521
522/**
523 * Helper functions
524 * ---------------------------
525 */
526
527
528/**
529 * Update bandwidth assignment for all networks
530 *
531 * @param s the solver handle
532 */
551static void 533static void
552update_all_networks (struct GAS_SIMPLISTIC_Handle *s) 534update_all_networks (struct GAS_PROPORTIONAL_Handle *s)
553{ 535{
554 int i; 536 int i;
555 for (i = 0; i < s->networks; i++) 537 for (i = 0; i < s->networks; i++)
@@ -557,8 +539,96 @@ update_all_networks (struct GAS_SIMPLISTIC_Handle *s)
557 539
558} 540}
559 541
542
543/**
544 * Lookup network struct by type
545 *
546 * @param s the solver handle
547 * @param type the network type
548 * @return the network struct
549 */
550static struct Network *
551get_network (struct GAS_PROPORTIONAL_Handle *s, uint32_t type)
552{
553 int c;
554 for (c = 0 ; c < s->networks; c++)
555 {
556 if (s->network_entries[c].type == type)
557 return &s->network_entries[c];
558 }
559 return NULL;
560}
561
562
563/**
564 * Hashmap Iterator to find current active address for peer
565 *
566 * @param cls last active address
567 * @param key peer's key
568 * @param value address to check
569 * @return GNUNET_NO on double active address else GNUNET_YES
570 */
571static int
572get_active_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
573{
574 struct ATS_Address * dest = (struct ATS_Address *) (*(struct ATS_Address **)cls);
575 struct ATS_Address * aa = (struct ATS_Address *) value;
576
577 if (GNUNET_YES == aa->active)
578 {
579 if (dest != NULL)
580 {
581 /* should never happen */
582 LOG (GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n", GNUNET_i2s (&aa->peer));
583 GNUNET_break (0);
584 return GNUNET_NO;
585 }
586 dest = aa;
587 }
588 return GNUNET_OK;
589}
590
591/**
592 * Find current active address for peer
593 *
594 * @param solver the solver handle
595 * @param addresses the address set
596 * @param peer the peer
597 * @return active address or NULL
598 */
599static struct ATS_Address *
600get_active_address (void *solver,
601 struct GNUNET_CONTAINER_MultiHashMap * addresses,
602 const struct GNUNET_PeerIdentity *peer)
603{
604 struct ATS_Address * dest = NULL;
605
606 GNUNET_CONTAINER_multihashmap_get_multiple(addresses,
607 &peer->hashPubKey,
608 &get_active_address_it, &dest);
609 return dest;
610}
611
612static int
613free_pref (void *cls,
614 const struct GNUNET_HashCode * key,
615 void *value)
616{
617 float *v = value;
618 GNUNET_free (v);
619 return GNUNET_OK;
620}
621
622
623
624
625
626
627
628
629
560static void 630static void
561addresse_increment (struct GAS_SIMPLISTIC_Handle *s, 631addresse_increment (struct GAS_PROPORTIONAL_Handle *s,
562 struct Network *net, 632 struct Network *net,
563 int total, 633 int total,
564 int active) 634 int active)
@@ -581,7 +651,7 @@ addresse_increment (struct GAS_SIMPLISTIC_Handle *s,
581} 651}
582 652
583static int 653static int
584addresse_decrement (struct GAS_SIMPLISTIC_Handle *s, 654addresse_decrement (struct GAS_PROPORTIONAL_Handle *s,
585 struct Network *net, 655 struct Network *net,
586 int total, 656 int total,
587 int active) 657 int active)
@@ -662,263 +732,10 @@ get_performance_info (struct ATS_Address *address, uint32_t type)
662} 732}
663 733
664 734
665/**
666 * Add a single address within a network to the solver
667 *
668 * @param solver the solver Handle
669 * @param addresses the address hashmap containing all addresses
670 * @param address the address to add
671 * @param network network type of this address
672 */
673void
674GAS_simplistic_address_add (void *solver,
675 struct GNUNET_CONTAINER_MultiHashMap *addresses,
676 struct ATS_Address *address,
677 uint32_t network)
678{
679 struct GAS_SIMPLISTIC_Handle *s = solver;
680 struct Network *net = NULL;
681 struct AddressWrapper *aw = NULL;
682 int c;
683
684 GNUNET_assert (NULL != s);
685 for (c = 0; c < s->networks; c++)
686 {
687 net = &s->network_entries[c];
688 if (network == net->type)
689 break;
690 }
691 if (NULL == net)
692 {
693 GNUNET_break (0);
694 return;
695 }
696
697 aw = GNUNET_malloc (sizeof (struct AddressWrapper));
698 aw->addr = address;
699 GNUNET_CONTAINER_DLL_insert (net->head, net->tail, aw);
700 addresse_increment (s, net, GNUNET_YES, GNUNET_NO);
701 aw->addr->solver_information = net;
702
703 LOG (GNUNET_ERROR_TYPE_DEBUG, "After adding address now total %u and active %u addresses in network `%s'\n",
704 net->total_addresses,
705 net->active_addresses,
706 net->desc);
707}
708
709/**
710 * Remove an address from the solver
711 *
712 * @param solver the solver handle
713 * @param addresses the address hashmap containing all addresses
714 * @param address the address to remove
715 * @param session_only delete only session not whole address
716 */
717void
718GAS_simplistic_address_delete (void *solver,
719 struct GNUNET_CONTAINER_MultiHashMap * addresses,
720 struct ATS_Address *address, int session_only)
721{
722 struct GAS_SIMPLISTIC_Handle *s = solver;
723 struct Network *net;
724 struct AddressWrapper *aw;
725 735
726 /* Remove an adress completely, we have to:
727 * - Remove from specific network
728 * - Decrease number of total addresses
729 * - If active:
730 * - decrease number of active addreses
731 * - update quotas
732 */
733 736
734 net = (struct Network *) address->solver_information;
735 737
736 if (GNUNET_NO == session_only)
737 {
738 LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ active: %u)\n",
739 (GNUNET_NO == address->active) ? "inactive" : "active",
740 address, GNUNET_i2s (&address->peer),
741 net->desc, net->total_addresses, net->active_addresses);
742 738
743 /* Remove address */
744 addresse_decrement (s, net, GNUNET_YES, GNUNET_NO);
745 for (aw = net->head; NULL != aw; aw = aw->next)
746 {
747 if (aw->addr == address)
748 break;
749 }
750 if (NULL == aw )
751 {
752 GNUNET_break (0);
753 return;
754 }
755 GNUNET_CONTAINER_DLL_remove (net->head, net->tail, aw);
756 GNUNET_free (aw);
757 }
758 else
759 {
760 /* Remove session only: remove if active and update */
761 LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ active: %u)\n",
762 (GNUNET_NO == address->active) ? "inactive" : "active",
763 address, GNUNET_i2s (&address->peer),
764 net->desc, net->total_addresses, net->active_addresses);
765 }
766
767 if (GNUNET_YES == address->active)
768 {
769 /* Address was active, remove from network and update quotas*/
770 address->active = GNUNET_NO;
771 if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES))
772 GNUNET_break (0);
773 update_quota_per_network (s, net, NULL);
774 }
775 LOG (GNUNET_ERROR_TYPE_DEBUG, "After deleting address now total %u and active %u addresses in network `%s'\n",
776 net->total_addresses,
777 net->active_addresses,
778 net->desc);
779
780}
781
782static struct Network *
783find_network (struct GAS_SIMPLISTIC_Handle *s, uint32_t type)
784{
785 int c;
786 for (c = 0 ; c < s->networks; c++)
787 {
788 if (s->network_entries[c].type == type)
789 return &s->network_entries[c];
790 }
791 return NULL;
792}
793
794/**
795 * Updates a single address in the solver
796 *
797 * If ATS information was updated, the previous values are passed
798 *
799 * @param solver the solver Handle
800 * @param addresses the address hashmap containing all addresses
801 * @param address the update address
802 * @param session the new session (if changed otherwise current)
803 * @param in_use the new address in use state (if changed otherwise current)
804 * @param prev_ats ATS information
805 * @param prev_atsi_count the atsi count
806 */
807void
808GAS_simplistic_address_update (void *solver,
809 struct GNUNET_CONTAINER_MultiHashMap *addresses,
810 struct ATS_Address *address,
811 uint32_t session,
812 int in_use,
813 const struct GNUNET_ATS_Information *prev_ats,
814 uint32_t prev_atsi_count)
815{
816 struct ATS_Address *new;
817 struct GAS_SIMPLISTIC_Handle *s = (struct GAS_SIMPLISTIC_Handle *) solver;
818 int i;
819 uint32_t prev_value;
820 uint32_t prev_type;
821 uint32_t addr_net;
822 int save_active = GNUNET_NO;
823 struct Network *new_net = NULL;
824 for (i = 0; i < prev_atsi_count; i++)
825 {
826 prev_type = ntohl (prev_ats[i].type);
827 prev_value = ntohl (prev_ats[i].value);
828 switch (prev_type)
829 {
830 case GNUNET_ATS_UTILIZATION_UP:
831 case GNUNET_ATS_UTILIZATION_DOWN:
832 case GNUNET_ATS_QUALITY_NET_DELAY:
833 case GNUNET_ATS_QUALITY_NET_DISTANCE:
834 case GNUNET_ATS_COST_WAN:
835 case GNUNET_ATS_COST_LAN:
836 case GNUNET_ATS_COST_WLAN:
837 /* No actions required here*/
838 break;
839 case GNUNET_ATS_NETWORK_TYPE:
840
841 addr_net = get_performance_info (address, GNUNET_ATS_NETWORK_TYPE);
842 if (GNUNET_ATS_VALUE_UNDEFINED == addr_net)
843 {
844 GNUNET_break (0);
845 addr_net = GNUNET_ATS_NET_UNSPECIFIED;
846 }
847 if (addr_net != prev_value)
848 {
849 /* Network changed */
850 LOG (GNUNET_ERROR_TYPE_DEBUG, "Network type changed, moving %s address from `%s' to `%s'\n",
851 (GNUNET_YES == address->active) ? "active" : "inactive",
852 GNUNET_ATS_print_network_type(prev_value),
853 GNUNET_ATS_print_network_type(addr_net));
854
855 save_active = address->active;
856 /* remove from old network */
857 GAS_simplistic_address_delete (solver, addresses, address, GNUNET_NO);
858
859 /* set new network type */
860 new_net = find_network (solver, addr_net);
861 address->solver_information = new_net;
862
863 /* Add to new network and update*/
864 GAS_simplistic_address_add (solver, addresses, address, addr_net);
865 if (GNUNET_YES == save_active)
866 {
867 /* check if bandwidth available in new network */
868 if (GNUNET_YES == (bw_available_in_network (new_net)))
869 {
870 /* Suggest updated address */
871 address->active = GNUNET_YES;
872 addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES);
873 update_quota_per_network (solver, new_net, NULL);
874 }
875 else
876 {
877 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not enough bandwidth in new network, suggesting alternative address ..\n");
878
879 /* Set old address to zero bw */
880 address->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0);
881 address->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0);
882 s->bw_changed (s->bw_changed_cls, address);
883
884 /* Find new address to suggest since no bandwidth in network*/
885 new = (struct ATS_Address *) GAS_simplistic_get_preferred_address (s, addresses, &address->peer);
886 if (NULL != new)
887 {
888 /* Have an alternative address to suggest */
889 s->bw_changed (s->bw_changed_cls, new);
890 }
891
892 }
893 }
894 }
895
896 break;
897 case GNUNET_ATS_ARRAY_TERMINATOR:
898 break;
899 default:
900 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
901 "Received unsupported ATS type %u\n", prev_type);
902 GNUNET_break (0);
903 break;
904
905 }
906
907 }
908 if (address->session_id != session)
909 {
910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 "Session changed from %u to %u\n", address->session_id, session);
912 address->session_id = session;
913 }
914 if (address->used != in_use)
915 {
916 LOG (GNUNET_ERROR_TYPE_DEBUG,
917 "Usage changed from %u to %u\n", address->used, in_use);
918 address->used = in_use;
919 }
920
921}
922 739
923 740
924 741
@@ -957,7 +774,7 @@ find_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
957 return GNUNET_OK; 774 return GNUNET_OK;
958 } 775 }
959 776
960 if (GNUNET_NO == bw_available_in_network (net)) 777 if (GNUNET_NO == is_bandwidth_available_in_network (net))
961 return GNUNET_OK; /* There's no bandwidth available in this network */ 778 return GNUNET_OK; /* There's no bandwidth available in this network */
962 779
963 if (NULL != previous) 780 if (NULL != previous)
@@ -1017,126 +834,8 @@ find_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
1017 return GNUNET_OK; 834 return GNUNET_OK;
1018} 835}
1019 836
1020static int
1021find_active_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
1022{
1023 struct ATS_Address * dest = (struct ATS_Address *) (*(struct ATS_Address **)cls);
1024 struct ATS_Address * aa = (struct ATS_Address *) value;
1025 837
1026 if (GNUNET_YES == aa->active)
1027 {
1028 if (dest != NULL)
1029 {
1030 /* should never happen */
1031 LOG (GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n", GNUNET_i2s (&aa->peer));
1032 GNUNET_break (0);
1033 return GNUNET_NO;
1034 }
1035 dest = aa;
1036 }
1037 return GNUNET_OK;
1038}
1039 838
1040static struct ATS_Address *
1041find_active_address (void *solver,
1042 struct GNUNET_CONTAINER_MultiHashMap * addresses,
1043 const struct GNUNET_PeerIdentity *peer)
1044{
1045 struct ATS_Address * dest = NULL;
1046
1047 GNUNET_CONTAINER_multihashmap_get_multiple(addresses,
1048 &peer->hashPubKey,
1049 &find_active_address_it, &dest);
1050 return dest;
1051}
1052
1053/**
1054 * Get the prefered address for a specific peer
1055 *
1056 * @param solver the solver handle
1057 * @param addresses the address hashmap containing all addresses
1058 * @param peer the identity of the peer
1059 */
1060const struct ATS_Address *
1061GAS_simplistic_get_preferred_address (void *solver,
1062 struct GNUNET_CONTAINER_MultiHashMap * addresses,
1063 const struct GNUNET_PeerIdentity *peer)
1064{
1065 struct GAS_SIMPLISTIC_Handle *s = solver;
1066 struct Network *net_prev;
1067 struct Network *net_cur;
1068 struct ATS_Address *cur;
1069 struct ATS_Address *prev;
1070
1071 GNUNET_assert (s != NULL);
1072 cur = NULL;
1073 /* Get address with: stick to current address, lower distance, lower latency */
1074 GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
1075 &find_address_it, &cur);
1076 if (NULL == cur)
1077 {
1078 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
1079 return NULL;
1080 }
1081
1082 LOG (GNUNET_ERROR_TYPE_DEBUG, "Suggesting %s address %p for peer `%s'\n",
1083 (GNUNET_NO == cur->active) ? "inactive" : "active",
1084 cur, GNUNET_i2s (peer));
1085 net_cur = (struct Network *) cur->solver_information;
1086 if (GNUNET_YES == cur->active)
1087 {
1088 /* This address was selected previously, so no need to update quotas */
1089 return cur;
1090 }
1091
1092 /* This address was not active, so we have to:
1093 *
1094 * - mark previous active address as not active
1095 * - update quota for previous address network
1096 * - update quota for this address network
1097 */
1098
1099 prev = find_active_address (s, addresses, peer);
1100 if (NULL != prev)
1101 {
1102 net_prev = (struct Network *) prev->solver_information;
1103 prev->active = GNUNET_NO; /* No active any longer */
1104 prev->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */
1105 prev->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */
1106 s->bw_changed (s->bw_changed_cls, prev); /* notify about bw change, REQUIRED? */
1107 if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES))
1108 GNUNET_break (0);
1109 update_quota_per_network (s, net_prev, NULL);
1110 }
1111
1112 if (GNUNET_NO == (bw_available_in_network (cur->solver_information)))
1113 {
1114 GNUNET_break (0); /* This should never happen*/
1115 return NULL;
1116 }
1117
1118 cur->active = GNUNET_YES;
1119 addresse_increment(s, net_cur, GNUNET_NO, GNUNET_YES);
1120 update_quota_per_network (s, net_cur, cur);
1121
1122 return cur;
1123}
1124
1125
1126/**
1127 * Stop notifying about address and bandwidth changes for this peer
1128 *
1129 * @param solver the MLP handle
1130 * @param addresses address hashmap
1131 * @param peer the peer
1132 */
1133void
1134GAS_simplistic_stop_get_preferred_address (void *solver,
1135 struct GNUNET_CONTAINER_MultiHashMap *addresses,
1136 const struct GNUNET_PeerIdentity *peer)
1137{
1138 return;
1139}
1140 839
1141 840
1142/** 841/**
@@ -1148,7 +847,7 @@ GAS_simplistic_stop_get_preferred_address (void *solver,
1148static void 847static void
1149recalculate_preferences (struct PreferencePeer *p) 848recalculate_preferences (struct PreferencePeer *p)
1150{ 849{
1151 struct GAS_SIMPLISTIC_Handle *s = p->s; 850 struct GAS_PROPORTIONAL_Handle *s = p->s;
1152 struct PreferencePeer *p_cur; 851 struct PreferencePeer *p_cur;
1153 struct PreferenceClient *c_cur = p->client; 852 struct PreferenceClient *c_cur = p->client;
1154 double p_rel_global; 853 double p_rel_global;
@@ -1362,7 +1061,7 @@ GAS_simplistic_address_change_preference (void *solver,
1362 float score) 1061 float score)
1363{ 1062{
1364 static struct GNUNET_TIME_Absolute next_update; 1063 static struct GNUNET_TIME_Absolute next_update;
1365 struct GAS_SIMPLISTIC_Handle *s = solver; 1064 struct GAS_PROPORTIONAL_Handle *s = solver;
1366 struct PreferenceClient *c_cur; 1065 struct PreferenceClient *c_cur;
1367 struct PreferencePeer *p_cur; 1066 struct PreferencePeer *p_cur;
1368 int i; 1067 int i;
@@ -1438,6 +1137,422 @@ GAS_simplistic_address_change_preference (void *solver,
1438 * --------------------------- 1137 * ---------------------------
1439 */ 1138 */
1440 1139
1140/**
1141 * Get the prefered address for a specific peer
1142 *
1143 * @param solver the solver handle
1144 * @param addresses the address hashmap containing all addresses
1145 * @param peer the identity of the peer
1146 */
1147const struct ATS_Address *
1148GAS_proportional_get_preferred_address (void *solver,
1149 struct GNUNET_CONTAINER_MultiHashMap * addresses,
1150 const struct GNUNET_PeerIdentity *peer)
1151{
1152 struct GAS_PROPORTIONAL_Handle *s = solver;
1153 struct Network *net_prev;
1154 struct Network *net_cur;
1155 struct ATS_Address *cur;
1156 struct ATS_Address *prev;
1157
1158 GNUNET_assert (s != NULL);
1159 cur = NULL;
1160 /* Get address with: stick to current address, lower distance, lower latency */
1161 GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
1162 &find_address_it, &cur);
1163 if (NULL == cur)
1164 {
1165 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
1166 return NULL;
1167 }
1168
1169 LOG (GNUNET_ERROR_TYPE_DEBUG, "Suggesting %s address %p for peer `%s'\n",
1170 (GNUNET_NO == cur->active) ? "inactive" : "active",
1171 cur, GNUNET_i2s (peer));
1172 net_cur = (struct Network *) cur->solver_information;
1173 if (GNUNET_YES == cur->active)
1174 {
1175 /* This address was selected previously, so no need to update quotas */
1176 return cur;
1177 }
1178
1179 /* This address was not active, so we have to:
1180 *
1181 * - mark previous active address as not active
1182 * - update quota for previous address network
1183 * - update quota for this address network
1184 */
1185
1186 prev = get_active_address (s, addresses, peer);
1187 if (NULL != prev)
1188 {
1189 net_prev = (struct Network *) prev->solver_information;
1190 prev->active = GNUNET_NO; /* No active any longer */
1191 prev->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */
1192 prev->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */
1193 s->bw_changed (s->bw_changed_cls, prev); /* notify about bw change, REQUIRED? */
1194 if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES))
1195 GNUNET_break (0);
1196 update_quota_per_network (s, net_prev, NULL);
1197 }
1198
1199 if (GNUNET_NO == (is_bandwidth_available_in_network (cur->solver_information)))
1200 {
1201 GNUNET_break (0); /* This should never happen*/
1202 return NULL;
1203 }
1204
1205 cur->active = GNUNET_YES;
1206 addresse_increment(s, net_cur, GNUNET_NO, GNUNET_YES);
1207 update_quota_per_network (s, net_cur, cur);
1208
1209 return cur;
1210}
1211
1212
1213/**
1214 * Stop notifying about address and bandwidth changes for this peer
1215 *
1216 * @param solver the solver handle
1217 * @param addresses address hashmap
1218 * @param peer the peer
1219 */
1220void
1221GAS_proportional_stop_get_preferred_address (void *solver,
1222 struct GNUNET_CONTAINER_MultiHashMap *addresses,
1223 const struct GNUNET_PeerIdentity *peer)
1224{
1225 return;
1226}
1227
1228
1229/**
1230 * Remove an address from the solver
1231 *
1232 * @param solver the solver handle
1233 * @param addresses the address hashmap containing all addresses
1234 * @param address the address to remove
1235 * @param session_only delete only session not whole address
1236 */
1237void
1238GAS_proportional_address_delete (void *solver,
1239 struct GNUNET_CONTAINER_MultiHashMap * addresses,
1240 struct ATS_Address *address, int session_only)
1241{
1242 struct GAS_PROPORTIONAL_Handle *s = solver;
1243 struct Network *net;
1244 struct AddressWrapper *aw;
1245
1246 /* Remove an adress completely, we have to:
1247 * - Remove from specific network
1248 * - Decrease number of total addresses
1249 * - If active:
1250 * - decrease number of active addreses
1251 * - update quotas
1252 */
1253
1254 net = (struct Network *) address->solver_information;
1255
1256 if (GNUNET_NO == session_only)
1257 {
1258 LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ active: %u)\n",
1259 (GNUNET_NO == address->active) ? "inactive" : "active",
1260 address, GNUNET_i2s (&address->peer),
1261 net->desc, net->total_addresses, net->active_addresses);
1262
1263 /* Remove address */
1264 addresse_decrement (s, net, GNUNET_YES, GNUNET_NO);
1265 for (aw = net->head; NULL != aw; aw = aw->next)
1266 {
1267 if (aw->addr == address)
1268 break;
1269 }
1270 if (NULL == aw )
1271 {
1272 GNUNET_break (0);
1273 return;
1274 }
1275 GNUNET_CONTAINER_DLL_remove (net->head, net->tail, aw);
1276 GNUNET_free (aw);
1277 }
1278 else
1279 {
1280 /* Remove session only: remove if active and update */
1281 LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ active: %u)\n",
1282 (GNUNET_NO == address->active) ? "inactive" : "active",
1283 address, GNUNET_i2s (&address->peer),
1284 net->desc, net->total_addresses, net->active_addresses);
1285 }
1286
1287 if (GNUNET_YES == address->active)
1288 {
1289 /* Address was active, remove from network and update quotas*/
1290 address->active = GNUNET_NO;
1291 if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES))
1292 GNUNET_break (0);
1293 update_quota_per_network (s, net, NULL);
1294 }
1295 LOG (GNUNET_ERROR_TYPE_DEBUG, "After deleting address now total %u and active %u addresses in network `%s'\n",
1296 net->total_addresses,
1297 net->active_addresses,
1298 net->desc);
1299
1300}
1301
1302
1303/**
1304 * Add a new single address to a network
1305 *
1306 * @param solver the solver Handle
1307 * @param addresses the address hashmap containing all addresses
1308 * @param address the address to add
1309 * @param network network type of this address
1310 */
1311void
1312GAS_proportional_address_add (void *solver,
1313 struct GNUNET_CONTAINER_MultiHashMap *addresses,
1314 struct ATS_Address *address,
1315 uint32_t network);
1316
1317/**
1318 * Updates a single address in the solver
1319 *
1320 * If ATS information was updated, the previous values are passed
1321 *
1322 * @param solver the solver Handle
1323 * @param addresses the address hashmap containing all addresses
1324 * @param address the update address
1325 * @param session the new session (if changed otherwise current)
1326 * @param in_use the new address in use state (if changed otherwise current)
1327 * @param prev_ats ATS information
1328 * @param prev_atsi_count the atsi count
1329 */
1330void
1331GAS_proportional_address_update (void *solver,
1332 struct GNUNET_CONTAINER_MultiHashMap *addresses,
1333 struct ATS_Address *address,
1334 uint32_t session,
1335 int in_use,
1336 const struct GNUNET_ATS_Information *prev_ats,
1337 uint32_t prev_atsi_count)
1338{
1339 struct ATS_Address *new;
1340 struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver;
1341 int i;
1342 uint32_t prev_value;
1343 uint32_t prev_type;
1344 uint32_t addr_net;
1345 int save_active = GNUNET_NO;
1346 struct Network *new_net = NULL;
1347 for (i = 0; i < prev_atsi_count; i++)
1348 {
1349 prev_type = ntohl (prev_ats[i].type);
1350 prev_value = ntohl (prev_ats[i].value);
1351 switch (prev_type)
1352 {
1353 case GNUNET_ATS_UTILIZATION_UP:
1354 case GNUNET_ATS_UTILIZATION_DOWN:
1355 case GNUNET_ATS_QUALITY_NET_DELAY:
1356 case GNUNET_ATS_QUALITY_NET_DISTANCE:
1357 case GNUNET_ATS_COST_WAN:
1358 case GNUNET_ATS_COST_LAN:
1359 case GNUNET_ATS_COST_WLAN:
1360 /* No actions required here*/
1361 break;
1362 case GNUNET_ATS_NETWORK_TYPE:
1363
1364 addr_net = get_performance_info (address, GNUNET_ATS_NETWORK_TYPE);
1365 if (GNUNET_ATS_VALUE_UNDEFINED == addr_net)
1366 {
1367 GNUNET_break (0);
1368 addr_net = GNUNET_ATS_NET_UNSPECIFIED;
1369 }
1370 if (addr_net != prev_value)
1371 {
1372 /* Network changed */
1373 LOG (GNUNET_ERROR_TYPE_DEBUG, "Network type changed, moving %s address from `%s' to `%s'\n",
1374 (GNUNET_YES == address->active) ? "active" : "inactive",
1375 GNUNET_ATS_print_network_type(prev_value),
1376 GNUNET_ATS_print_network_type(addr_net));
1377
1378 save_active = address->active;
1379 /* remove from old network */
1380 GAS_proportional_address_delete (solver, addresses, address, GNUNET_NO);
1381
1382 /* set new network type */
1383 new_net = get_network (solver, addr_net);
1384 address->solver_information = new_net;
1385
1386 /* Add to new network and update*/
1387 GAS_proportional_address_add (solver, addresses, address, addr_net);
1388 if (GNUNET_YES == save_active)
1389 {
1390 /* check if bandwidth available in new network */
1391 if (GNUNET_YES == (is_bandwidth_available_in_network (new_net)))
1392 {
1393 /* Suggest updated address */
1394 address->active = GNUNET_YES;
1395 addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES);
1396 update_quota_per_network (solver, new_net, NULL);
1397 }
1398 else
1399 {
1400 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not enough bandwidth in new network, suggesting alternative address ..\n");
1401
1402 /* Set old address to zero bw */
1403 address->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0);
1404 address->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0);
1405 s->bw_changed (s->bw_changed_cls, address);
1406
1407 /* Find new address to suggest since no bandwidth in network*/
1408 new = (struct ATS_Address *) GAS_proportional_get_preferred_address (s, addresses, &address->peer);
1409 if (NULL != new)
1410 {
1411 /* Have an alternative address to suggest */
1412 s->bw_changed (s->bw_changed_cls, new);
1413 }
1414
1415 }
1416 }
1417 }
1418
1419 break;
1420 case GNUNET_ATS_ARRAY_TERMINATOR:
1421 break;
1422 default:
1423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1424 "Received unsupported ATS type %u\n", prev_type);
1425 GNUNET_break (0);
1426 break;
1427
1428 }
1429
1430 }
1431 if (address->session_id != session)
1432 {
1433 LOG (GNUNET_ERROR_TYPE_DEBUG,
1434 "Session changed from %u to %u\n", address->session_id, session);
1435 address->session_id = session;
1436 }
1437 if (address->used != in_use)
1438 {
1439 LOG (GNUNET_ERROR_TYPE_DEBUG,
1440 "Usage changed from %u to %u\n", address->used, in_use);
1441 address->used = in_use;
1442 }
1443
1444}
1445
1446
1447/**
1448 * Add a new single address to a network
1449 *
1450 * @param solver the solver Handle
1451 * @param addresses the address hashmap containing all addresses
1452 * @param address the address to add
1453 * @param network network type of this address
1454 */
1455void
1456GAS_proportional_address_add (void *solver,
1457 struct GNUNET_CONTAINER_MultiHashMap *addresses,
1458 struct ATS_Address *address,
1459 uint32_t network)
1460{
1461 struct GAS_PROPORTIONAL_Handle *s = solver;
1462 struct Network *net = NULL;
1463 struct AddressWrapper *aw = NULL;
1464 int c;
1465
1466 GNUNET_assert (NULL != s);
1467 for (c = 0; c < s->networks; c++)
1468 {
1469 net = &s->network_entries[c];
1470 if (network == net->type)
1471 break;
1472 }
1473 if (NULL == net)
1474 {
1475 GNUNET_break (0);
1476 return;
1477 }
1478
1479 aw = GNUNET_malloc (sizeof (struct AddressWrapper));
1480 aw->addr = address;
1481 GNUNET_CONTAINER_DLL_insert (net->head, net->tail, aw);
1482 addresse_increment (s, net, GNUNET_YES, GNUNET_NO);
1483 aw->addr->solver_information = net;
1484
1485 LOG (GNUNET_ERROR_TYPE_DEBUG, "After adding address now total %u and active %u addresses in network `%s'\n",
1486 net->total_addresses,
1487 net->active_addresses,
1488 net->desc);
1489}
1490
1491
1492/**
1493 * Init the proportional problem solver
1494 *
1495 * Quotas:
1496 * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
1497 * out_quota[i] contains outbound quota for network type i
1498 * in_quota[i] contains inbound quota for network type i
1499 *
1500 * Example
1501 * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
1502 * network[2] == GNUNET_ATS_NET_LAN
1503 * out_quota[2] == 65353
1504 * in_quota[2] == 65353
1505 *
1506 * @param cfg configuration handle
1507 * @param stats the GNUNET_STATISTICS handle
1508 * @param network array of GNUNET_ATS_NetworkType with length dest_length
1509 * @param out_quota array of outbound quotas
1510 * @param in_quota array of outbound quota
1511 * @param dest_length array length for quota arrays
1512 * @param bw_changed_cb callback for changed bandwidth amounts
1513 * @param bw_changed_cb_cls cls for callback
1514 * @return handle for the solver on success, NULL on fail
1515 */
1516void *
1517GAS_proportional_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
1518 const struct GNUNET_STATISTICS_Handle *stats,
1519 int *network,
1520 unsigned long long *out_quota,
1521 unsigned long long *in_quota,
1522 int dest_length,
1523 GAS_bandwidth_changed_cb bw_changed_cb,
1524 void *bw_changed_cb_cls)
1525{
1526 int c;
1527 struct GAS_PROPORTIONAL_Handle *s = GNUNET_malloc (sizeof (struct GAS_PROPORTIONAL_Handle));
1528 struct Network * cur;
1529 char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
1530
1531
1532 s->stats = (struct GNUNET_STATISTICS_Handle *) stats;
1533 s->bw_changed = bw_changed_cb;
1534 s->bw_changed_cls = bw_changed_cb_cls;
1535 s->networks = dest_length;
1536 s->network_entries = GNUNET_malloc (dest_length * sizeof (struct Network));
1537 s->active_addresses = 0;
1538 s->total_addresses = 0;
1539 s->prefs = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
1540
1541 for (c = 0; c < dest_length; c++)
1542 {
1543 cur = &s->network_entries[c];
1544 cur->total_addresses = 0;
1545 cur->active_addresses = 0;
1546 cur->type = network[c];
1547 cur->total_quota_in = in_quota[c];
1548 cur->total_quota_out = out_quota[c];
1549 cur->desc = net_str[c];
1550 GNUNET_asprintf (&cur->stat_total, "# ATS addresses %s total", cur->desc);
1551 GNUNET_asprintf (&cur->stat_active, "# ATS active addresses %s total", cur->desc);
1552 }
1553 return s;
1554}
1555
1441 1556
1442/** 1557/**
1443 * Shutdown the proportional problem solver 1558 * Shutdown the proportional problem solver
@@ -1447,7 +1562,7 @@ GAS_simplistic_address_change_preference (void *solver,
1447void 1562void
1448GAS_proportional_done (void *solver) 1563GAS_proportional_done (void *solver)
1449{ 1564{
1450 struct GAS_SIMPLISTIC_Handle *s = solver; 1565 struct GAS_PROPORTIONAL_Handle *s = solver;
1451 struct PreferenceClient *pc; 1566 struct PreferenceClient *pc;
1452 struct PreferenceClient *next_pc; 1567 struct PreferenceClient *next_pc;
1453 struct PreferencePeer *p; 1568 struct PreferencePeer *p;
@@ -1531,68 +1646,4 @@ GAS_proportional_done (void *solver)
1531} 1646}
1532 1647
1533 1648
1534/**
1535 * Init the proportional problem solver
1536 *
1537 * Quotas:
1538 * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
1539 * out_quota[i] contains outbound quota for network type i
1540 * in_quota[i] contains inbound quota for network type i
1541 *
1542 * Example
1543 * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
1544 * network[2] == GNUNET_ATS_NET_LAN
1545 * out_quota[2] == 65353
1546 * in_quota[2] == 65353
1547 *
1548 * @param cfg configuration handle
1549 * @param stats the GNUNET_STATISTICS handle
1550 * @param network array of GNUNET_ATS_NetworkType with length dest_length
1551 * @param out_quota array of outbound quotas
1552 * @param in_quota array of outbound quota
1553 * @param dest_length array length for quota arrays
1554 * @param bw_changed_cb callback for changed bandwidth amounts
1555 * @param bw_changed_cb_cls cls for callback
1556 * @return handle for the solver on success, NULL on fail
1557 */
1558void *
1559GAS_proportional_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
1560 const struct GNUNET_STATISTICS_Handle *stats,
1561 int *network,
1562 unsigned long long *out_quota,
1563 unsigned long long *in_quota,
1564 int dest_length,
1565 GAS_bandwidth_changed_cb bw_changed_cb,
1566 void *bw_changed_cb_cls)
1567{
1568 int c;
1569 struct GAS_SIMPLISTIC_Handle *s = GNUNET_malloc (sizeof (struct GAS_SIMPLISTIC_Handle));
1570 struct Network * cur;
1571 char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
1572
1573
1574 s->stats = (struct GNUNET_STATISTICS_Handle *) stats;
1575 s->bw_changed = bw_changed_cb;
1576 s->bw_changed_cls = bw_changed_cb_cls;
1577 s->networks = dest_length;
1578 s->network_entries = GNUNET_malloc (dest_length * sizeof (struct Network));
1579 s->active_addresses = 0;
1580 s->total_addresses = 0;
1581 s->prefs = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
1582
1583 for (c = 0; c < dest_length; c++)
1584 {
1585 cur = &s->network_entries[c];
1586 cur->total_addresses = 0;
1587 cur->active_addresses = 0;
1588 cur->type = network[c];
1589 cur->total_quota_in = in_quota[c];
1590 cur->total_quota_out = out_quota[c];
1591 cur->desc = net_str[c];
1592 GNUNET_asprintf (&cur->stat_total, "# ATS addresses %s total", cur->desc);
1593 GNUNET_asprintf (&cur->stat_active, "# ATS active addresses %s total", cur->desc);
1594 }
1595 return s;
1596}
1597
1598/* end of gnunet-service-ats-solver_proportional.c */ 1649/* end of gnunet-service-ats-solver_proportional.c */