aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-17 14:59:44 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-17 14:59:44 +0000
commit0bdf3ec3d40452b66e39b28e7e3694de8ead219e (patch)
tree93a2609bcc9569286235eca670bd5e2bc6c040a3
parent851903da372fa136ff783bc92c3abe57f554786e (diff)
downloadgnunet-0bdf3ec3d40452b66e39b28e7e3694de8ead219e.tar.gz
gnunet-0bdf3ec3d40452b66e39b28e7e3694de8ead219e.zip
-bound #messages queued, bound #destinations and bound #tunnels
-rw-r--r--src/vpn/gnunet-service-vpn.c269
1 files changed, 163 insertions, 106 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index bb6e6c595..5d91d79f5 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -29,8 +29,6 @@
29 * TODO: 29 * TODO:
30 * Basics: 30 * Basics:
31 * - test! 31 * - test!
32 * - better message queue management (bounded state, drop oldest/RED?)
33 * - actually destroy "stale" tunnels once we have too many!
34 * 32 *
35 * Features: 33 * Features:
36 * - add back ICMP support (especially needed for IPv6) 34 * - add back ICMP support (especially needed for IPv6)
@@ -53,6 +51,12 @@
53 51
54 52
55/** 53/**
54 * Maximum number of messages we allow in the queue for mesh.
55 */
56#define MAX_MESSAGE_QUEUE_SIZE 4
57
58
59/**
56 * State we keep for each of our tunnels. 60 * State we keep for each of our tunnels.
57 */ 61 */
58struct TunnelState; 62struct TunnelState;
@@ -67,7 +71,7 @@ struct DestinationEntry
67 71
68 /** 72 /**
69 * Key under which this entry is in the 'destination_map' (only valid 73 * Key under which this entry is in the 'destination_map' (only valid
70 * if 'heap_node != NULL'. 74 * if 'heap_node != NULL').
71 */ 75 */
72 GNUNET_HashCode key; 76 GNUNET_HashCode key;
73 77
@@ -170,6 +174,7 @@ struct TunnelMessageQueueEntry
170 */ 174 */
171struct TunnelState 175struct TunnelState
172{ 176{
177
173 /** 178 /**
174 * Information about the tunnel to use, NULL if no tunnel 179 * Information about the tunnel to use, NULL if no tunnel
175 * is available right now. 180 * is available right now.
@@ -606,8 +611,6 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf)
606 * Add the given message to the given tunnel and trigger the 611 * Add the given message to the given tunnel and trigger the
607 * transmission process. 612 * transmission process.
608 * 613 *
609 * FIXME: bound queue length!
610 *
611 * @param tnq message to queue 614 * @param tnq message to queue
612 * @param ts tunnel to queue the message for 615 * @param ts tunnel to queue the message for
613 */ 616 */
@@ -622,6 +625,23 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
622 ts->tmq_tail, 625 ts->tmq_tail,
623 tnq); 626 tnq);
624 ts->tmq_length++; 627 ts->tmq_length++;
628 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
629 {
630 struct TunnelMessageQueueEntry *dq;
631
632 dq = ts->tmq_head;
633 GNUNET_assert (dq != tnq);
634 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
635 ts->tmq_tail,
636 dq);
637 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
638 ts->th = NULL;
639 GNUNET_STATISTICS_update (stats,
640 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
641 dq->len,
642 GNUNET_NO);
643 GNUNET_free (dq);
644 }
625 if (NULL == ts->th) 645 if (NULL == ts->th)
626 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 646 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
627 GNUNET_NO /* cork */, 647 GNUNET_NO /* cork */,
@@ -707,6 +727,90 @@ create_tunnel_to_destination (struct DestinationEntry *de,
707 727
708 728
709/** 729/**
730 * Free resources associated with a tunnel state.
731 *
732 * @param ts state to free
733 */
734static void
735free_tunnel_state (struct TunnelState *ts)
736{
737 GNUNET_HashCode key;
738 struct TunnelMessageQueueEntry *tnq;
739
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Cleaning up tunnel state\n");
742 GNUNET_STATISTICS_update (stats,
743 gettext_noop ("# Active tunnels"),
744 -1, GNUNET_NO);
745 while (NULL != (tnq = ts->tmq_head))
746 {
747 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
748 ts->tmq_tail,
749 tnq);
750 ts->tmq_length--;
751 GNUNET_free (tnq);
752 }
753 GNUNET_assert (0 == ts->tmq_length);
754 if (NULL != ts->client)
755 {
756 GNUNET_SERVER_client_drop (ts->client);
757 ts->client = NULL;
758 }
759 if (NULL != ts->th)
760 {
761 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
762 ts->th = NULL;
763 }
764 GNUNET_assert (NULL == ts->destination.heap_node);
765 if (NULL != ts->tunnel)
766 {
767 GNUNET_MESH_tunnel_destroy (ts->tunnel);
768 ts->tunnel = NULL;
769 }
770 if (NULL != ts->heap_node)
771 {
772 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
773 ts->heap_node = NULL;
774 get_tunnel_key_from_ips (ts->af,
775 ts->protocol,
776 &ts->source_ip,
777 ts->source_port,
778 &ts->destination_ip,
779 ts->destination_port,
780 &key);
781 GNUNET_assert (GNUNET_YES ==
782 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
783 &key,
784 ts));
785 }
786 if (NULL != ts->destination_container)
787 {
788 GNUNET_assert (ts == ts->destination_container->ts);
789 ts->destination_container->ts = NULL;
790 ts->destination_container = NULL;
791 }
792 GNUNET_free (ts);
793}
794
795
796/**
797 * We have too many active tunnels. Clean up the oldest tunnel.
798 *
799 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
800 */
801static void
802expire_tunnel (struct TunnelState *except)
803{
804 struct TunnelState *ts;
805
806 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
807 if (except == ts)
808 return; /* can't do this */
809 free_tunnel_state (ts);
810}
811
812
813/**
710 * Route a packet via mesh to the given destination. 814 * Route a packet via mesh to the given destination.
711 * 815 *
712 * @param destination description of the destination 816 * @param destination description of the destination
@@ -878,7 +982,8 @@ route_packet (struct DestinationEntry *destination,
878 GNUNET_STATISTICS_update (stats, 982 GNUNET_STATISTICS_update (stats,
879 gettext_noop ("# Active tunnels"), 983 gettext_noop ("# Active tunnels"),
880 1, GNUNET_NO); 984 1, GNUNET_NO);
881 /* FIXME: expire OLD tunnels if we have too many! */ 985 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
986 expire_tunnel (ts);
882 } 987 }
883 else 988 else
884 { 989 {
@@ -1662,6 +1767,54 @@ allocate_v6_address (struct in6_addr *v6)
1662 1767
1663 1768
1664/** 1769/**
1770 * Free resources occupied by a destination entry.
1771 *
1772 * @param de entry to free
1773 */
1774static void
1775free_destination_entry (struct DestinationEntry *de)
1776{
1777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1778 "Cleaning up destination entry\n");
1779 GNUNET_STATISTICS_update (stats,
1780 gettext_noop ("# Active destinations"),
1781 -1, GNUNET_NO);
1782 if (NULL != de->ts)
1783 {
1784 free_tunnel_state (de->ts);
1785 GNUNET_assert (NULL == de->ts);
1786 }
1787 if (NULL != de->heap_node)
1788 {
1789 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
1790 de->heap_node = NULL;
1791 GNUNET_assert (GNUNET_YES ==
1792 GNUNET_CONTAINER_multihashmap_remove (destination_map,
1793 &de->key,
1794 de));
1795 }
1796 GNUNET_free (de);
1797}
1798
1799
1800/**
1801 * We have too many active destinations. Clean up the oldest destination.
1802 *
1803 * @param except destination that must NOT be cleaned up, even if it is the oldest
1804 */
1805static void
1806expire_destination (struct DestinationEntry *except)
1807{
1808 struct DestinationEntry *de;
1809
1810 de = GNUNET_CONTAINER_heap_peek (destination_heap);
1811 if (except == de)
1812 return; /* can't do this */
1813 free_destination_entry (de);
1814}
1815
1816
1817/**
1665 * A client asks us to setup a redirection via some exit 1818 * A client asks us to setup a redirection via some exit
1666 * node to a particular IP. Setup the redirection and 1819 * node to a particular IP. Setup the redirection and
1667 * give the client the allocated IP. 1820 * give the client the allocated IP.
@@ -1807,8 +1960,9 @@ service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *cl
1807 GNUNET_STATISTICS_update (stats, 1960 GNUNET_STATISTICS_update (stats,
1808 gettext_noop ("# Active destinations"), 1961 gettext_noop ("# Active destinations"),
1809 1, GNUNET_NO); 1962 1, GNUNET_NO);
1963 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
1964 expire_destination (de);
1810 1965
1811 /* FIXME: expire OLD destinations if we have too many! */
1812 /* setup tunnel to destination */ 1966 /* setup tunnel to destination */
1813 (void) create_tunnel_to_destination (de, 1967 (void) create_tunnel_to_destination (de,
1814 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client, 1968 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
@@ -1926,7 +2080,8 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien
1926 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, 2080 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1927 de, 2081 de,
1928 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value); 2082 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1929 /* FIXME: expire OLD destinations if we have too many! */ 2083 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2084 expire_destination (de);
1930 (void) create_tunnel_to_destination (de, 2085 (void) create_tunnel_to_destination (de,
1931 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client, 2086 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1932 msg->request_id); 2087 msg->request_id);
@@ -1959,104 +2114,6 @@ inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1959 2114
1960 2115
1961/** 2116/**
1962 * Free resources associated with a tunnel state.
1963 *
1964 * @param ts state to free
1965 */
1966static void
1967free_tunnel_state (struct TunnelState *ts)
1968{
1969 GNUNET_HashCode key;
1970 struct TunnelMessageQueueEntry *tnq;
1971
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1973 "Cleaning up tunnel state\n");
1974 GNUNET_STATISTICS_update (stats,
1975 gettext_noop ("# Active tunnels"),
1976 -1, GNUNET_NO);
1977 while (NULL != (tnq = ts->tmq_head))
1978 {
1979 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
1980 ts->tmq_tail,
1981 tnq);
1982 ts->tmq_length--;
1983 GNUNET_free (tnq);
1984 }
1985 GNUNET_assert (0 == ts->tmq_length);
1986 if (NULL != ts->client)
1987 {
1988 GNUNET_SERVER_client_drop (ts->client);
1989 ts->client = NULL;
1990 }
1991 if (NULL != ts->th)
1992 {
1993 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1994 ts->th = NULL;
1995 }
1996 GNUNET_assert (NULL == ts->destination.heap_node);
1997 if (NULL != ts->tunnel)
1998 {
1999 GNUNET_MESH_tunnel_destroy (ts->tunnel);
2000 ts->tunnel = NULL;
2001 }
2002 if (NULL != ts->heap_node)
2003 {
2004 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
2005 ts->heap_node = NULL;
2006 get_tunnel_key_from_ips (ts->af,
2007 ts->protocol,
2008 &ts->source_ip,
2009 ts->source_port,
2010 &ts->destination_ip,
2011 ts->destination_port,
2012 &key);
2013 GNUNET_assert (GNUNET_YES ==
2014 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
2015 &key,
2016 ts));
2017 }
2018 if (NULL != ts->destination_container)
2019 {
2020 GNUNET_assert (ts == ts->destination_container->ts);
2021 ts->destination_container->ts = NULL;
2022 ts->destination_container = NULL;
2023 }
2024 GNUNET_free (ts);
2025}
2026
2027
2028/**
2029 * Free resources occupied by a destination entry.
2030 *
2031 * @param de entry to free
2032 */
2033static void
2034free_destination_entry (struct DestinationEntry *de)
2035{
2036 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2037 "Cleaning up destination entry\n");
2038 GNUNET_STATISTICS_update (stats,
2039 gettext_noop ("# Active destinations"),
2040 -1, GNUNET_NO);
2041 if (NULL != de->ts)
2042 {
2043 free_tunnel_state (de->ts);
2044 GNUNET_assert (NULL == de->ts);
2045 }
2046 if (NULL != de->heap_node)
2047 {
2048 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2049 de->heap_node = NULL;
2050 GNUNET_assert (GNUNET_YES ==
2051 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2052 &de->key,
2053 de));
2054 }
2055 GNUNET_free (de);
2056}
2057
2058
2059/**
2060 * Function called whenever an inbound tunnel is destroyed. Should clean up 2117 * Function called whenever an inbound tunnel is destroyed. Should clean up
2061 * any associated state. 2118 * any associated state.
2062 * 2119 *