From: Amos Jeffries Date: Sat, 3 May 2008 23:37:00 +0000 (+1200) Subject: Author: Marin Stavrev X-Git-Tag: SQUID_3_0_STABLE6~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96a59806e99ce4d0ab4de1aec8c77b7f0afd5447;p=thirdparty%2Fsquid.git Author: Marin Stavrev 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. --- diff --git a/configure.in b/configure.in index 72a648fdc3..02461b65e7 100644 --- a/configure.in +++ b/configure.in @@ -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], diff --git a/src/cf.data.pre b/src/cf.data.pre index 1d0c116244..25b0e0139d 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -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 diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index cd6d0c93d0..f2a5dc205a 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -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; diff --git a/src/fde.h b/src/fde.h index d53a17c73b..8c33d492c5 100644 --- 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 }; diff --git a/src/forward.cc b/src/forward.cc index 4d083dafad..0ff3a3b734 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -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 "<_peer)) { p->stats.fetches++; request->peer_login = p->login; diff --git a/src/structs.h b/src/structs.h index 3cdaa4a507..b44969d5b4 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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