]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Steven Wilton <swilton@q-net.net.au>
authorswilton <>
Sat, 9 Feb 2008 10:48:05 +0000 (10:48 +0000)
committerswilton <>
Sat, 9 Feb 2008 10:48:05 +0000 (10:48 +0000)
Sort cache list in wccpv2 to ensure a consistent hash allocation across all serv
ices

Under some circumstances different caches were being allocated differnet hash
assignments for different wccpv2 services.  This caused problems when using
TPROXY as the reply traffic was being sent to a different cache than the request
causing problems in browsing web pages.

This patch applied a selection sort algorithm to the cache list to ensure that
as long as the same group of caches are registered for any number of wccpv2
services, they will be allocated the same hash assignments in the router.

src/wccp2.cc

index 491ac92e53b34d99be4f5f82e18808b46fd94377..f50b87340bf5c5505e6a28056e054a0d3539f9c6 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wccp2.cc,v 1.22 2008/02/05 22:39:42 amosjeffries Exp $
+ * $Id: wccp2.cc,v 1.23 2008/02/09 03:48:05 swilton Exp $
  *
  * DEBUG: section 80    WCCP Support
  * AUTHOR: Steven Wilton
@@ -463,6 +463,7 @@ int empty_portlist[WCCP2_NUMPORTS] =
 /* END WCCP V2 */
 void wccp2_add_service_list(int service, int service_id, int service_priority,
                             int service_proto, int service_flags, int ports[], int security_type, char *password);
+static void wccp2SortCacheList(struct wccp2_cache_list_t *head);
 
 /*
  * The functions used during startup:
@@ -1495,6 +1496,8 @@ wccp2HandleUdp(int sock, void *not_used)
         num_caches = 1;
     }
 
+    wccp2SortCacheList(&router_list_ptr->cache_list_head);
+
     router_list_ptr->num_caches = htonl(num_caches);
 
     if ((found == 1) && (service_list_ptr->lowest_ip == 1)) {
@@ -2388,6 +2391,41 @@ dump_wccp2_service_info(StoreEntry * e, const char *label, void *v)
     }
 }
 
+/* Sort the cache list by doing a "selection sort" by IP address */
+static void
+wccp2SortCacheList(struct wccp2_cache_list_t *head)
+{
+    struct wccp2_cache_list_t tmp;
+    struct wccp2_cache_list_t *this_item;
+    struct wccp2_cache_list_t *find_item;
+    struct wccp2_cache_list_t *next_lowest;
+
+    /* Go through each position in the list one at a time */
+    for (this_item = head; this_item->next; this_item = this_item->next) {
+       /* Find the item with the lowest IP */
+       next_lowest = this_item;
+
+       for (find_item = this_item; find_item->next; find_item = find_item->next) {
+           if (find_item->cache_ip.s_addr < next_lowest->cache_ip.s_addr) {
+               next_lowest = find_item;
+           }
+       }
+       /* Swap if we need to */
+       if (next_lowest != this_item) {
+           /* First make a copy of the current item */
+           memcpy(&tmp, this_item, sizeof(struct wccp2_cache_list_t));
+
+           /* Next update the pointers to maintain the linked list */
+           tmp.next = next_lowest->next;
+           next_lowest->next = this_item->next;
+
+           /* Finally copy the updated items to their correct location */
+           memcpy(this_item, next_lowest, sizeof(struct wccp2_cache_list_t));
+           memcpy(next_lowest, &tmp, sizeof(struct wccp2_cache_list_t));
+       }
+    }
+}
+
 void
 free_wccp2_service_info(void *v)
 {}