=== modified file 'configure.in'
--- configure.in 2010-08-10 15:37:53 +0000
+++ configure.in 2010-08-11 13:32:45 +0000
@@ -1112,6 +1112,34 @@
fi
AC_SUBST(SSLLIB)
+dnl Allow user to specify libnetfilter_conntrack (needed for QOS netfilter marking)
+AC_ARG_WITH(netfilter-conntrack,
+ AS_HELP_STRING([--with-netfilter-conntrack=PATH],
+ [Compile with the Netfilter conntrack libraries. The path to
+ the development libraries and headers
+ installation can be specified if outside of the
+ system standard directories]), [
+case "$with_netfilter_conntrack" in
+ no)
+ : # Nothing special to do here
+ ;;
+ yes)
+ AC_CHECK_LIB([netfilter_conntrack], [nfct_query],,
+ AC_MSG_ERROR([libnetfilter-conntrack library not found. Needed for netfilter-conntrack support]),
+ [-lnetfilter_conntrack])
+ AC_CHECK_HEADERS([libnetfilter_conntrack/libnetfilter_conntrack.h \
+ libnetfilter_conntrack/libnetfilter_conntrack_tcp.h])
+ ;;
+ *)
+ if test ! -d $withval ; then
+ AC_MSG_ERROR([--with-netfilter-conntrack path does not point to a directory])
+ fi
+ LDFLAGS="-L$with_netfilter_conntrack/lib $LDFLAGS"
+ CPPFLAGS="-I$with_netfilter_conntrack/include $CPPFLAGS"
+ with_netfilter_conntrack=yes
+ ;;
+ esac
+])
AC_ARG_ENABLE(forw-via-db,
AS_HELP_STRING([--enable-forw-via-db],[Enable Forw/Via database]), [
@@ -1990,10 +2018,19 @@
SQUID_YESNO([$enableval],
[unrecognized argument to --enable-zph-qos: $enableval])
])
-SQUID_DEFINE_BOOL(USE_ZPH_QOS,${enable_zph_qos:=no},
+SQUID_DEFINE_BOOL(USE_QOS_TOS,${enable_zph_qos:=no},
[Enable Zero Penalty Hit QOS. When set, Squid will alter the
TOS field of HIT responses to help policing network traffic])
AC_MSG_NOTICE([ZPH QOS enabled: $enable_zph_qos])
+if test "$enable_zph_qos" = "yes" ; then
+ if test "$with_netfilter_conntrack" = "yes" ; then
+ AC_MSG_NOTICE([QOS netfilter marking enabled: $with_netfilter_conntrack])
+ SQUID_DEFINE_BOOL(USE_QOS_NFMARK,$with_netfilter_conntrack,
+ [Enable support for QOS netfilter packet marking])
+ else
+ AC_MSG_WARN([--with-netfilter-conntrack not enabled. QOS features will not support Netfilter marking.])
+ fi
+fi
if $CPPUNITCONFIG --help >/dev/null; then
squid_cv_cppunit_version="`$CPPUNITCONFIG --version`"
=== modified file 'doc/release-notes/release-3.2.sgml'
--- doc/release-notes/release-3.2.sgml 2010-08-02 13:55:59 +0000
+++ doc/release-notes/release-3.2.sgml 2010-08-05 19:13:42 +0000
@@ -396,6 +396,15 @@
Please check and update your squid.conf to use the text none for no limit instead of the old 0 (zero).
All users upgrading need to be aware that from Squid-3.3 setting this option to 0 (zero) will mean zero bytes of memory get pooled.
+ qos_flows
+
New options mark and tos
+
tos retains the original QOS functionality of the IP header TOS field.
+
mark offers the same functionality, but with a netfilter mark value.
+
These options should be placed immediately after qos_flows.
+
The tos value is optional in order to maintain backwards compatability.
+
Netfilter marking requires libnetfilter_conntrack, which must be included during compilation using --with-netfilter-conntrack.
+
The preserve-miss functionality is available with the mark option and requires no kernel patching.
+
windows_ipaddrchangemonitor
Now only available to be set in Windows builds.
@@ -472,6 +481,9 @@
Currently one demo helper fake is provided in shell and C++ forms to demonstrate
the helper protocol usage and provide exemplar code.
+ --with-netfiler-conntrack
+
Includes the libnetfilter_conntrack library, required for the new qos_flows option mark .
+
Changes to existing options
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2010-08-10 07:19:17 +0000
+++ src/cf.data.pre 2010-08-11 14:46:15 +0000
@@ -1527,23 +1527,28 @@
NAME: qos_flows
TYPE: QosConfig
-IFDEF: USE_ZPH_QOS
+IFDEF: USE_QOS_TOS
DEFAULT: none
-LOC: Ip::Qos::TheConfig
+LOC: Ip::TheQos
DOC_START
Allows you to select a TOS/DSCP value to mark outgoing
- connections with, based on where the reply was sourced.
+ connections with, based on where the reply was sourced. For
+ platforms using netfilter, allows you to set a netfilter mark
+ value instead of, or in addition to, a TOS value.
TOS values really only have local significance - so you should
know what you're specifying. For more information, see RFC2474,
RFC2475, and RFC3260.
The TOS/DSCP byte must be exactly that - octet value 0x00-0xFF.
- Note that in practice often only values up to 0x3F are usable
- as the two highest bits have been redefined for use by ECN
- (RFC3168).
-
- This setting is configured by setting the source TOS values:
+ Note that in practice often only values up to 0x3F are usable as
+ the two highest bits have been redefined for use by ECN (RFC3168).
+
+ Mark values can be any unsigned integer value (normally up to 0xFFFFFFFF)
+
+ This setting is configured by setting the following values:
+
+ tos|mark Whether to set TOS or netfilter mark values
local-hit=0xFF Value to mark local cache hits.
@@ -1551,23 +1556,31 @@
parent-hit=0xFF Value to mark hits from parent peers.
-
- NOTE: 'miss' preserve feature is only possible on Linux at this time.
-
- For the following 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
+ The TOS varient of the following features are only possible on Linux
+ and require your kernel to be patched with the TOS preserving ZPH
+ patch, available from http://zph.bratcheda.org
+ No patch is needed to preserve the netfilter mark, which will work
+ with all varients of netfilter.
disable-preserve-miss
- By default, the existing TOS value of the response coming
- from the remote server will be retained and masked with
- miss-mark. This option disables that feature.
+ This option disables the preservation of the TOS or netfilter
+ mark. By default, the existing TOS or netfilter mark value of
+ the response coming from the remote server will be retained
+ and masked with miss-mark.
+ NOTE: in the case of a netfilter mark, the mark must be set on
+ the connection (using the CONNMARK target) not on the packet
+ (MARK target).
miss-mask=0xFF
- Allows you to mask certain bits in the TOS received from the
- remote server, before copying the value to the TOS sent
- towards clients.
- Default: 0xFF (TOS from server is not changed).
+ Allows you to mask certain bits in the TOS or mark value
+ received from the remote server, before copying the value to
+ the TOS sent towards clients.
+ Default for tos: 0xFF (TOS from server is not changed).
+ Default for mark: 0xFFFFFFFF (mark from server is not changed).
+
+ All of these features require the --enable-zph-qos compilation flag.
+ Netfilter marking also requires the libnetfilter_conntrack libraries
+ (--with-netfilter-conntrack) and libcap 2.09+ (--with-libcap)
DOC_END
=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc 2010-07-13 14:27:25 +0000
+++ src/client_side_reply.cc 2010-08-11 17:50:23 +0000
@@ -1665,12 +1665,17 @@
/* guarantee nothing has been sent yet! */
assert(http->out.size == 0);
assert(http->out.offset == 0);
-#if USE_ZPH_QOS
- if (Ip::Qos::TheConfig.tos_local_hit) {
- debugs(33, 2, "ZPH Local hit, TOS=" << Ip::Qos::TheConfig.tos_local_hit);
- comm_set_tos(http->getConn()->fd, Ip::Qos::TheConfig.tos_local_hit);
- }
-#endif /* USE_ZPH_QOS */
+
+ if (Ip::TheQos.isTosActive()) {
+ debugs(33, 2, "QOS Local hit, TOS=" << Ip::TheQos.getTosLocalHit());
+ comm_set_tos(http->getConn()->fd, Ip::TheQos.getTosLocalHit());
+ }
+
+ if (Ip::TheQos.isMarkActive()) {
+ debugs(33, 2, "QOS Local hit, Mark=" << Ip::TheQos.getNfmarkLocalHit());
+ comm_set_nfmark(http->getConn()->fd, Ip::TheQos.getNfmarkLocalHit());
+ }
+
localTempBuffer.offset = reqofs;
localTempBuffer.length = getNextNode()->readBuffer.length;
localTempBuffer.data = getNextNode()->readBuffer.data;
@@ -1949,23 +1954,17 @@
body_buf = buf;
}
-#if USE_ZPH_QOS
if (reqofs==0 && !logTypeIsATcpHit(http->logType)) {
assert(fd >= 0); // the beginning of this method implies fd may be -1
- int tos = 0;
- if (Ip::Qos::TheConfig.tos_sibling_hit && http->request->hier.code==SIBLING_HIT ) {
- tos = Ip::Qos::TheConfig.tos_sibling_hit;
- debugs(33, 2, "ZPH: Sibling Peer hit with hier.code=" << http->request->hier.code << ", TOS=" << tos);
- } else if (Ip::Qos::TheConfig.tos_parent_hit && http->request->hier.code==PARENT_HIT) {
- tos = Ip::Qos::TheConfig.tos_parent_hit;
- debugs(33, 2, "ZPH: Parent Peer hit with hier.code=" << http->request->hier.code << ", TOS=" << tos);
- } else if (Ip::Qos::TheConfig.preserve_miss_tos && Ip::Qos::TheConfig.preserve_miss_tos_mask) {
- tos = fd_table[fd].upstreamTOS & Ip::Qos::TheConfig.preserve_miss_tos_mask;
- debugs(33, 2, "ZPH: Preserving TOS on miss, TOS="<request->hier);
+ comm_set_tos(fd,tos);
+ }
+ if (Ip::TheQos.isMarkActive()) {
+ unsigned int mark = Ip::TheQos.getNfmarkLocalMiss(fd, http->request->hier);
+ comm_set_nfmark(fd,mark);
+ }
}
-#endif
/* We've got the final data to start pushing... */
flags.storelogiccomplete = 1;
=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc 2010-07-23 10:49:32 +0000
+++ src/client_side_request.cc 2010-08-11 16:36:24 +0000
@@ -1337,7 +1337,7 @@
ACLFilledChecklist ch(NULL, request, NULL);
ch.src_addr = request->client_addr;
ch.my_addr = request->my_addr;
- int tos = aclMapTOS(Config.accessList.clientside_tos, &ch);
+ unsigned char tos = aclMapTOS(Config.accessList.clientside_tos, &ch);
if (tos)
comm_set_tos(getConn()->fd, tos);
}
=== modified file 'src/comm.cc'
--- src/comm.cc 2010-07-28 12:39:35 +0000
+++ src/comm.cc 2010-08-11 21:03:38 +0000
@@ -620,16 +620,20 @@
return anErrno == ENFILE || anErrno == EMFILE;
}
+/**
+ * Function to set the TOS value of packets. Sets the value on the socket
+ * which then gets copied to the packets. Called from client_side_reply.cc
+ */
int
-comm_set_tos(int fd, int tos)
+comm_set_tos(int fd, unsigned char tos)
{
#ifdef IP_TOS
- int x = setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int));
+ int x = setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(unsigned char));
if (x < 0)
- debugs(50, 1, "comm_set_tos: setsockopt(IP_TOS) on FD " << fd << ": " << xstrerror());
+ debugs(50, 2, "comm_set_tos: setsockopt(IP_TOS) on FD " << fd << ": " << xstrerror());
return x;
#else
- debugs(50, 0, "WARNING: setsockopt(IP_TOS) not supported on this platform");
+ debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(IP_TOS) not supported on this platform");
return -1;
#endif
}
@@ -647,6 +651,24 @@
}
/**
+ * Function to set the netfilter mark value of packets. Sets the value on the
+ * socket which then gets copied to the packets. Called from client_side_reply.cc
+ */
+int
+comm_set_nfmark(int fd, unsigned int mark)
+{
+#ifdef SO_MARK
+ int x = setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
+ if (x < 0)
+ debugs(50, 2, "comm_set_nfmark: setsockopt(SO_MARK) on FD " << fd << ": " << xstrerror());
+ return x;
+#else
+ debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(SO_MARK) not supported on this platform");
+ return -1;
+#endif
+}
+
+/**
* Set the socket IP_TRANSPARENT option for Linux TPROXY v4 support.
*/
void
@@ -678,7 +700,7 @@
const char *note)
{
int new_socket;
- int tos = 0;
+ unsigned char tos = 0;
struct addrinfo *AI = NULL;
PROF_start(comm_open);
=== modified file 'src/comm.h'
--- src/comm.h 2010-07-06 23:09:44 +0000
+++ src/comm.h 2010-08-11 16:48:19 +0000
@@ -76,7 +76,8 @@
SQUIDCEXTERN int comm_openex(int, int, Ip::Address &, int, unsigned char TOS, const char *);
SQUIDCEXTERN u_short comm_local_port(int fd);
-SQUIDCEXTERN int comm_set_tos(int fd, int tos);
+SQUIDCEXTERN int comm_set_tos(int fd, unsigned char tos);
+SQUIDCEXTERN int comm_set_nfmark(int fd, unsigned int mark);
SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t);
SQUIDCEXTERN void commResetSelect(int);
=== modified file 'src/fde.h'
--- src/fde.h 2010-07-06 23:09:44 +0000
+++ src/fde.h 2010-08-07 07:23:43 +0000
@@ -109,9 +109,10 @@
long handle;
} win32;
#endif
-#if USE_ZPH_QOS
- unsigned char upstreamTOS; /* see FwdState::dispatch() */
-#endif
+ unsigned char upstreamTOS; /* Stores the TOS flags of the packets
+ from the remote server. See FwdState::dispatch() */
+ unsigned int upstreamMark; /* Stores the Netfilter mark value of the connection
+ to the remote server. See FwdState::dispatch() */
private:
/** Clear the fde class back to NULL equivalent. */
=== modified file 'src/forward.cc'
--- src/forward.cc 2010-08-10 10:33:04 +0000
+++ src/forward.cc 2010-08-11 16:35:25 +0000
@@ -42,6 +42,7 @@
#include "hier_code.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "ip/QosConfig.h"
#include "MemObject.h"
#include "pconn.h"
#include "SquidTime.h"
@@ -778,7 +779,7 @@
int ftimeout = Config.Timeout.forward - (squid_curtime - start_t);
Ip::Address outgoing;
- unsigned short tos;
+ unsigned char tos;
Ip::Address client_addr;
assert(fs);
assert(server_fd == -1);
@@ -990,44 +991,26 @@
netdbPingSite(request->GetHost());
-#if USE_ZPH_QOS && defined(_SQUID_LINUX_)
- /* Bug 2537: This part of ZPH only applies to patched Linux kernels. */
-
- /* Retrieves remote server TOS value, and stores it as part of the
+ /* Retrieves remote server TOS or MARK 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.
+ * remote server's TOS/MARK 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 * pbuf = buf;
- while (pbuf-buf < len) {
- struct cmsghdr *o = (struct cmsghdr*)pbuf;
- if (o->cmsg_len<=0)
- break;
+ if (Ip::TheQos.isMarkActive()) {
+ fde * clientFde = &fd_table[client_fd];
+ fde * servFde = &fd_table[server_fd];
+ if (clientFde && servFde) {
+ /* Get the netfilter mark for the connection */
+ Ip::TheQos.getUpstreamNfMark(clientFde, servFde, server_fd);
+ }
+ }
- if (o->cmsg_level == SOL_IP && o->cmsg_type == IP_TOS) {
- int *tmp = (int*)CMSG_DATA(o);
- clientFde->upstreamTOS = (unsigned char)*tmp;
- break;
- }
- pbuf += CMSG_LEN(o->cmsg_len);
- }
- } else {
- debugs(33, 1, "ZPH: error in getsockopt(IP_PKTOPTIONS) on FD "<hier, fs->code, nextHop);
}
-
/**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
static void
=== modified file 'src/ip/QosConfig.cc'
--- src/ip/QosConfig.cc 2010-04-17 02:29:04 +0000
+++ src/ip/QosConfig.cc 2010-08-11 18:58:57 +0000
@@ -1,79 +1,383 @@
#include "squid.h"
-
-#if USE_ZPH_QOS
-
#include "QosConfig.h"
-Ip::Qos::QosConfig Ip::Qos::TheConfig;
-
-Ip::Qos::QosConfig::QosConfig() :
- tos_local_hit(0),
- tos_sibling_hit(0),
- tos_parent_hit(0),
- preserve_miss_tos(1),
- preserve_miss_tos_mask(255)
-{
- ;
+
+Ip::Qos Ip::TheQos;
+
+Ip::Qos::Qos()
+{
+ tos_local_hit = 0;
+ tos_sibling_hit = 0;
+ tos_parent_hit = 0;
+ preserve_miss_tos = false;
+ preserve_miss_tos_mask = 0xFF;
+ mark_local_hit = 0;
+ mark_sibling_hit = 0;
+ mark_parent_hit = 0;
+ preserve_miss_mark = false;
+ preserve_miss_mark_mask = 0xFFFFFFFF;
+}
+
+Ip::Qos::~Qos()
+{
+ memset(this,0,sizeof(Ip::Qos));
}
void
-Ip::Qos::QosConfig::parseConfigLine()
+Ip::Qos::parseConfigLine()
{
- // %i honors 0 and 0x prefixes, which are important for things like umask
+ // strtoul honors 0 and 0x prefixes, which are important for things like umask
/* parse options ... */
char *token;
+ /* These are set as appropriate and then used to check whether the initial loop has been done */
+ bool mark = false;
+ bool tos = false;
+ /* Assume preserve is true. We don't set at initialisation as this affects isTosActive().
+ We have to do this now, as we may never match the 'tos' parameter below */
+#if !USE_QOS_TOS
+ debugs(3, DBG_CRITICAL, "ERROR: Invalid option 'qos_flows'. QOS features not enabled in this build");
+ self_destruct();
+#endif
+
while ( (token = strtok(NULL, w_space)) ) {
+ // Work out TOS or mark. Default to TOS for backwards compatibility
+ if (!(mark || tos)) {
+ if (strncmp(token, "mark",4) == 0) {
+#if USE_QOS_NFMARK
+ mark = true;
+ // Assume preserve is true. We don't set at initialisation as this affects isMarkActive()
+ preserve_miss_mark = 1;
+#else
+ debugs(3, DBG_CRITICAL, "ERROR: Invalid parameter 'mark' in qos_flows option. "
+ << "Netfilter marking not enabled in this build");
+ self_destruct();
+#endif
+ } else if (strncmp(token, "tos",3) == 0) {
+ preserve_miss_tos = true;
+ tos = true;
+ } else {
+ preserve_miss_tos = true;
+ tos = true;
+ }
+ }
+
if (strncmp(token, "local-hit=",10) == 0) {
- sscanf(&token[10], "%i", &tos_local_hit);
+ if (mark) {
+ mark_local_hit = (unsigned int)strtoul(&token[10], NULL, 0);
+ } else {
+ tos_local_hit = (unsigned char)strtoul(&token[10], NULL, 0);
+ }
} else if (strncmp(token, "sibling-hit=",12) == 0) {
- sscanf(&token[12], "%i", &tos_sibling_hit);
+ if (mark) {
+ mark_sibling_hit = (unsigned int)strtoul(&token[12], NULL, 0);
+ } else {
+ tos_sibling_hit = (unsigned char)strtoul(&token[12], NULL, 0);
+ }
} else if (strncmp(token, "parent-hit=",11) == 0) {
- sscanf(&token[11], "%i", &tos_parent_hit);
+ if (mark) {
+ mark_parent_hit = (unsigned int)strtoul(&token[11], NULL, 0);
+ } else {
+ tos_parent_hit = (unsigned char)strtoul(&token[11], NULL, 0);
+ }
} else if (strcmp(token, "disable-preserve-miss") == 0) {
- preserve_miss_tos = 0;
- preserve_miss_tos_mask = 0;
- } else if (preserve_miss_tos && strncmp(token, "miss-mask=",10) == 0) {
- sscanf(&token[10], "%i", &preserve_miss_tos_mask);
+ if (preserve_miss_tos_mask!=0xFF || preserve_miss_mark_mask!=0xFFFFFFFF) {
+ debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set with disable-preserve-miss");
+ }
+ if (mark) {
+ preserve_miss_mark = false;
+ preserve_miss_mark_mask = 0;
+ } else {
+ preserve_miss_tos = false;
+ preserve_miss_tos_mask = 0;
+ }
+ } else if (strncmp(token, "miss-mask=",10) == 0) {
+ if (mark && preserve_miss_mark) {
+ preserve_miss_mark_mask = (unsigned int)strtoul(&token[10], NULL, 0);
+ } else if (preserve_miss_tos) {
+ preserve_miss_tos_mask = (unsigned char)strtoul(&token[10], NULL, 0);
+ } else {
+ debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set with disable-preserve-miss");
+ }
}
}
}
+
/**
* NOTE: Due to the low-level nature of the library these
* objects are part of the dump function must be self-contained.
- * which means no StoreEntry refrences. Just a basic char* buffer.
+ * which means no StoreEntry references. Just a basic char* buffer.
*/
void
-Ip::Qos::QosConfig::dumpConfigLine(char *entry, const char *name) const
+Ip::Qos::dumpConfigLine(char *entry, const char *name)
{
char *p = entry;
- snprintf(p, 10, "%s", name); // strlen("qos_flows ");
- p += strlen(name);
-
- if (tos_local_hit >0) {
- snprintf(p, 15, " local-hit=%2x", tos_local_hit);
- p += 15;
- }
-
- if (tos_sibling_hit >0) {
- snprintf(p, 17, " sibling-hit=%2x", tos_sibling_hit);
- p += 17;
- }
- if (tos_parent_hit >0) {
- snprintf(p, 16, " parent-hit=%2x", tos_parent_hit);
- p += 16;
- }
- if (preserve_miss_tos != 0) {
- snprintf(p, 22, " disable-preserve-miss");
- p += 22;
- }
- if (preserve_miss_tos && preserve_miss_tos_mask != 0) {
- snprintf(p, 15, " miss-mask=%2x", preserve_miss_tos_mask);
- p += 15;
- }
- snprintf(p, 1, "\n");
-// p += 1;
-}
-
-#endif /* USE_ZPH_QOS */
+ if (isTosActive()) {
+
+ p += snprintf(p, 11, "%s", name); // strlen("qos_flows ");
+ p += snprintf(p, 4, "%s", "tos");
+
+ if (tos_local_hit >0) {
+ p += snprintf(p, 16, " local-hit=0x%02X", tos_local_hit);
+ }
+ if (tos_sibling_hit >0) {
+ p += snprintf(p, 18, " sibling-hit=0x%02X", tos_sibling_hit);
+ }
+ if (tos_parent_hit >0) {
+ p += snprintf(p, 17, " parent-hit=0x%02X", tos_parent_hit);
+ }
+ if (preserve_miss_tos == 0) {
+ p += snprintf(p, 23, " disable-preserve-miss");
+ }
+ if (preserve_miss_tos && preserve_miss_tos_mask != 0) {
+ p += snprintf(p, 16, " miss-mask=0x%02X", preserve_miss_tos_mask);
+ }
+ p += snprintf(p, 2, "\n");
+ }
+
+ if (isMarkActive()) {
+ p += snprintf(p, 11, "%s", name); // strlen("qos_flows ");
+ p += snprintf(p, 5, "%s", "mark");
+
+ if (mark_local_hit >0) {
+ p += snprintf(p, 22, " local-hit=0x%02X", mark_local_hit);
+ }
+ if (mark_sibling_hit >0) {
+ p += snprintf(p, 24, " sibling-hit=0x%02X", mark_sibling_hit);
+ }
+ if (mark_parent_hit >0) {
+ p += snprintf(p, 23, " parent-hit=0x%02X", mark_parent_hit);
+ }
+ if (preserve_miss_mark == 0) {
+ p += snprintf(p, 23, " disable-preserve-miss");
+ }
+ if (preserve_miss_mark && preserve_miss_mark_mask != 0) {
+ p += snprintf(p, 22, " miss-mask=0x%02X", preserve_miss_mark_mask);
+ }
+ p += snprintf(p, 2, "\n");
+ }
+}
+
+/**
+ * Function to return the appropriate TOS value to set on packets when
+ * items have not been retrieved from local cache. Called by
+ * clientReplyContext::sendMoreData if QOS is enabled for TOS.
+ */
+unsigned char
+Ip::Qos::getTosLocalMiss(const int fd, const HierarchyLogEntry hier)
+{
+ unsigned char tos = 0;
+ if (tos_sibling_hit && hier.code==SIBLING_HIT ) {
+ tos = tos_sibling_hit;
+ debugs(33, 2, "QOS: Sibling Peer hit with hier.code=" << hier.code << ", TOS=" << (int)tos);
+ } else if (tos_parent_hit && hier.code==PARENT_HIT) {
+ tos = tos_parent_hit;
+ debugs(33, 2, "QOS: Parent Peer hit with hier.code=" << hier.code << ", TOS=" << (int)tos);
+ } else if (preserve_miss_tos && preserve_miss_tos_mask) {
+ tos = fd_table[fd].upstreamTOS & preserve_miss_tos_mask;
+ debugs(33, 2, "QOS: Preserving TOS on miss, TOS="<ai_addr, &(addr->ai_addrlen));
+ serv_fde_local_conn = *addr;
+ serv_fde_local_conn.GetAddrInfo(addr);
+
+ unsigned short serv_fde_local_port = ((struct sockaddr_in*)addr->ai_addr)->sin_port;
+ struct in6_addr serv_fde_local_ip6;
+ struct in_addr serv_fde_local_ip;
+
+ if (Ip::EnableIpv6 && serv_fde_local_conn.IsIPv6()) {
+ serv_fde_local_ip6 = ((struct sockaddr_in6*)addr->ai_addr)->sin6_addr;
+ nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
+ struct in6_addr serv_fde_remote_ip6;
+ inet_pton(AF_INET6,servFde->ipaddr,(struct in6_addr*)&serv_fde_remote_ip6);
+ nfct_set_attr(ct, ATTR_IPV6_DST, serv_fde_remote_ip6.s6_addr);
+ nfct_set_attr(ct, ATTR_IPV6_SRC, serv_fde_local_ip6.s6_addr);
+ } else {
+ serv_fde_local_ip = ((struct sockaddr_in*)addr->ai_addr)->sin_addr;
+ nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
+ nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr(servFde->ipaddr));
+ nfct_set_attr_u32(ct, ATTR_IPV4_SRC, serv_fde_local_ip.s_addr);
+ }
+
+ nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP);
+ nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(servFde->remote_port));
+ nfct_set_attr_u16(ct, ATTR_PORT_SRC, serv_fde_local_port);
+
+ /* Open a handle to the conntrack */
+ if (struct nfct_handle *h = nfct_open(CONNTRACK, 0)) {
+ /* Register the callback. The callback function will record the mark value. */
+ nfct_callback_register(h, NFCT_T_ALL, GetNfMarkCallback, (void *)clientFde);
+ /* Query the conntrack table using the data previously set */
+ int x = nfct_query(h, NFCT_Q_GET, ct);
+ if (x == -1) {
+ debugs(17, 2, "QOS: Failed to retrieve connection mark: (" << x << ") " << strerror(errno)
+ << " (Destination " << servFde->ipaddr << ":" << servFde->remote_port
+ << ", source " << serv_fde_local_conn << ")" );
+ }
+
+ nfct_close(h);
+ } else {
+ debugs(17, 2, "QOS: Failed to open conntrack handle for upstream netfilter mark retrieval.");
+ }
+ serv_fde_local_conn.FreeAddrInfo(addr);
+ nfct_destroy(ct);
+
+ } else {
+ debugs(17, 2, "QOS: Failed to allocate new conntrack for upstream netfilter mark retrieval.");
+ }
+#endif
+}
+
+/**
+ * Returns true or false depending on whether we should carry out the
+ * QOS functions for the TOS flags
+ */
+bool
+Ip::Qos::isTosActive()
+{
+ if (tos_local_hit || tos_sibling_hit || tos_parent_hit || preserve_miss_tos) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Returns true or false depending on whether we should carry out the
+ * QOS functions for netfilter marks
+ */
+bool
+Ip::Qos::isMarkActive()
+{
+ if (mark_local_hit || mark_sibling_hit || mark_parent_hit || preserve_miss_mark) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#if USE_QOS_NFMARK
+/**
+ * Callback function to mark connection once it's been found.
+ * This function is called by the libnetfilter_conntrack
+ * libraries, during nfct_query in Ip::Qos::getUpstreamNfMark.
+ * nfct_callback_register is used to register this function.
+*/
+int
+Ip::Qos::GetNfMarkCallback(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ fde *clientFde = (fde *)data;
+ clientFde->upstreamMark = nfct_get_attr_u32(ct, ATTR_MARK);
+ debugs(17, 3, "QOS: Retrieved connection mark value: " << clientFde->upstreamMark);
+
+ return NFCT_CB_CONTINUE;
+}
+#endif
=== modified file 'src/ip/QosConfig.h'
--- src/ip/QosConfig.h 2010-04-18 00:13:00 +0000
+++ src/ip/QosConfig.h 2010-08-11 16:33:21 +0000
@@ -2,33 +2,51 @@
#define SQUID_QOSCONFIG_H
#include "config.h"
-
-#if USE_ZPH_QOS
+#include "HierarchyLogEntry.h"
+#include "fde.h"
+#if HAVE_LIBNETFILTER_CONNTRACK_LIBNETFILTER_CONNTRACK_H
+#include "ip/tools.h"
+#include
+#include
+#endif
namespace Ip
{
-namespace Qos
-{
-
-class QosConfig
-{
-public:
- int tos_local_hit;
- int tos_sibling_hit;
- int tos_parent_hit;
- int preserve_miss_tos;
- int preserve_miss_tos_mask;
-
-public:
- QosConfig();
- ~QosConfig() {};
-
+class Qos
+{
+public:
+ Qos();
+ ~Qos();
void parseConfigLine();
- void dumpConfigLine(char *entry, const char *name) const;
+ void dumpConfigLine(char *entry, const char *name);
+ unsigned char getTosLocalMiss(const int fd, const HierarchyLogEntry hier);
+ int getNfmarkLocalMiss(const int fd, const HierarchyLogEntry hier);
+ unsigned char getTosLocalHit();
+ int getNfmarkLocalHit();
+ void getUpstreamTOS(fde *clientFde, const int server_fd);
+ void getUpstreamNfMark(const fde *clientFde, const fde *servFde, const int server_fd);
+ bool isTosActive();
+ bool isMarkActive();
+#if USE_QOS_NFMARK
+ static int GetNfMarkCallback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *clientFde);
+#endif
+
+private:
+ unsigned char tos_local_hit;
+ unsigned char tos_sibling_hit;
+ unsigned char tos_parent_hit;
+ bool preserve_miss_tos;
+ unsigned char preserve_miss_tos_mask;
+ unsigned int mark_local_hit;
+ unsigned int mark_sibling_hit;
+ unsigned int mark_parent_hit;
+ bool preserve_miss_mark;
+ unsigned int preserve_miss_mark_mask;
+
};
-extern QosConfig TheConfig;
+extern Qos TheQos;
/* legacy parser access wrappers */
#define parse_QosConfig(X) (X)->parseConfigLine()
@@ -39,8 +57,6 @@
storeAppendPrintf(e, "%s", temp); \
} while(0);
-}; // namespace Qos
}; // namespace Ip
-#endif /* USE_ZPH_QOS */
#endif /* SQUID_QOSCONFIG_H */
=== modified file 'src/ip/stubQosConfig.cc'
--- src/ip/stubQosConfig.cc 2010-04-25 07:07:14 +0000
+++ src/ip/stubQosConfig.cc 2010-08-05 15:02:00 +0000
@@ -1,6 +1,6 @@
#include "squid.h"
-#if USE_ZPH_QOS
+#if USE_QOS_TOS
#include "ip/QosConfig.h"
#include "Store.h"
@@ -44,4 +44,4 @@
; /* Not needed in stub */
}
-#endif /* USE_ZPH_QOS */
+#endif /* USE_QOS_TOS */
=== modified file 'src/tools.cc'
--- src/tools.cc 2010-08-09 11:06:36 +0000
+++ src/tools.cc 2010-08-11 14:47:08 +0000
@@ -43,6 +43,7 @@
#include "ProtoPort.h"
#include "SquidMath.h"
#include "SquidTime.h"
+#include "ip/QosConfig.h"
#include "ipc/Kids.h"
#include "ipc/Coordinator.h"
#include "SwapDir.h"
@@ -1307,7 +1308,7 @@
cap_value_t cap_list[10];
cap_list[ncaps++] = CAP_NET_BIND_SERVICE;
- if (Ip::Interceptor.TransparentActive()) {
+ if (Ip::Interceptor.TransparentActive() || Ip::TheQos.isMarkActive()) {
cap_list[ncaps++] = CAP_NET_ADMIN;
}