]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Marin Stavrev <mstavrev@gmail.com>
authorAmos Jeffries <squid3@treenet.co.nz>
Sat, 3 May 2008 23:37:00 +0000 (11:37 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Sat, 3 May 2008 23:37:00 +0000 (11:37 +1200)
ZPH (Zero Penalty Hit) QOS features.

Adds --enable-zph-qos options to turn on the following:

 - Allows you to select a TOS/Diffserv value to mark local hits.

 - Allows you to select a TOS/Diffserv value to mark peer hits.

 - Allows you to selectively set only sibling or sibling+parent requests

 - Allows any HTTP response towards clients will
   have the TOS value of the response comming from the remote
   server masked with the value of zph_preserve_miss_tos_mask.
   For this to work correctly, you will need to patch your linux
   kernel with the TOS preserving ZPH patch.
   The kernel patch can be downloaded from http://zph.bratcheda.org

 - Allows you to mask certain bits in the TOS received from the
   remote server, before copying the value to the TOS send towards
   clients.

configure.in
src/cf.data.pre
src/client_side_reply.cc
src/fde.h
src/forward.cc
src/structs.h

index 72a648fdc34dab516a894202e1ce2e4df4d3cf77..02461b65e7b5ebd43ae4e62c510ad8510d544ef0 100644 (file)
@@ -1733,6 +1733,16 @@ AC_ARG_ENABLE(x_accelerator_vary,
   fi
 ])
 
