diff -urN a/src/cache_cf.c b/src/cache_cf.c --- a/src/cache_cf.c Thu Feb 6 06:01:07 2003 +++ b/src/cache_cf.c Thu Jul 31 18:17:11 2003 @@ -729,6 +729,66 @@ } } +CBDATA_TYPE(acl_priority); + +static void +dump_acl_priority(StoreEntry * entry, const char *name, acl_priority * head) +{ + acl_priority *l; + for (l = head; l; l = l->next) { + if (l->priority > 0) + storeAppendPrintf(entry, "%s %04X:%04X", name, + l->priority >> 16, l->priority & 0xFFFF); + else + storeAppendPrintf(entry, "%s none", name); + dump_acl_list(entry, l->acl_list); + storeAppendPrintf(entry, "\n"); + } +} + +static void +freed_acl_priority(void *data) +{ + acl_priority *l = data; + aclDestroyAclList(&l->acl_list); +} + +static void +parse_acl_priority(acl_priority ** head) +{ + acl_priority *l; + acl_priority **tail = head; /* sane name below */ + unsigned long priority, t1, t2; + char junk; + char *token = strtok(NULL, w_space); + if (!token) + self_destruct(); + if (sscanf(token, "%x:%x%c", &t1, &t2, &junk) != 2) + self_destruct(); + if (t1 < 0 || t1 > 0xFFFF || t2 < 0 || t2 > 0xFFFF) + self_destruct(); + priority = t1 << 16 | t2; + CBDATA_INIT_TYPE_FREECB(acl_priority, freed_acl_priority); + l = cbdataAlloc(acl_priority); + l->priority = priority; + aclParseAclList(&l->acl_list); + while (*tail) + tail = &(*tail)->next; + *tail = l; +} + +static void +free_acl_priority(acl_priority ** head) +{ + while (*head) { + acl_priority *l = *head; + *head = l->next; + l->next = NULL; + cbdataFree(l); + } +} + + #if DELAY_POOLS /* do nothing - free_delay_pool_count is the magic free function. diff -urN a/src/cf.data.pre b/src/cf.data.pre --- a/src/cf.data.pre Wed May 21 16:34:38 2003 +++ b/src/cf.data.pre Thu Jul 31 18:17:11 2003 @@ -2232,6 +2232,27 @@ matching line. DOC_END +NAME: tcp_outgoing_priority +TYPE: acl_priority +DEFAULT: none +LOC: Config.accessList.outgoing_priority +DOC_START + Allows you to select the priority of the outgoing connection, + based on the username or source address making the request. The + priority can be used by Linux QoS Qdiscs for classification. + + tcp_outgoing_priority priority [!]aclname ... + + Example where requests from special_service_net are assigned + priority 10:100 + + acl special_service_net src 10.0.0.0/255.255.255.0 + tcp_outgoing_priority 10:100 special_service_net + + Processing proceeds in the order specified, and stops at first fully + matching line. +DOC_END + NAME: tcp_outgoing_address TYPE: acl_address DEFAULT: none diff -urN a/src/comm.c b/src/comm.c --- a/src/comm.c Mon Apr 1 08:03:38 2002 +++ b/src/comm.c Thu Jul 31 18:18:38 2003 @@ -157,7 +157,7 @@ int flags, const char *note) { - return comm_openex(sock_type, proto, addr, port, flags, 0, note); + return comm_openex(sock_type, proto, addr, port, flags, 0, 0, note); } @@ -170,10 +170,12 @@ u_short port, int flags, unsigned char TOS, + unsigned long PRIORITY, const char *note) { int new_socket; int tos = 0; + unsigned long priority = 0; fde *F = NULL; /* Create socket for accepting new connections. */ @@ -204,12 +206,25 @@ debug(50, 0) ("comm_open: setsockopt(IP_TOS) not supported on this platform\n"); #endif } + if (PRIORITY) { +#ifdef SO_PRIORITY + priority = PRIORITY; + enter_suid(); + if (setsockopt(new_socket, SOL_SOCKET, SO_PRIORITY, (char *) &priority, sizeof(unsigned long)) < 0) + debug(50, 1) ("comm_open: setsockopt(SO_PRIORITY) on FD %d: %s\n", + new_socket, xstrerror()); + leave_suid(); +#else + debug(50, 0) ("comm_open: setsockopt(SO_PRIORITY) not supported on this platform\n"); +#endif + } /* update fdstat */ debug(5, 5) ("comm_open: FD %d is a new socket\n", new_socket); fd_open(new_socket, FD_SOCKET, note); F = &fd_table[new_socket]; F->local_addr = addr; F->tos = tos; + F->priority = priority; if (!(flags & COMM_NOCLOEXEC)) commSetCloseOnExec(new_socket); if ((flags & COMM_REUSEADDR)) @@ -367,6 +382,15 @@ int tos = F->tos; if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) debug(50, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n", cs->fd, xstrerror()); + } +#endif +#ifdef SO_PRIORITY + if (F->priority) { + unsigned long priority = F->priority; + enter_suid(); + if (setsockopt(cs->fd, SOL_SOCKET, SO_PRIORITY, (char *)&priority, sizeof(unsigned long)) < 0) + debug(50, 1) ("commResetFD: setsockopt(SO_PRIORITY) on FD %d: %s\n", cs->fd, xstrerror()); + leave_suid(); } #endif if (F->flags.close_on_exec) diff -urN a/src/forward.c b/src/forward.c --- a/src/forward.c Mon Mar 17 19:34:19 2003 +++ b/src/forward.c Thu Jul 31 18:17:11 2003 @@ -323,6 +323,17 @@ return 0; } +static unsigned long +aclMapPriority(acl_priority * head, aclCheck_t * ch) +{ + acl_priority *l; + for (l = head; l; l = l->next) { + if (aclMatchAclList(l->acl_list, ch)) + return l->priority; + } + return 0; +} + struct in_addr getOutgoingAddr(request_t * request) { @@ -351,6 +362,20 @@ return aclMapTOS(Config.accessList.outgoing_tos, &ch); } +unsigned long +getOutgoingPriority(request_t * request) +{ + aclCheck_t ch; + memset(&ch, '\0', sizeof(aclCheck_t)); + if (request) { + ch.src_addr = request->client_addr; + ch.my_addr = request->my_addr; + ch.my_port = request->my_port; + ch.request = request; + } + return aclMapPriority(Config.accessList.outgoing_priority, &ch); +} + static void fwdConnectStart(void *data) { @@ -364,6 +389,7 @@ time_t ctimeout; struct in_addr outgoing; unsigned short tos; + unsigned long priority; assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); @@ -397,15 +423,17 @@ #endif outgoing = getOutgoingAddr(fwdState->request); tos = getOutgoingTOS(fwdState->request); + priority = getOutgoingPriority(fwdState->request); - debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n", - inet_ntoa(outgoing), tos); + debug(17, 3) ("fwdConnectStart: got addr %s, tos %d, priority %lu\n", + inet_ntoa(outgoing), tos, priority); fd = comm_openex(SOCK_STREAM, 0, outgoing, 0, COMM_NONBLOCKING, tos, + priority, url); if (fd < 0) { debug(50, 4) ("fwdConnectStart: %s\n", xstrerror()); diff -urN a/src/protos.h b/src/protos.h --- a/src/protos.h Tue May 6 22:13:02 2003 +++ b/src/protos.h Thu Jul 31 18:17:11 2003 @@ -158,7 +158,7 @@ extern void comm_init(void); extern int comm_listen(int sock); extern int comm_open(int, int, struct in_addr, u_short port, int, const char *note); -extern int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, const char *); +extern int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, unsigned long PRIORITY, const char *); extern u_short comm_local_port(int fd); extern void commSetSelect(int, unsigned int, PF *, void *, time_t); @@ -729,6 +729,7 @@ #endif struct in_addr getOutgoingAddr(request_t * request); unsigned long getOutgoingTOS(request_t * request); +unsigned long getOutgoingPriority(request_t * request); extern void urnStart(request_t *, StoreEntry *); diff -urN a/src/ssl.c b/src/ssl.c --- a/src/ssl.c Sun Feb 9 22:42:03 2003 +++ b/src/ssl.c Thu Jul 31 18:17:11 2003 @@ -480,6 +480,7 @@ 0, COMM_NONBLOCKING, getOutgoingTOS(request), + getOutgoingPriority(request), url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); diff -urN a/src/structs.h b/src/structs.h --- a/src/structs.h Sun May 11 00:17:44 2003 +++ b/src/structs.h Thu Jul 31 18:17:11 2003 @@ -277,6 +277,12 @@ int tos; }; +struct _acl_priority { + acl_priority *next; + acl_list *acl_list; + unsigned long priority; +}; + struct _aclCheck_t { const acl_access *access_list; struct in_addr src_addr; @@ -613,6 +619,7 @@ acl_access *reply; acl_address *outgoing_address; acl_tos *outgoing_tos; + acl_priority *outgoing_priority; } accessList; acl_deny_info_list *denyInfoList; struct _authConfig { @@ -759,6 +766,7 @@ u_short remote_port; struct in_addr local_addr; unsigned char tos; + unsigned long priority; char ipaddr[16]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; struct { diff -urN a/src/typedefs.h b/src/typedefs.h --- a/src/typedefs.h Sun May 11 19:30:13 2003 +++ b/src/typedefs.h Thu Jul 31 18:17:11 2003 @@ -77,6 +77,7 @@ typedef struct _acl_access acl_access; typedef struct _acl_address acl_address; typedef struct _acl_tos acl_tos; +typedef struct _acl_priority acl_priority; typedef struct _aclCheck_t aclCheck_t; typedef struct _wordlist wordlist; typedef struct _intlist intlist;