We've had a couple of problems on our caches using WCCP2 + tproxy where the caches registered in a different order with the different WCCP services (traffic to the web server VS traffic from the web server). This resulted in the assignment algorithm sending traffic coming from a particular client to one cache, and the reply traffic to a different cache.

My solution is to order the linked list of web caches in the WCCP2 code to ensure that each cache will be assigned the same has map regardless of when the cache registers with the router.

I've attached the patch, which we're using in production. I'll commit it to head shortly unless there's any objections, and I'm not sure if it's worth applying to 2.6/2.7/3.0.

Steven

----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

Index: src/wccp2.c
===================================================================
RCS file: /cvsroot/squid/squid/src/wccp2.c,v
retrieving revision 1.29
diff -u -u -r1.29 wccp2.c
--- src/wccp2.c 26 Dec 2007 23:52:02 -0000      1.29
+++ src/wccp2.c 25 Jan 2008 01:10:55 -0000
@@ -361,6 +361,7 @@
 /* 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:
@@ -1166,6 +1167,8 @@
        found = 1;
        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)) {
@@ -1913,6 +1916,39 @@
     }
 }
 
+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)
 {

Reply via email to