+AC_ARG_ENABLE(zph-qos,
+[  --enable-zph-qos        Enable ZPH QOS support],
+[ if test "$enableval" = "yes" ; then
+    echo "ZPH QOS enabled"
+    AC_DEFINE(USE_ZPH_QOS,1,
+    [ Define this to use Squid's ZPH (Zero Penalty Hit) QOS features.
+      When enabled, Squid will alter TOS field of HIT responses for better QOS on intermediate routing/shaping devices.])
+  fi
+])
+
 AC_ARG_WITH(filedescriptors,
 [  --with-filedescriptors=NUMBER
                           Force squid to support NUMBER filedescriptors],
index 1d0c116244ed00bd7ffeabe93effdc9eeda39b33..25b0e0139d21f39f6ec7533986e9944c7960d081 100644 (file)
@@ -1103,6 +1103,66 @@ DOC_START
        making the request.
 DOC_END
 
+NAME: zph_tos_local
+TYPE: int
+IFDEF: USE_ZPH_QOS
+DEFAULT: 0
+LOC: Config.zph_tos_local
+DOC_START
+       Allows you to select a TOS/Diffserv value to mark local hits. Read above
+       (tcp_outgoing_tos) for details/requirements about TOS.
+       Default: 0 (disabled).
+DOC_END
+
+NAME: zph_tos_peer
+TYPE: int
+IFDEF: USE_ZPH_QOS
+DEFAULT: 0
+LOC: Config.zph_tos_peer
+DOC_START
+       Allows you to select a TOS/Diffserv value to mark peer hits. Read above
+       (tcp_outgoing_tos) for details/requirements about TOS.
+       Default: 0 (disabled).
+DOC_END
+
+NAME: zph_tos_parent
+COMMENT: on|off
+TYPE: onoff
+IFDEF: USE_ZPH_QOS
+DEFAULT: on
+LOC: Config.onoff.zph_tos_parent
+DOC_START
+       Set this to off if you want only sibling hits to be marked.
+       If set to on (default), parent hits are being marked too.
+DOC_END
+
+NAME: zph_preserve_miss_tos
+COMMENT: on|off
+TYPE: onoff
+IFDEF: USE_ZPH_QOS
+DEFAULT: on
+LOC: Config.onoff.zph_preserve_miss_tos
+DOC_START
+       If set to on (default), any HTTP response towards clients will
+       have the TOS value of the response comming from the remote
+       server masked with the value of zph_preserve_miss_tos_mask.
+       For this to work correctly, you will need to patch your linux
+       kernel with the TOS preserving ZPH patch.
+       The kernel patch can be downloaded from http://zph.bratcheda.org
+DOC_END
+
+NAME: zph_preserve_miss_tos_mask
+TYPE: int
+IFDEF: USE_ZPH_QOS
+DEFAULT: 255
+LOC: Config.zph_preserve_miss_tos_mask
+DOC_START
+       Allows you to mask certain bits in the TOS received from the
+       remote server, before copying the value to the TOS send towards
+       clients.
+       Default: 255 (TOS from server is not changed).
+DOC_END
+
 NAME: tcp_outgoing_address
 TYPE: acl_address
 DEFAULT: none
index cd6d0c93d0d9209430849f8d7860e70827c0818f..f2a5dc205a6678ee03b410fc1407c4d3417cefc7 100644 (file)
@@ -48,6 +48,9 @@
 #include "ESI.h"
 #endif
 #include "MemObject.h"
+#if USE_ZPH_QOS
+#include "fde.h"
+#endif
 #include "ACLChecklist.h"
 #include "ACL.h"
 #if DELAY_POOLS
@@ -1548,6 +1551,58 @@ clientReplyContext::doGetMoreData()
         /* guarantee nothing has been sent yet! */
         assert(http->out.size == 0);
         assert(http->out.offset == 0);
+#if USE_ZPH_QOS        
+        if (Config.zph_tos_local ||
+               Config.zph_tos_peer ||
+               Config.onoff.zph_preserve_miss_tos && Config.zph_preserve_miss_tos_mask)
+               {
+                  int need_change = 0;
+                  int hit = 0;
+                  int tos = 0;
+                  int tos_old = 0;
+                  int tos_len = sizeof(tos_old);
+                  int res;
+                              
+                  if (Config.zph_tos_local)
+                  {
+                          /* local hit */
+                      hit = 1;
+                      tos = Config.zph_tos_local;
+                  }
+                  else if (Config.zph_tos_peer && 
+                               (http->request->hier.code==SIBLING_HIT ||
+                               Config.onoff.zph_tos_parent&&http->request->hier.code==PARENT_HIT))
+                  {
+                         /* sibling or parent hit */
+                      hit = 1;
+                      tos = Config.zph_tos_peer;
+                  }
+                  
+                  if (http->request->flags.proxy_keepalive)
+                  {
+                          res = getsockopt(http->getConn()->fd, IPPROTO_IP, IP_TOS, &tos_old, (socklen_t*)&tos_len);
+                      if (res < 0)
+                      {
+                          debugs(33, 1, "ZPH: error in getsockopt(IP_TOS) on keepalived FD "<< http->getConn()->fd << " " << xstrerror());
+                      }
+                      else if (hit && tos_old != tos)
+                      {
+                          /* HIT: 1-st request, or previous was MISS,
+                           * or local/parent hit change.
+                           */
+                          need_change = 1;                    
+                      }
+                  }
+                  else if (hit)
+                  {
+                          /* no keepalive */
+                      need_change = 1;
+                  }
+                  if (need_change) {
+                          comm_set_tos(http->getConn()->fd,tos);
+                  }
+               }        
+#endif /* USE_ZPH_QOS */        
         tempBuffer.offset = reqofs;
         tempBuffer.length = getNextNode()->readBuffer.length;
         tempBuffer.data = getNextNode()->readBuffer.data;
@@ -1833,6 +1888,16 @@ clientReplyContext::sendMoreData (StoreIOBuffer result)
         body_buf = buf;
     }
 
+#if USE_ZPH_QOS    
+    if (reqofs==0 && !logTypeIsATcpHit(http->logType) &&
+               Config.onoff.zph_preserve_miss_tos &&
+               Config.zph_preserve_miss_tos_mask)
+    {
+       int tos = fd_table[fd].upstreamTOS & Config.zph_preserve_miss_tos_mask;
+       comm_set_tos(fd,tos);
+    }
+#endif    
+
     /* We've got the final data to start pushing... */
     flags.storelogiccomplete = 1;
 
