On Wed, 2010-09-15 at 02:06 +0000, Amos Jeffries wrote:
> On Tue, 14 Sep 2010 23:55:20 +0100, Andrew Beverley <[email protected]>
> wrote:
> >> * Config.accessList.outgoingTos, Config.accessList.clientsideTos,
> >> Config.accessList.outgoingNfmark, Config.accessList.clientsideNfmark
> can
> >> become members of the Qos scope Config object. All the parsing /free
> >> stuff
> >> can be moved there too with some #define parse_...() etc for the legacy
> >> parser.
> >>
> >
> > I've moved all the configuration variables and functions to the Qos
> > scope. I have renamed parse_acl_tos(acl_tos ** head) as
> > Ip::Qos::Config::parseConfigAclTos(acl_tos ** head).
> >
> > However, I'm unable to compile because of the following error:
> >
> > Qos.cc: In member function ‘void
> > Ip::Qos::Config::parseConfigAclTos(acl_tos**)’:
> > Qos.cc:377: error: argument of type ‘void (Ip::Qos::Config::)(void*)’
> does
> > not match ‘void (*)(void*)’
> >
> > The code at line 377 is:
> >
> > CBDATA_INIT_TYPE_FREECB(acl_tos, freedConfigAclTos);
> >
> > I have
> >
> > CBDATA_TYPE(acl_tos);
> >
> > specified before the parseConfigAclTos function.
> >
> > Could you give me any ideas as to what I am doing wrong here? If you
> > need me to send through any more of the code then please let me know.
>
> Do you have this with a cast?
> #define parse_acl_tos(X) Ip::Qos::Config::parseConfigAclTos((acl_tos
> **)X)
>
> with the cf.data.pre "TYPE: acl_tos" unchanged.
No, I had changed it. However, I have now changed it back to the above,
but still get the same error. Any other ideas?
Qos.cc: In member function ‘void Ip::Qos::Config::parseConfigAclTos(acl_tos**)’:
Qos.cc:377: error: argument of type ‘void (Ip::Qos::Config::)(void*)’ does not
match ‘void (*)(void*)’
I have attached my current Qos.cc and Qos.h
Thanks,
Andy
#include "acl/Gadgets.h"
#include "ConfigParser.h"
#include "fde.h"
#include "HierarchyLogEntry.h"
#include "ip/tools.h"
#include "Qos.h"
#include "Parsing.h"
#include "squid.h"
#include "Store.h"
extern void dump_acl_list(StoreEntry * entry, ACLList * head);
/* Qos namespace */
void
Ip::Qos::getTosFromServer(const int server_fd, fde *clientFde)
{
#if USE_QOS_TOS
tos_t tos = 1;
int tos_len = sizeof(tos);
clientFde->tosFromServer = 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 (o->cmsg_level == SOL_IP && o->cmsg_type == IP_TOS) {
int *tmp = (int*)CMSG_DATA(o);
clientFde->tosFromServer = (tos_t)*tmp;
break;
}
pbuf += CMSG_LEN(o->cmsg_len);
}
} else {
debugs(33, 1, "QOS: error in getsockopt(IP_PKTOPTIONS) on FD " << server_fd << " " << xstrerror());
}
} else {
debugs(33, 1, "QOS: error in setsockopt(IP_RECVTOS) on FD " << server_fd << " " << xstrerror());
}
#endif
}
void Ip::Qos::getNfmarkFromServer(const int server_fd, const fde *servFde, const fde *clientFde)
{
#if USE_QOS_NFMARK
/* Allocate a new conntrack */
if (struct nf_conntrack *ct = nfct_new()) {
/* Prepare data needed to find the connection in the conntrack table.
* We need the local and remote IP address, and the local and remote
* port numbers.
*/
Ip::Address serv_fde_local_conn;
struct addrinfo *addr = NULL;
serv_fde_local_conn.InitAddrInfo(addr);
getsockname(server_fd, addr->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
}
#if USE_QOS_NFMARK
int
Ip::Qos::getNfMarkCallback(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
{
fde *clientFde = (fde *)data;
clientFde->nfmarkFromServer = nfct_get_attr_u32(ct, ATTR_MARK);
debugs(17, 3, "QOS: Retrieved connection mark value: " << clientFde->nfmarkFromServer);
return NFCT_CB_CONTINUE;
}
#endif
int
Ip::Qos::doTosLocalMiss(const int fd, const HierarchyLogEntry *hier)
{
tos_t tos = 0;
if (Ip::Qos::TheConfig.tosSiblingHit && hier->code==SIBLING_HIT ) {
tos = Ip::Qos::TheConfig.tosSiblingHit;
debugs(33, 2, "QOS: Sibling Peer hit with hier code=" << hier->code << ", TOS=" << int(tos));
} else if (Ip::Qos::TheConfig.tosParentHit && hier->code==PARENT_HIT) {
tos = Ip::Qos::TheConfig.tosParentHit;
debugs(33, 2, "QOS: Parent Peer hit with hier code=" << hier->code << ", TOS=" << int(tos));
} else if (Ip::Qos::TheConfig.preserveMissTos && Ip::Qos::TheConfig.preserveMissTosMask) {
tos = fd_table[fd].tosFromServer & Ip::Qos::TheConfig.preserveMissTosMask;
debugs(33, 2, "QOS: Preserving TOS on miss, TOS=" << int(tos));
}
return setSockTos(fd, tos);
}
int
Ip::Qos::doNfmarkLocalMiss(const int fd, const HierarchyLogEntry *hier)
{
nfmark_t mark = 0;
if (Ip::Qos::TheConfig.markSiblingHit && hier->code==SIBLING_HIT ) {
mark = Ip::Qos::TheConfig.markSiblingHit;
debugs(33, 2, "QOS: Sibling Peer hit with hier code=" << hier->code << ", Mark=" << mark);
} else if (Ip::Qos::TheConfig.markParentHit && hier->code==PARENT_HIT) {
mark = Ip::Qos::TheConfig.markParentHit;
debugs(33, 2, "QOS: Parent Peer hit with hier code=" << hier->code << ", Mark=" << mark);
} else if (Ip::Qos::TheConfig.preserveMissMark) {
mark = fd_table[fd].nfmarkFromServer & Ip::Qos::TheConfig.preserveMissMarkMask;
debugs(33, 2, "QOS: Preserving mark on miss, Mark=" << mark);
}
return setSockNfmark(fd, mark);
}
int
Ip::Qos::doTosLocalHit(const int fd)
{
debugs(33, 2, "QOS: Setting TOS for local hit, TOS=" << int(Ip::Qos::TheConfig.tosLocalHit));
return setSockTos(fd, Ip::Qos::TheConfig.tosLocalHit);
}
int
Ip::Qos::doNfmarkLocalHit(const int fd)
{
debugs(33, 2, "QOS: Setting netfilter mark for local hit, mark=" << Ip::Qos::TheConfig.markLocalHit);
return setSockNfmark(fd, Ip::Qos::TheConfig.markLocalHit);
}
/* Qos::Config class */
Ip::Qos::Config Ip::Qos::TheConfig;
Ip::Qos::Config::Config()
{
tosLocalHit = 0;
tosSiblingHit = 0;
tosParentHit = 0;
preserveMissTos = false;
preserveMissTosMask = 0xFF;
markLocalHit = 0;
markSiblingHit = 0;
markParentHit = 0;
preserveMissMark = false;
preserveMissMarkMask = 0xFFFFFFFF;
}
void
Ip::Qos::Config::parseConfigLine()
{
/* 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 isHitTosActive().
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 && defined(_SQUID_LINUX_)
mark = true;
// Assume preserve is true. We don't set at initialisation as this affects isHitNfmarkActive()
preserveMissMark = 1;
#elif defined(_SQUID_LINUX_)
debugs(3, DBG_CRITICAL, "ERROR: Invalid parameter 'mark' in qos_flows option. "
<< "Netfilter marking only available for Linux environment");
self_destruct();
#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) {
preserveMissTos = true;
tos = true;
} else {
preserveMissTos = true;
tos = true;
}
}
if (strncmp(token, "local-hit=",10) == 0) {
if (mark) {
if (!xstrtoui(&token[10], NULL, &markLocalHit, 0, std::numeric_limits<nfmark_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad mark local-hit value " << &token[10]);
} else {
unsigned int v = 0;
if (!xstrtoui(&token[10], NULL, &v, 0, std::numeric_limits<tos_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad TOS local-hit value " << &token[10]);
tosLocalHit = (tos_t)v;
}
} else if (strncmp(token, "sibling-hit=",12) == 0) {
if (mark) {
if (!xstrtoui(&token[12], NULL, &markSiblingHit, 0, std::numeric_limits<nfmark_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad mark sibling-hit value " << &token[12]);
} else {
unsigned int v = 0;
if (!xstrtoui(&token[12], NULL, &v, 0, std::numeric_limits<tos_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad TOS sibling-hit value " << &token[12]);
tosSiblingHit = (tos_t)v;
}
} else if (strncmp(token, "parent-hit=",11) == 0) {
if (mark) {
if (!xstrtoui(&token[11], NULL, &markParentHit, 0, std::numeric_limits<nfmark_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad mark parent-hit value " << &token[11]);
} else {
unsigned int v = 0;
if (!xstrtoui(&token[11], NULL, &v, 0, std::numeric_limits<tos_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad TOS parent-hit value " << &token[11]);
tosParentHit = (tos_t)v;
}
} else if (strcmp(token, "disable-preserve-miss") == 0) {
if (preserveMissTosMask!=0xFFU || preserveMissMarkMask!=0xFFFFFFFFU) {
debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set with disable-preserve-miss");
}
if (mark) {
preserveMissMark = false;
preserveMissMarkMask = 0;
} else {
preserveMissTos = false;
preserveMissTosMask = 0;
}
} else if (strncmp(token, "miss-mask=",10) == 0) {
if (mark && preserveMissMark) {
if (!xstrtoui(&token[10], NULL, &preserveMissMarkMask, 0, std::numeric_limits<nfmark_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad mark miss-mark value " << &token[10]);
} else if (preserveMissTos) {
unsigned int v = 0;
if (!xstrtoui(&token[10], NULL, &v, 0, std::numeric_limits<tos_t>::max()))
debugs(3, DBG_CRITICAL, "ERROR: Bad TOS miss-mark value " << &token[10]);
preserveMissTosMask = (tos_t)v;
} else {
debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set with disable-preserve-miss");
}
}
}
}
void
Ip::Qos::Config::dumpConfigLine(char *entry, const char *name) const
{
char *p = entry;
if (isHitTosActive()) {
p += snprintf(p, 11, "%s", name); // strlen("qos_flows ");
p += snprintf(p, 4, "%s", "tos");
if (tosLocalHit > 0) {
p += snprintf(p, 16, " local-hit=0x%02X", tosLocalHit);
}
if (tosSiblingHit > 0) {
p += snprintf(p, 18, " sibling-hit=0x%02X", tosSiblingHit);
}
if (tosParentHit > 0) {
p += snprintf(p, 17, " parent-hit=0x%02X", tosParentHit);
}
if (preserveMissTos == 0) {
p += snprintf(p, 23, " disable-preserve-miss");
}
if (preserveMissTos && preserveMissTosMask != 0) {
p += snprintf(p, 16, " miss-mask=0x%02X", preserveMissTosMask);
}
p += snprintf(p, 2, "\n");
}
if (isHitNfmarkActive()) {
p += snprintf(p, 11, "%s", name); // strlen("qos_flows ");
p += snprintf(p, 5, "%s", "mark");
if (markLocalHit > 0) {
p += snprintf(p, 22, " local-hit=0x%02X", markLocalHit);
}
if (markSiblingHit > 0) {
p += snprintf(p, 24, " sibling-hit=0x%02X", markSiblingHit);
}
if (markParentHit > 0) {
p += snprintf(p, 23, " parent-hit=0x%02X", markParentHit);
}
if (preserveMissMark == 0) {
p += snprintf(p, 23, " disable-preserve-miss");
}
if (preserveMissMark && preserveMissMarkMask != 0) {
p += snprintf(p, 22, " miss-mask=0x%02X", preserveMissMarkMask);
}
p += snprintf(p, 2, "\n");
}
}
CBDATA_TYPE(acl_tos);
static ConfigParser LegacyParser = ConfigParser();
void
Ip::Qos::Config::parseConfigAclTos(acl_tos ** head)
{
acl_tos *l;
acl_tos **tail = head; /* sane name below */
unsigned int tos; /* Initially uint for strtoui. Casted to tos_t before return */
char *token = strtok(NULL, w_space);
if (!token) {
self_destruct();
return;
}
if (!xstrtoui(token, NULL, &tos, 0, std::numeric_limits<tos_t>::max())) {
self_destruct();
return;
}
CBDATA_INIT_TYPE_FREECB(acl_tos, freedConfigAclTos);
l = cbdataAlloc(acl_tos);
l->tos = (tos_t)tos;
aclParseAclList(LegacyParser, &l->aclList);
while (*tail)
tail = &(*tail)->next;
*tail = l;
}
void
Ip::Qos::Config::dumpConfigAclTos(StoreEntry * entry, const char *name, acl_tos * head)
{
acl_tos *l;
for (l = head; l; l = l->next) {
if (l->tos > 0)
storeAppendPrintf(entry, "%s 0x%02X", name, l->tos);
else
storeAppendPrintf(entry, "%s none", name);
dump_acl_list(entry, l->aclList);
storeAppendPrintf(entry, "\n");
}
}
void
Ip::Qos::Config::freedConfigAclTos(void *data)
{
acl_tos *l = static_cast<acl_tos *>(data);
aclDestroyAclList(&l->aclList);
}
void
Ip::Qos::Config::freeConfigAclTos(acl_tos ** head)
{
while (*head) {
acl_tos *l = *head;
*head = l->next;
l->next = NULL;
cbdataFree(l);
}
}
#if !_USE_INLINE_
#include "Qos.cci"
#endif
#ifndef SQUID_QOSCONFIG_H
#define SQUID_QOSCONFIG_H
#include "config.h"
#if HAVE_LIBNETFILTER_CONNTRACK_LIBNETFILTER_CONNTRACK_H
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#endif
#if HAVE_LIBNETFILTER_CONNTRACK_LIBNETFILTER_CONNTRACK_TCP_H
#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
#endif
#if HAVE_LIMITS
#include <limits>
#endif
// Forward-declarations
class fde;
class HierarchyLogEntry;
namespace Ip
{
/**
* QOS namespace contains all the QOS functionality: global functions within
* the namespace and the configuration parameters within a config class.
*/
namespace Qos
{
/**
* Function to retrieve the TOS value of the inbound packet.
* Called by FwdState::dispatch if QOS options are enabled.
* @param server_fd Server side descriptor of connection to get TOS for
* @param clientFde Pointer to client side fde instance to set tosFromServer in
*/
void getTosFromServer(const int server_fd, fde *clientFde);
/**
* Function to retrieve the netfilter mark value of the connection
* to the upstream server. Called by FwdState::dispatch if QOS
* options are enabled.
* @param server_fd Server side descriptor of connection to get mark for
* @param servFde Pointer to server side fde instance to get mark for
* @param clientFde Pointer to client side fde instance to set nfmarkFromServer in
*/
void getNfmarkFromServer(const int server_fd, const fde *servFde, const fde *clientFde);
#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::getNfmarkFromServer.
* nfct_callback_register is used to register this function.
* @param nf_conntrack_msg_type Type of conntrack message
* @param nf_conntrack Pointer to the conntrack structure
* @param clientFde Pointer to client side fde instance to set nfmarkFromServer in
*/
int getNfMarkCallback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *clientFde);
#endif
/**
* Function to work out and then apply to the socket 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.
* @param fd Descriptor of socket to set the TOS for
* @param HierarchyLogEntry Pointer to hier structure of request
*/
int doTosLocalMiss(const int fd, const HierarchyLogEntry *hier);
/**
* Function to work out and then apply to the socket the appropriate
* netfilter mark value to set on packets when items have not been
* retrieved from local cache. Called by clientReplyContext::sendMoreData
* if QOS is enabled for TOS.
* @param fd Descriptor of socket to set the mark for
* @param HierarchyLogEntry Pointer to hier structure of request
*/
int doNfmarkLocalMiss(const int fd, const HierarchyLogEntry *hier);
/**
* Function to work out and then apply to the socket the appropriate
* TOS value to set on packets when items *have* been retrieved from
* local cache. Called by clientReplyContext::doGetMoreData if QOS is
* enabled for TOS.
* @param fd Descriptor of socket to set the TOS for
*/
int doTosLocalHit(const int fd);
/**
* Function to work out and then apply to the socket the appropriate
* netfilter mark value to set on packets when items *have* been
* retrieved from local cache. Called by clientReplyContext::doGetMoreData
* if QOS is enabled for TOS.
* @param fd Descriptor of socket to set the mark for
*/
int doNfmarkLocalHit(const int fd);
/**
* Function to set the TOS value of packets. Sets the value on the socket
* which then gets copied to the packets.
* @param fd Descriptor of socket to set the TOS for
*/
_SQUID_INLINE_ int setSockTos(int fd, tos_t tos);
/**
* Function to set the netfilter mark value of packets. Sets the value on the
* socket which then gets copied to the packets. Called from Ip::Qos::doNfmarkLocalMiss
* @param fd Descriptor of socket to set the mark for
*/
_SQUID_INLINE_ int setSockNfmark(int fd, nfmark_t mark);
/**
* QOS configuration class. Contains all the parameters for QOS functions as well
* as functions to check whether either TOS or MARK QOS is enabled.
*/
class Config
{
public:
Config();
~Config() {};
void parseConfigLine();
/**
* Dump all the configuration values
*
* 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 references. Just a basic char* buffer.
*/
void dumpConfigLine(char *entry, const char *name) const;
void parseConfigAclTos(acl_tos ** head);
void dumpConfigAclTos(StoreEntry * entry, const char *name, acl_tos * head);
void freedConfigAclTos(void *data);
void freeConfigAclTos(acl_tos ** head);
/// Whether we should modify TOS flags based on cache hits and misses.
_SQUID_INLINE_ bool isHitTosActive() const;
/// Whether we should modify netfilter marks based on cache hits and misses.
_SQUID_INLINE_ bool isHitNfmarkActive() const;
/**
* Iterates through any outgoing_nfmark or clientside_nfmark configuration parameters
* to find out if any Netfilter marking is required.
* This function is used on initialisation to define capabilities required (Netfilter
* marking requires CAP_NET_ADMIN).
*/
_SQUID_INLINE_ bool isAclNfmarkActive();
/**
* Iterates through any outgoing_tos or clientside_tos configuration parameters
* to find out if packets should be marked with TOS flags.
*/
_SQUID_INLINE_ bool isAclTosActive();
tos_t tosLocalHit; ///< TOS value to apply to local cache hits
tos_t tosSiblingHit; ///< TOS value to apply to hits from siblings
tos_t tosParentHit; ///< TOS value to apply to hits from parent
bool preserveMissTos; ///< Whether to preserve the TOS value of the inbound packet for misses
tos_t preserveMissTosMask; ///< The mask to apply when preserving the TOS of misses
nfmark_t markLocalHit; ///< Netfilter mark value to apply to local cache hits
nfmark_t markSiblingHit; ///< Netfilter mark value to apply to hits from siblings
nfmark_t markParentHit; ///< Netfilter mark value to apply to hits from parent
bool preserveMissMark; ///< Whether to preserve netfilter mark value of inbound connection
nfmark_t preserveMissMarkMask; ///< The mask to apply when preserving the netfilter mark of misses
acl_tos *tosToServer; ///< The TOS that packets to the web server should be marked with, based on ACL
acl_tos *tosToClient; ///< The TOS that packets to the client should be marked with, based on ACL
acl_nfmark *nfmarkToServer; ///< The MARK that packets to the web server should be marked with, based on ACL
acl_nfmark *nfmarkToClient; ///< The MARK that packets to the client should be marked with, based on ACL
};
/// Globally available instance of Qos::Config
extern Config TheConfig;
/* legacy parser access wrappers */
#define parse_QosConfig(X) (X)->parseConfigLine()
#define free_QosConfig(X)
#define dump_QosConfig(e,n,X) do { \
char temp[256]; /* random number. change as needed. max config line length. */ \
(X).dumpConfigLine(temp,n); \
storeAppendPrintf(e, "%s", temp); \
} while(0);
#define parse_acl_tos(X) Ip::Qos::Config::parseConfigAclTos((acl_tos **)X)
#define dump_acl_tos(X) Ip::Qos::Config::dumpConfigAclTos((acl_tos **)X)
#define freed_acl_tos(X) Ip::Qos::Config::freedConfigAclTos((acl_tos **)X)
#define free_acl_tos(X) Ip::Qos::Config::freeConfigAclTos((acl_tos **)X)
}; // namespace Qos
}; // namespace Ip
#if _USE_INLINE_
#include "Qos.cci"
#endif
#endif /* SQUID_QOSCONFIG_H */