[PATCH]: support for setting socket priority based on src/user

From: Patrick McHardy <kaber@dont-contact.us>
Date: Thu, 31 Jul 2003 18:30:05 +0200

Please CC any replies, i'm not subscribed to the list.

This patch adds support for setting the socket priority based on requesting
src/user. This is useful for Linux QoS, classful qdiscs can use this
value for
classification. The patch is for 2.5-STABLE3 and i guess you have no
interest
in including it in a stable version, but i assume more people will find this
useful so you can at least point people to the patch. If there is
interest, i
could also port it to latest development version.

The patch is also available at http://trash.net/~kaber/squid-qos/

Best regards,
Patrick

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;
Received on Thu Jul 31 2003 - 11:24:19 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:20:18 MST