On 07/12/2013 08:06 PM, Amos Jeffries wrote:
> On 13/07/2013 2:05 a.m., Tsantilas Christos wrote:
>> This patch add new logformat codes to log TOS/DSCP values and netfilter
>> marks for client and server connections. If multiple outgoing
>> connections were used, the last used connection value logged.
>> The values printed in hexadecimal form.
>>
>> The logformat codes are:
>> %>tos Client connection tos mark set by Squid
>> %<tos Server connection tos mark set by Squid
>
> Can you call the code "qos" please? And document it exactly as you wrote
> above as "the TOS/DSCP value" removing the word "mark" from those lines
> to avoid confusion.
OK.
>
>
>> %>nfmark Client connection netfilter mark set by Squid
>> %<nfmark Server connection netfilter mark set by Squid
>>
>> I must note that the setsockopt(...,IPPROTO_IP, IP_TOS...) system call
>> we are using to set tos value may not set the configured value. It can
>> set only values which are multiple of 4. In this case we log wrong
>> value, the configured not the value is set.
>>
>> To get the real value we must modify the Ip::Qos::setSockTos method to
>> set the TOS and then read it again from socket to see which value is
>> used. However this is means one more system call to set the tos value.
>
> We should be auto-adjusting the configured value to make it a multiple
> of 4 before setting. So no set,read cycle required.
>
> Please rename these:
>
> + LFT_PEER_INCOMING_TOS,
> + LFT_PEER_OUTGOING_TOS,
> + LFT_PEER_INCOMING_NFMARK,
> + LFT_PEER_OUTGOING_NFMARK,
>
> We already have the naming scheme LFT_CLIENT_LOCAL_* and
> LFT_SERVER_LOCAL_* for the relevant TCP connections local-end details
> (ie. "set by Squid").
Done. it is match better now...
>
> Although I am not certain what you are calling the Client connection
> details set by Squid are in fact set by Squid and not the received ones
> set by the client. Please check that. If so the LFT_CLIENT_LOCAL_ part
> of the naming scheme should be LFT_CLIENT_*
Yes the values set by squid, not by client or web server.
The LFT_CLIENT_LOCAL and LFT_SERVER_LOCAL_ looks good options.
>
> Amos
>
Log TOS and Netfilter marks set by Squid
This patch add new logformat codes to log TOS/DSCP values and netfilter marks
for client and server connections. If multiple outgoing connections were used,
the last used connection value logged.
The values printed in hexadecimal form.
The logformat codes are:
%>qos Client connection TOS/DSCP value set by Squid
%<qos Server connection TOS/DSCP value set by Squid
%>nfmark Client connection netfilter mark set by Squid
%<nfmark Server connection netfilter mark set by Squid
This patch also modify qos related code to set Comm::Connection::nfmark and
Comm::Connection::tos members in Ip::Qos::setSockNfmark and Ip::Qos::setSockTos
methods. The Comm::Connection members are now set only if the tos and nfmark
set successfuly.
This is a Measurement Factory project
=== modified file 'src/FwdState.cc'
--- src/FwdState.cc 2013-06-18 22:30:39 +0000
+++ src/FwdState.cc 2013-07-15 07:14:08 +0000
@@ -1147,47 +1147,47 @@
// Avoid pconns after races so that the same client does not suffer twice.
// This does not increase the total number of connections because we just
// closed the connection that failed the race. And re-pinning assumes this.
if (pconnRace != raceHappened)
temp = fwdPconnPool->pop(serverDestinations[0], host, checkRetriable());
const bool openedPconn = Comm::IsConnOpen(temp);
pconnRace = openedPconn ? racePossible : raceImpossible;
// if we found an open persistent connection to use. use it.
if (openedPconn) {
serverConn = temp;
flags.connected_okay = true;
debugs(17, 3, HERE << "reusing pconn " << serverConnection());
++n_tries;
comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
/* Update server side TOS and Netfilter mark on the connection. */
if (Ip::Qos::TheConfig.isAclTosActive()) {
- temp->tos = GetTosToServer(request);
- Ip::Qos::setSockTos(temp, temp->tos);
+ const tos_t tos = GetTosToServer(request);
+ Ip::Qos::setSockTos(temp, tos);
}
#if SO_MARK
if (Ip::Qos::TheConfig.isAclNfmarkActive()) {
- temp->nfmark = GetNfmarkToServer(request);
- Ip::Qos::setSockNfmark(temp, temp->nfmark);
+ const nfmark_t nfmark = GetNfmarkToServer(request);
+ Ip::Qos::setSockNfmark(temp, nfmark);
}
#endif
dispatch();
return;
}
// We will try to open a new connection, possibly to the same destination.
// We reset serverDestinations[0] in case we are using it again because
// ConnOpener modifies its destination argument.
serverDestinations[0]->local.port(0);
serverConn = NULL;
#if URL_CHECKSUM_DEBUG
entry->mem_obj->checkUrlChecksum();
#endif
/* Get the server side TOS and Netfilter mark to be set on the connection. */
if (Ip::Qos::TheConfig.isAclTosActive()) {
serverDestinations[0]->tos = GetTosToServer(request);
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2013-06-18 06:22:13 +0000
+++ src/cf.data.pre 2013-07-15 07:18:27 +0000
@@ -3670,40 +3670,44 @@
adaptation_meta configuration parameter.
If no argument given all meta headers logged.
Connection related format codes:
>a Client source IP address
>A Client FQDN
>p Client source port
>eui Client source EUI (MAC address, EUI-48 or EUI-64 identifier)
>la Local IP address the client connected to
>lp Local port number the client connected to
la Local listening IP address the client connection was connected to.
lp Local listening port number the client connection was connected to.
<a Server IP address of the last server or peer connection
<A Server FQDN or peer name
<p Server port number of the last server or peer connection
<la Local IP address of the last server or peer connection
<lp Local port number of the last server or peer connection
+ >qos Client connection TOS/DSCP value set by Squid
+ <qos Server connection TOS/DSCP value set by Squid
+ >nfmark Client connection netfilter mark set by Squid
+ <nfmark Server connection netfilter mark set by Squid
Time related format codes:
ts Seconds since epoch
tu subsecond time (milliseconds)
tl Local time. Optional strftime format argument
default %d/%b/%Y:%H:%M:%S %z
tg GMT time. Optional strftime format argument
default %d/%b/%Y:%H:%M:%S %z
tr Response time (milliseconds)
dt Total time spent making DNS lookups (milliseconds)
Access Control related format codes:
et Tag returned by external acl
ea Log string returned by external acl
un User name (any available)
ul User name from authentication
ue User name from external acl helper
ui User name from ident
=== modified file 'src/comm/Connection.cc'
--- src/comm/Connection.cc 2013-05-05 01:19:46 +0000
+++ src/comm/Connection.cc 2013-07-15 07:14:08 +0000
@@ -30,40 +30,41 @@
Comm::Connection::~Connection()
{
if (fd >= 0) {
debugs(5, 4, "BUG #3329: Orphan Comm::Connection: " << *this);
debugs(5, 4, "NOTE: " << ++lost_conn << " Orphans since last started.");
close();
}
cbdataReferenceDone(peer_);
}
Comm::ConnectionPointer
Comm::Connection::copyDetails() const
{
ConnectionPointer c = new Comm::Connection;
c->local = local;
c->remote = remote;
c->peerType = peerType;
c->tos = tos;
+ c->nfmark = nfmark;
c->flags = flags;
// ensure FD is not open in the new copy.
c->fd = -1;
// ensure we have a cbdata reference to peer_ not a straight ptr copy.
c->peer_ = cbdataReference(getPeer());
return c;
}
void
Comm::Connection::close()
{
if (isOpen()) {
comm_close(fd);
fd = -1;
if (CachePeer *p=getPeer())
-- p->stats.conn_open;
}
=== modified file 'src/format/ByteCode.h'
--- src/format/ByteCode.h 2013-02-11 23:11:12 +0000
+++ src/format/ByteCode.h 2013-07-15 07:26:42 +0000
@@ -180,35 +180,39 @@
LFT_ICAP_REQ_HEADER_ELEM,
LFT_ICAP_REQ_ALL_HEADERS,
LFT_ICAP_REP_HEADER,
LFT_ICAP_REP_HEADER_ELEM,
LFT_ICAP_REP_ALL_HEADERS,
LFT_ICAP_TR_RESPONSE_TIME,
LFT_ICAP_IO_TIME,
LFT_ICAP_OUTCOME,
LFT_ICAP_STATUS_CODE,
#endif
#if USE_SSL
LFT_SSL_BUMP_MODE,
LFT_SSL_USER_CERT_SUBJECT,
LFT_SSL_USER_CERT_ISSUER,
#endif
LFT_NOTE,
+ LFT_CLIENT_LOCAL_TOS,
+ LFT_SERVER_LOCAL_TOS,
+ LFT_CLIENT_LOCAL_NFMARK,
+ LFT_SERVER_LOCAL_NFMARK,
LFT_PERCENT /* special string cases for escaped chars */
} ByteCode_t;
/// Quoting style for a format output.
enum Quoting {
LOG_QUOTE_NONE = 0,
LOG_QUOTE_QUOTES,
LOG_QUOTE_MIMEBLOB,
LOG_QUOTE_URL,
LOG_QUOTE_RAW
};
} // namespace Format
#endif /* _SQUID_FMT_BYTECODE_H */
=== modified file 'src/format/Format.cc'
--- src/format/Format.cc 2013-06-11 09:25:07 +0000
+++ src/format/Format.cc 2013-07-15 07:28:57 +0000
@@ -1029,40 +1029,69 @@
}
case LFT_SSL_USER_CERT_SUBJECT:
if (X509 *cert = al->cache.sslClientCert.get()) {
if (X509_NAME *subject = X509_get_subject_name(cert)) {
X509_NAME_oneline(subject, tmp, sizeof(tmp));
out = tmp;
}
}
break;
case LFT_SSL_USER_CERT_ISSUER:
if (X509 *cert = al->cache.sslClientCert.get()) {
if (X509_NAME *issuer = X509_get_issuer_name(cert)) {
X509_NAME_oneline(issuer, tmp, sizeof(tmp));
out = tmp;
}
}
break;
#endif
+
+ case LFT_CLIENT_LOCAL_TOS:
+ if (al->tcpClient != NULL) {
+ snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->tcpClient->tos);
+ out = tmp;
+ }
+ break;
+
+ case LFT_SERVER_LOCAL_TOS:
+ if (al->hier.tcpServer != NULL) {
+ snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->hier.tcpServer->tos);
+ out = tmp;
+ }
+ break;
+
+ case LFT_CLIENT_LOCAL_NFMARK:
+ if (al->tcpClient != NULL) {
+ snprintf(tmp, sizeof(tmp), "0x%x", al->tcpClient->nfmark);
+ out = tmp;
+ }
+ break;
+
+ case LFT_SERVER_LOCAL_NFMARK:
+ if (al->hier.tcpServer != NULL) {
+ snprintf(tmp, sizeof(tmp), "0x%x", al->hier.tcpServer->nfmark);
+ out = tmp;
+ }
+ break;
+
case LFT_NOTE:
if (fmt->data.string) {
#if USE_ADAPTATION
Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer();
if (ah != NULL && ah->metaHeaders != NULL) {
if (const char *meta = ah->metaHeaders->find(fmt->data.string))
sb.append(meta);
}
#endif
if (al->notes != NULL) {
if (const char *note = al->notes->find(fmt->data.string)) {
if (sb.size())
sb.append(", ");
sb.append(note);
}
}
out = sb.termedBuf();
quote = 1;
} else {
#if USE_ADAPTATION
=== modified file 'src/format/Token.cc'
--- src/format/Token.cc 2013-05-22 01:04:34 +0000
+++ src/format/Token.cc 2013-07-15 07:28:12 +0000
@@ -29,41 +29,40 @@
{">v", LFT_REQUEST_VERSION_OLD_2X},
{"%", LFT_PERCENT},
{NULL, LFT_NONE} /* this must be last */
};
/// 2-char tokens
static TokenTableEntry TokenTable2C[] = {
{">la", LFT_CLIENT_LOCAL_IP},
{"la", LFT_LOCAL_LISTENING_IP},
{">lp", LFT_CLIENT_LOCAL_PORT},
{"lp", LFT_LOCAL_LISTENING_PORT},
/*{ "lA", LFT_LOCAL_NAME }, */
{"<la", LFT_SERVER_LOCAL_IP},
{"oa", LFT_SERVER_LOCAL_IP_OLD_27},
{"<lp", LFT_SERVER_LOCAL_PORT},
- /* {"ot", LFT_PEER_OUTGOING_TOS}, */
{"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
{"tu", LFT_TIME_SUBSECOND},
{"tl", LFT_TIME_LOCALTIME},
{"tg", LFT_TIME_GMT},
{"tr", LFT_TIME_TO_HANDLE_REQUEST},
{"<pt", LFT_PEER_RESPONSE_TIME},
{"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME},
{"dt", LFT_DNS_WAIT_TIME},
{">ha", LFT_ADAPTED_REQUEST_HEADER},
{">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS},
{"un", LFT_USER_NAME},
{"ul", LFT_USER_LOGIN},
/*{ "ur", LFT_USER_REALM }, */
/*{ "us", LFT_USER_SCHEME }, */
{"ui", LFT_USER_IDENT},
{"ue", LFT_USER_EXTERNAL},
@@ -105,40 +104,44 @@
{"<st", LFT_REPLY_SIZE_TOTAL},
{"<sH", LFT_REPLY_HIGHOFFSET},
{"<sS", LFT_REPLY_OBJECTSIZE},
/*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
{"<sh", LFT_REPLY_SIZE_HEADERS },
/*{ "<sb", LFT_REPLY_SIZE_BODY }, */
/*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
{"et", LFT_TAG},
{"st", LFT_IO_SIZE_TOTAL},
{"ea", LFT_EXT_LOG},
{"sn", LFT_SEQUENCE_NUMBER},
{NULL, LFT_NONE} /* this must be last */
};
/// Miscellaneous >2 byte tokens
static TokenTableEntry TokenTableMisc[] = {
{">eui", LFT_CLIENT_EUI},
+ {">qos", LFT_CLIENT_LOCAL_TOS},
+ {"<qos", LFT_SERVER_LOCAL_TOS},
+ {">nfmark", LFT_CLIENT_LOCAL_NFMARK},
+ {"<nfmark", LFT_SERVER_LOCAL_NFMARK},
{"err_code", LFT_SQUID_ERROR },
{"err_detail", LFT_SQUID_ERROR_DETAIL },
{"note", LFT_NOTE },
{NULL, LFT_NONE} /* this must be last */
};
#if USE_ADAPTATION
static TokenTableEntry TokenTableAdapt[] = {
{"all_trs", LFT_ADAPTATION_ALL_XACT_TIMES},
{"sum_trs", LFT_ADAPTATION_SUM_XACT_TIMES},
{"<last_h", LFT_ADAPTATION_LAST_HEADER},
{NULL, LFT_NONE} /* this must be last */
};
#endif
#if ICAP_CLIENT
/// ICAP (icap::) tokens
static TokenTableEntry TokenTableIcap[] = {
{"tt", LFT_ICAP_TOTAL_TIME},
{"<last_h", LFT_ADAPTATION_LAST_HEADER}, // deprecated
=== modified file 'src/ip/Qos.cci'
--- src/ip/Qos.cci 2013-01-08 23:51:02 +0000
+++ src/ip/Qos.cci 2013-07-15 07:14:08 +0000
@@ -1,50 +1,54 @@
/* Inline QOS functions */
#include "comm/Connection.h"
#include "Debug.h"
int
Ip::Qos::setSockTos(const Comm::ConnectionPointer &conn, tos_t tos)
{
#if defined(IP_TOS)
// Bug 3731: FreeBSD produces 'invalid option'
// unless we pass it a 32-bit variable storing 8-bits of data.
// NP: it is documented as 'int' for all systems, even those like Linux which accept 8-bit char
// so we convert to a int before setting.
int bTos = tos;
int x = setsockopt(conn->fd, IPPROTO_IP, IP_TOS, &bTos, sizeof(bTos));
if (x < 0)
debugs(50, 2, "Ip::Qos::setSockTos: setsockopt(IP_TOS) on " << conn << ": " << xstrerror());
+ else
+ conn->tos = tos;
return x;
#else
debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(IP_TOS) not supported on this platform");
return -1;
#endif
}
int
Ip::Qos::setSockNfmark(const Comm::ConnectionPointer &conn, nfmark_t mark)
{
#if SO_MARK && USE_LIBCAP
int x = setsockopt(conn->fd, SOL_SOCKET, SO_MARK, &mark, sizeof(nfmark_t));
if (x < 0)
debugs(50, 2, "setSockNfmark: setsockopt(SO_MARK) on " << conn << ": " << xstrerror());
+ else
+ conn->nfmark = mark;
return x;
#elif USE_LIBCAP
debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(SO_MARK) not supported on this platform");
return -1;
#else
debugs(50, DBG_IMPORTANT, "WARNING: Netfilter marking disabled (netfilter marking requires build with LIBCAP)");
return -1;
#endif
}
bool
Ip::Qos::Config::isHitTosActive() const
{
return (tosLocalHit || tosSiblingHit || tosParentHit || tosMiss || preserveMissTos);
}
bool
Ip::Qos::Config::isHitNfmarkActive() const
{
return (markLocalHit || markSiblingHit || markParentHit || markMiss || preserveMissMark);