index d53a17c73b9a7ccf089c076e0ab6b991e7d22534..8c33d492c5b4bd08e1ac2842462748f3fa2bfcf3 100644 (file)
--- a/src/fde.h
+++ b/src/fde.h
@@ -106,6 +106,9 @@ public:
         long handle;
     } win32;
 #endif
+#if USE_ZPH_QOS
+    unsigned char upstreamTOS;                 /* see FwdState::dispatch()  */
+#endif
 
 };
 
index 4d083dafadeb8ff5940561df0edfbb65957f459a..0ff3a3b7344f3e88304678aca69bbd448b9958df 100644 (file)
@@ -964,6 +964,54 @@ FwdState::dispatch()
 
     netdbPingSite(request->host);
 
+#if USE_ZPH_QOS
+    /* Retrieves remote server TOS value, and stores it as part of the
+     * original client request FD object. It is later used to forward
+     * remote server's TOS in the response to the client in case of a MISS.
+     */
+    fde * clientFde = &fd_table[client_fd];
+    if (clientFde)
+    {
+       int tos = 1;
+       int tos_len = sizeof(tos);
+       clientFde->upstreamTOS = 0;
+        if (setsockopt(server_fd,SOL_IP,IP_RECVTOS,&tos,tos_len)==0)
+        {
+           unsigned char buf[512];
+           int len = 512;
+           if (getsockopt(server_fd,SOL_IP,IP_PKTOPTIONS,buf,(socklen_t*)&len) == 0)
+           {
+               /* Parse the PKTOPTIONS structure to locate the TOS data message
+                * prepared in the kernel by the ZPH incoming TCP TOS preserving
+                * patch.
+                */
+                  unsigned char * p = buf;
+               while (p-buf < len)
+               {
+                  struct cmsghdr *o = (struct cmsghdr*)p;
+                  if (o->cmsg_len<=0)
+                     break;
+    
+                  if (o->cmsg_level == SOL_IP && o->cmsg_type == IP_TOS)
+                  {
+                         clientFde->upstreamTOS = (unsigned char)(*(int*)CMSG_DATA(o));
+                         break;
+                  }
+                  p += CMSG_LEN(o->cmsg_len);
+               }
+           }
+           else
+           {
+               debugs(33, 1, "ZPH: error in getsockopt(IP_PKTOPTIONS) on FD "<<server_fd<<" "<<xstrerror());
+           }
+        }
+        else
+        {
+               debugs(33, 1, "ZPH: error in setsockopt(IP_RECVTOS) on FD "<<server_fd<<" "<<xstrerror());
+        }
+    }    
+#endif
+
     if (servers && (p = servers->_peer)) {
         p->stats.fetches++;
         request->peer_login = p->login;
index 3cdaa4a5073667898fc2e38cbcb7ecfe782ab51d..b44969d5b4c5de149595e882816721d846aab682 100644 (file)
@@ -554,9 +554,11 @@ struct _SquidConfig
         int httpd_suppress_version_string;
         int global_internal_static;
         int debug_override_X;
-    }
-
-    onoff;
+#if USE_ZPH_QOS
+        int zph_tos_parent;
+        int zph_preserve_miss_tos;
+#endif
+    } onoff;
 
     class ACL *aclList;
 
@@ -720,6 +722,11 @@ struct _SquidConfig
     int sleep_after_fork;      /* microseconds */
     time_t minimum_expiry_time;        /* seconds */
     external_acl *externalAclHelperList;
+#if USE_ZPH_QOS
+    int zph_tos_local;
+    int zph_tos_peer;
+    int zph_preserve_miss_tos_mask; 
+#endif
 #if USE_SSL
 
     struct