Hello,

In attachment is our patch to the nginx core. You can take a look.

We found that your module isn't IPv6 compatible too, but it may be
simple to implement that.

Thanks.

On Tue, 16 Dec 2014 18:48:28 +0000
Maxim Dounin <mdou...@mdounin.ru> wrote:

> Hello!
> 
> On Tue, Dec 16, 2014 at 05:24:42PM +0000, Dani Bento wrote:
> 
> > Thanks for the reply.
> > 
> > We looked at your module and found it interesting that you
> > avoided to change the core.
> > 
> > Our code marks each buffer flush individually. We can control the
> > ToS for each request even when using keep-alive (using the
> > X-Accel-ClassID header). After the response has been sent the ToS
> > is reset back to the default (location configuration).
> > 
> > In your module you mark only at the beginning of the response (at
> > the header filter stage). Don't you have problems with different
> > requests using the same connection?
> 
> If you want ToS to be reset, you can use "ip_tos 0x00;" by 
> default, see example here:
> 
> http://mdounin.ru/hg/ngx_http_ip_tos_filter_module/file/tip/README
> 
> > You can only have one ToS mark for
> > each location if you relying on a static configuration. Can it be
> > set by variable "tos $class_id" ?
> 
> Not now, but this can be added if needed - like it was recently 
> added to the "expires" directive, see 
> http://hg.nginx.org/nginx/rev/4983f7d18fe3.
> 



-- 
Dani Bento
Direção de Internet e Tecnologia
DTS/DVS
tlm: +351 91 429 72 81
d...@telecom.pt
diff -rpuN nginx-1.6.2/src/core/ngx_connection.c nginx-1.6.2-traffic-xaccel-classid/src/core/ngx_connection.c
--- nginx-1.6.2/src/core/ngx_connection.c	2014-11-24 11:55:39.469073051 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/core/ngx_connection.c	2014-11-28 15:42:05.852784804 +0000
@@ -872,6 +872,7 @@ ngx_get_connection(ngx_socket_t s, ngx_l
     c->write = wev;
     c->fd = s;
     c->log = log;
+    c->traffic_class = NGX_TRAFFIC_CLASS_UNSET;

     instance = rev->instance;

@@ -1208,3 +1209,78 @@ ngx_connection_error(ngx_connection_t *c

     return NGX_ERROR;
 }
+
+
+#if (NGX_LINUX)
+
+ngx_int_t
+ngx_connection_traffic_class(ngx_connection_t *c)
+{
+	unsigned int   traffic_class;
+	unsigned int   sa_family = 0;
+	int            tos_return;
+	u_char         sock_addr[NGX_SOCKADDR_STRLEN];
+	unsigned int   len;
+
+	/* we shall continue the process even if the setsockopt fails */
+	traffic_class = c->traffic_class != NGX_TRAFFIC_CLASS_UNSET ? c->traffic_class : 0;
+
+	if (c->sockaddr == NULL) {
+		ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, ngx_socket_errno, "no socket family for traffic_class (fd: %d)",
+                       c->fd);
+		return NGX_DECLINED;
+	} else {
+	    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "socket family for traffic_class: %d (fd: %d)",
+	               sa_family, c->fd);
+		sa_family = c->sockaddr->sa_family;
+	}
+
+	ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "setting traffic_class: %d (fd: %d, conn traffic_class: %d)",
+				   traffic_class, c->fd, c->traffic_class);
+
+	len = ngx_sock_ntop(c->sockaddr, c->socklen, sock_addr, NGX_SOCKADDR_STRLEN, 1);
+
+	switch (sa_family) {
+		case AF_INET:
+			ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "set traffic_class for ipv4 (fd: %d, addr: %s)",
+			               c->fd, &sock_addr);
+			tos_return = ngx_traffic_class(c->fd, traffic_class);
+			break;
+		case AF_INET6:
+			ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "set traffic_class for ipv6 (fd: %d, addr: %s)",
+			               c->fd, &sock_addr);
+			tos_return = ngx_traffic_class6(c->fd, traffic_class);
+			break;
+		default:
+			ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "set traffic_class declined (fd: %d, sa_family: %d, addr: %s)",
+			               c->fd, sa_family, &sock_addr);
+			return NGX_DECLINED;
+	}
+
+	switch (tos_return) {
+		case NGX_ERROR:
+			ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno, "unable to set traffic class (fd: %d)",
+						  c->fd);
+			break;
+		case NGX_OK:
+			ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "setted traffic_class: %d (fd: %d)",
+			               traffic_class, c->fd);
+			break;
+		default:
+			ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno, "traffic_class returns an unknown error: %d (fd: %d)",
+			              tos_return, c->fd);
+			return NGX_ERROR;
+	}
+
+	return tos_return;
+}
+
+#else
+
+ngx_int_t
+ngx_connection_traffic_class(ngx_connection_t *c)
+{
+	return NGX_OK;
+}
+
+#endif
diff -rpuN nginx-1.6.2/src/core/ngx_connection.h nginx-1.6.2-traffic-xaccel-classid/src/core/ngx_connection.h
--- nginx-1.6.2/src/core/ngx_connection.h	2014-11-24 11:55:39.473073051 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/core/ngx_connection.h	2014-11-27 17:11:44.181960853 +0000
@@ -109,6 +109,7 @@ typedef enum {
      NGX_TCP_NOPUSH_DISABLED
 } ngx_connection_tcp_nopush_e;

+#define NGX_TRAFFIC_CLASS_UNSET -1

 #define NGX_LOWLEVEL_BUFFERED  0x0f
 #define NGX_SSL_BUFFERED       0x01
@@ -189,6 +190,8 @@ struct ngx_connection_s {
 #if (NGX_THREADS)
     ngx_atomic_t        lock;
 #endif
+
+    int        traffic_class;  /* TOS class represented by an int value */
 };


@@ -208,4 +211,6 @@ void ngx_free_connection(ngx_connection_

 void ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable);

+ngx_int_t ngx_connection_traffic_class(ngx_connection_t *c);
+
 #endif /* _NGX_CONNECTION_H_INCLUDED_ */
diff -rpuN nginx-1.6.2/src/event/ngx_event_accept.c nginx-1.6.2-traffic-xaccel-classid/src/event/ngx_event_accept.c
--- nginx-1.6.2/src/event/ngx_event_accept.c	2014-11-24 11:55:39.493073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/event/ngx_event_accept.c	2014-11-26 15:02:57.035327131 +0000
@@ -216,6 +216,9 @@ ngx_event_accept(ngx_event_t *ev)

         c->unexpected_eof = 1;

+        /* default TOS class */
+        c->traffic_class = NGX_TRAFFIC_CLASS_UNSET;
+
 #if (NGX_HAVE_UNIX_DOMAIN)
         if (c->sockaddr->sa_family == AF_UNIX) {
             c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
diff -rpuN nginx-1.6.2/src/event/ngx_event_connect.c nginx-1.6.2-traffic-xaccel-classid/src/event/ngx_event_connect.c
--- nginx-1.6.2/src/event/ngx_event_connect.c	2014-11-24 11:55:39.493073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/event/ngx_event_connect.c	2014-11-26 15:03:24.399326734 +0000
@@ -84,6 +84,9 @@ ngx_event_connect_peer(ngx_peer_connecti

     c->log_error = pc->log_error;

+    /* default TOS Class */
+    c->traffic_class = NGX_TRAFFIC_CLASS_UNSET;
+
     if (pc->sockaddr->sa_family == AF_UNIX) {
         c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
         c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
diff -rpuN nginx-1.6.2/src/http/modules/ngx_http_proxy_module.c nginx-1.6.2-traffic-xaccel-classid/src/http/modules/ngx_http_proxy_module.c
--- nginx-1.6.2/src/http/modules/ngx_http_proxy_module.c	2014-11-24 11:55:39.589073054 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/modules/ngx_http_proxy_module.c	2014-11-24 11:56:02.509073699 +0000
@@ -615,6 +615,7 @@ static ngx_str_t  ngx_http_proxy_hide_he
     ngx_string("X-Accel-Limit-Rate"),
     ngx_string("X-Accel-Buffering"),
     ngx_string("X-Accel-Charset"),
+    ngx_string("X-Accel-ClassID"),
     ngx_null_string
 };

diff -rpuN nginx-1.6.2/src/http/modules/ngx_http_uwsgi_module.c nginx-1.6.2-traffic-xaccel-classid/src/http/modules/ngx_http_uwsgi_module.c
--- nginx-1.6.2/src/http/modules/ngx_http_uwsgi_module.c	2014-11-24 11:55:39.573073054 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/modules/ngx_http_uwsgi_module.c	2014-12-02 11:31:47.668993065 +0000
@@ -452,6 +452,7 @@ static ngx_str_t ngx_http_uwsgi_hide_hea
     ngx_string("X-Accel-Limit-Rate"),
     ngx_string("X-Accel-Buffering"),
     ngx_string("X-Accel-Charset"),
+    ngx_string("X-Accel-ClassID"),
     ngx_null_string
 };

diff -rpuN nginx-1.6.2/src/http/ngx_http_core_module.c nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_core_module.c
--- nginx-1.6.2/src/http/ngx_http_core_module.c	2014-11-24 11:55:39.553073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_core_module.c	2014-11-26 15:56:09.367280793 +0000
@@ -87,6 +87,8 @@ static char *ngx_http_disable_symlinks(n
 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
 static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);

+static char *ngx_http_traffic_class(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+
 static ngx_conf_post_t  ngx_http_core_lowat_post =
     { ngx_http_core_lowat_check };

@@ -788,6 +790,12 @@ static ngx_command_t  ngx_http_core_comm
       NULL },

 #endif
+    { ngx_string("traffic_class"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_traffic_class,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, traffic_class),
+      NULL },

       ngx_null_command
 };
@@ -3659,6 +3667,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
     clcf->disable_symlinks_from = NGX_CONF_UNSET_PTR;
 #endif
+    clcf->traffic_class = NGX_CONF_UNSET;

     return clcf;
 }
@@ -3944,6 +3953,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t
     ngx_conf_merge_ptr_value(conf->disable_symlinks_from,
                              prev->disable_symlinks_from, NULL);
 #endif
+    ngx_conf_merge_uint_value(conf->traffic_class, prev->traffic_class, -1);

     return NGX_CONF_OK;
 }
@@ -5248,3 +5258,27 @@ ngx_http_core_pool_size(ngx_conf_t *cf,

     return NGX_CONF_OK;
 }
+
+static char *
+ngx_http_traffic_class(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_core_loc_conf_t *clcf = conf;
+
+    ngx_str_t  *value;
+    ngx_int_t  traffic_class;
+
+    value = cf->args->elts;
+
+    traffic_class = ngx_atoi(value[1].data, value[1].len);
+
+    if (traffic_class == NGX_ERROR || traffic_class > 63) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "traffic_class must be a non-negative integer under 64");
+        return NGX_CONF_ERROR;
+    }
+
+    clcf->traffic_class = (ngx_uint_t) traffic_class;
+
+    return NGX_CONF_OK;
+}
+
diff -rpuN nginx-1.6.2/src/http/ngx_http_core_module.h nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_core_module.h
--- nginx-1.6.2/src/http/ngx_http_core_module.h	2014-11-24 11:55:39.529073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_core_module.h	2014-11-24 11:56:02.509073699 +0000
@@ -450,6 +450,7 @@ struct ngx_http_core_loc_conf_s {
 #if 0
     ngx_http_core_loc_conf_t  *prev_location;
 #endif
+    ngx_uint_t  traffic_class;
 };


diff -rpuN nginx-1.6.2/src/http/ngx_http_request.c nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_request.c
--- nginx-1.6.2/src/http/ngx_http_request.c	2014-11-24 11:55:39.529073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_request.c	2014-11-28 15:24:25.448800196 +0000
@@ -308,6 +308,9 @@ ngx_http_init_connection(ngx_connection_

     c->log_error = NGX_ERROR_INFO;

+	/* initialize connection traffic_class with UNSET */
+	c->traffic_class = NGX_TRAFFIC_CLASS_UNSET;
+
     rev = c->read;
     rev->handler = ngx_http_wait_request_handler;
     c->write->handler = ngx_http_empty_handler;
@@ -596,6 +599,14 @@ ngx_http_create_request(ngx_connection_t

     r->http_state = NGX_HTTP_READING_REQUEST_STATE;

+	/* by default we initialize request traffic class
+       with the same value as location traffic class */
+    r->traffic_class = clcf->traffic_class;
+
+	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "create_request() set traffic_class: %d (fd: %d)",
+				   clcf->traffic_class, c->fd);
+
     ctx = c->log->data;
     ctx->request = r;
     ctx->current_request = r;
@@ -2513,6 +2524,15 @@ ngx_http_finalize_connection(ngx_http_re

     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                  "traffic_class (reset value): %d to %d (fd: %d)",
+				  r->traffic_class,
+				  clcf->traffic_class,
+				  r->connection->fd);
+
+    r->traffic_class = clcf->traffic_class;
+    r->connection->traffic_class = r->traffic_class;
+
     if (r->main->count != 1) {

         if (r->discard_body) {
@@ -2578,6 +2598,12 @@ ngx_http_set_write_handler(ngx_http_requ
     }

     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if ((unsigned int) clcf->traffic_class >= 0) {
+        r->traffic_class = clcf->traffic_class;
+        r->connection->traffic_class = clcf->traffic_class;
+    }
+
     if (!wev->delayed) {
         ngx_add_timer(wev, clcf->send_timeout);
     }
diff -rpuN nginx-1.6.2/src/http/ngx_http_request.h nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_request.h
--- nginx-1.6.2/src/http/ngx_http_request.h	2014-11-24 11:55:39.549073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_request.h	2014-12-02 12:07:36.604957661 +0000
@@ -237,6 +237,8 @@ typedef struct {
     unsigned                          chrome:1;
     unsigned                          safari:1;
     unsigned                          konqueror:1;
+
+	ngx_table_elt_t                   *x_accel_classid;
 } ngx_http_headers_in_t;


@@ -272,6 +274,8 @@ typedef struct {
     off_t                             content_length_n;
     time_t                            date_time;
     time_t                            last_modified_time;
+
+	ngx_table_elt_t                   *x_accel_classid;
 } ngx_http_headers_out_t;


@@ -569,6 +573,7 @@ struct ngx_http_request_s {

     unsigned                          http_minor:16;
     unsigned                          http_major:16;
+    unsigned int                      traffic_class;
 };


diff -rpuN nginx-1.6.2/src/http/ngx_http_upstream.c nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_upstream.c
--- nginx-1.6.2/src/http/ngx_http_upstream.c	2014-11-24 11:55:39.537073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_upstream.c	2014-12-02 14:37:20.896809644 +0000
@@ -106,6 +106,8 @@ static ngx_int_t ngx_http_upstream_proce
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_classid(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t
     ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
@@ -270,6 +272,10 @@ ngx_http_upstream_header_t  ngx_http_ups
                  ngx_http_upstream_process_charset, 0,
                  ngx_http_upstream_copy_header_line, 0, 0 },

+    { ngx_string("X-Accel-ClassID"),
+                 ngx_http_upstream_process_classid,
+                 ngx_http_upstream_copy_header_line, 0, 0 },
+
     { ngx_string("Transfer-Encoding"),
                  ngx_http_upstream_process_transfer_encoding, 0,
                  ngx_http_upstream_ignore_header_line, 0, 0 },
@@ -395,6 +401,7 @@ ngx_conf_bitmask_t  ngx_http_upstream_ig
     { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
     { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
     { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
+    { ngx_string("X-Accel-ClassID"), NGX_HTTP_UPSTREAM_IGN_XA_CLASSID },
     { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
     { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
     { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
@@ -2102,11 +2109,18 @@ ngx_http_upstream_process_headers(ngx_ht
         r->headers_out.date->hash = 0;
     }

+	if (r->headers_out.x_accel_classid && r->headers_out.x_accel_classid->value.data == NULL)
+	{
+		r->headers_out.x_accel_classid->hash = 0;
+	}
+
     r->headers_out.status = u->headers_in.status_n;
     r->headers_out.status_line = u->headers_in.status_line;

     r->headers_out.content_length_n = u->headers_in.content_length_n;

+	r->headers_out.x_accel_classid = u->headers_in.x_accel_classid;
+
     u->length = -1;

     return NGX_OK;
@@ -2199,6 +2213,7 @@ ngx_http_upstream_send_response(ngx_http
     ngx_event_pipe_t          *p;
     ngx_connection_t          *c;
     ngx_http_core_loc_conf_t  *clcf;
+	ngx_table_elt_t           *x_accel_classid;

     rc = ngx_http_send_header(r);

@@ -2242,6 +2257,24 @@ ngx_http_upstream_send_response(ngx_http

     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

+    /* set traffic_class if it exists */
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "http_upstream_send_response() setting traffic_class (fd: %d)", c->fd);
+    if (r->headers_in.x_accel_classid != NULL) {
+      	x_accel_classid = r->headers_in.x_accel_classid;
+	    r->traffic_class = ngx_atoi(x_accel_classid->value.data, x_accel_classid->value.len);
+        c->traffic_class = r->traffic_class;
+		r->connection->traffic_class = r->traffic_class;
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "http_upstream_send_response() set req traffic_class %d (fd: %d)",
+			               r->traffic_class, c->fd);
+    } else if (clcf->traffic_class != NGX_TRAFFIC_CLASS_UNSET) {
+        c->traffic_class = clcf->traffic_class;
+		r->traffic_class = clcf->traffic_class;
+		ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "http_upstream_send_response() set traffic_class %d (fd: %d)",
+                       c->traffic_class, c->fd);
+	}
+
+    ngx_connection_traffic_class(c);
+
     if (!u->buffering) {

         if (u->input_filter == NULL) {
@@ -2840,6 +2873,9 @@ ngx_http_upstream_process_non_buffered_r

     do_write = do_write || u->length == 0;

+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, downstream->log, 0,
+                   "http upstream process non buffered request");
+
     for ( ;; ) {

         if (do_write) {
@@ -3862,6 +3898,45 @@ ngx_http_upstream_process_buffering(ngx_

     return NGX_OK;
 }
+
+
+static ngx_int_t
+ngx_http_upstream_process_classid(ngx_http_request_t *r, ngx_table_elt_t *h,
+    ngx_uint_t offset)
+{
+    ngx_int_t   n;
+    ngx_http_upstream_t *u;
+
+    u = r->upstream;
+    u->headers_in.x_accel_classid = h;
+
+
+    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CLASSID) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "ignore http header X-Accel-ClassID");
+        return NGX_OK;
+    }
+
+    n = ngx_atoi(h->value.data, h->value.len);
+
+    if (n == NGX_ERROR || n > 63) {
+		r->traffic_class = NGX_TRAFFIC_CLASS_UNSET;
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "using location traffic_class: %d (fd: %d)",
+					   r->traffic_class, r->connection->fd);
+        return NGX_OK;
+    }
+
+    r->traffic_class = (unsigned int) n;
+    r->connection->traffic_class = r->traffic_class;
+	r->headers_in.x_accel_classid = h;
+	r->headers_out.x_accel_classid = h;
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "using http header traffic_class: %d (fd: %d)",
+				   n, r->connection->fd);
+
+    return NGX_OK;
+}


 static ngx_int_t
diff -rpuN nginx-1.6.2/src/http/ngx_http_upstream.h nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_upstream.h
--- nginx-1.6.2/src/http/ngx_http_upstream.h	2014-11-24 11:55:39.513073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_upstream.h	2014-11-24 11:56:02.513073699 +0000
@@ -50,6 +50,7 @@
 #define NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE  0x00000040
 #define NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING   0x00000080
 #define NGX_HTTP_UPSTREAM_IGN_XA_CHARSET     0x00000100
+#define NGX_HTTP_UPSTREAM_IGN_XA_CLASSID     0x00000200


 typedef struct {
@@ -227,6 +228,7 @@ typedef struct {
     ngx_table_elt_t                 *x_accel_expires;
     ngx_table_elt_t                 *x_accel_redirect;
     ngx_table_elt_t                 *x_accel_limit_rate;
+    ngx_table_elt_t                 *x_accel_classid;

     ngx_table_elt_t                 *content_type;
     ngx_table_elt_t                 *content_length;
diff -rpuN nginx-1.6.2/src/http/ngx_http_variables.c nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_variables.c
--- nginx-1.6.2/src/http/ngx_http_variables.c	2014-11-24 11:55:39.525073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_variables.c	2014-11-24 11:56:02.513073699 +0000
@@ -130,6 +130,9 @@ static ngx_int_t ngx_http_variable_time_
 static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);

+static ngx_int_t ngx_http_variable_traffic_class(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+
 /*
  * TODO:
  *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
@@ -340,6 +343,8 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
 #endif
+    { ngx_string("traffic_class"), NULL, ngx_http_variable_traffic_class,
+      offsetof(ngx_http_request_t, traffic_class), 0, 0},

     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
@@ -1048,6 +1053,25 @@ ngx_http_variable_tcpinfo(ngx_http_reque

 #endif

+static ngx_int_t
+ngx_http_variable_traffic_class(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+    uintptr_t data)
+{
+    u_char  *p;
+
+    p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
+    if (p == NULL) {
+        return NGX_ERROR;
+    }
+
+    v->len = ngx_sprintf(p, "%P", r->traffic_class) - p;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->data = p;
+
+    return NGX_OK;
+}

 static ngx_int_t
 ngx_http_variable_content_length(ngx_http_request_t *r,
diff -rpuN nginx-1.6.2/src/http/ngx_http_write_filter_module.c nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_write_filter_module.c
--- nginx-1.6.2/src/http/ngx_http_write_filter_module.c	2014-11-24 11:55:39.533073053 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/http/ngx_http_write_filter_module.c	2014-11-28 15:24:13.440800371 +0000
@@ -170,6 +170,24 @@ ngx_http_write_filter(ngx_http_request_t
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

     /*
+     * set TOS class based on request header or location configuration
+     *
+     */
+
+    if (r->traffic_class >= 0 && r->traffic_class <= 63) {
+        c->traffic_class = r->traffic_class;
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "set traffic_class based on http header: %d (fd: %d)",
+					   r->traffic_class, c->fd);
+    } else {
+        r->traffic_class = (unsigned int) clcf->traffic_class;
+        c->traffic_class = r->traffic_class;
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "set traffic_class based on location configuration: %d (fd: %d)",
+                       clcf->traffic_class, c->fd);
+    }
+
+    /*
      * avoid the output if there are no last buf, no flush point,
      * there are the incoming bufs and the size of all bufs
      * is smaller than "postpone_output" directive
diff -rpuN nginx-1.6.2/src/os/unix/ngx_linux_sendfile_chain.c nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_linux_sendfile_chain.c
--- nginx-1.6.2/src/os/unix/ngx_linux_sendfile_chain.c	2014-11-24 11:55:39.501073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_linux_sendfile_chain.c	2014-11-28 14:31:31.524846267 +0000
@@ -54,7 +54,7 @@ ngx_linux_sendfile_chain(ngx_connection_
     int32_t        offset;
 #endif

-    wev = c->write;
+	wev = c->write;

     if (!wev->ready) {
         return in;
@@ -87,6 +87,12 @@ ngx_linux_sendfile_chain(ngx_connection_
         prev = NULL;
         iov = NULL;

+		/* set connection traffic class */
+		ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "linux_sendfile_chain() setting traffic_class: %d (fd: %d)",
+                       c->traffic_class, c->fd);
+
+		ngx_connection_traffic_class(c);
+
         /* create the iovec and coalesce the neighbouring bufs */

         for (cl = in; cl && send < limit; cl = cl->next) {
diff -rpuN nginx-1.6.2/src/os/unix/ngx_send.c nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_send.c
--- nginx-1.6.2/src/os/unix/ngx_send.c	2014-11-24 11:55:39.509073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_send.c	2014-11-28 14:32:02.940845811 +0000
@@ -17,6 +17,8 @@ ngx_unix_send(ngx_connection_t *c, u_cha
     ngx_err_t     err;
     ngx_event_t  *wev;

+	unsigned int  traffic_class;
+
     wev = c->write;

 #if (NGX_HAVE_KQUEUE)
@@ -31,6 +33,13 @@ ngx_unix_send(ngx_connection_t *c, u_cha
 #endif

     for ( ;; ) {
+
+        /* set connection traffic class */
+		ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "linux_sendfile_chain() setting traffic_class: %d (fd: %d)",
+                       c->traffic_class, c->fd);
+
+		ngx_connection_traffic_class(c);
+
         n = send(c->fd, buf, size, 0);

         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
diff -rpuN nginx-1.6.2/src/os/unix/ngx_socket.c nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_socket.c
--- nginx-1.6.2/src/os/unix/ngx_socket.c	2014-11-24 11:55:39.505073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_socket.c	2014-11-27 16:24:15.658002200 +0000
@@ -114,3 +114,30 @@ ngx_tcp_push(ngx_socket_t s)
 }

 #endif
+
+#if (NGX_LINUX)
+
+int
+ngx_set_traffic_class(ngx_socket_t s, unsigned int traffic_class, unsigned int sa_family, unsigned int sockopt)
+{
+	unsigned int tos;
+	int          tos_return;
+
+	/* DSCP uses the six leftmost bits of the TOS field (the other two are reserved) */
+	tos = traffic_class << 2;
+
+	tos_return = setsockopt(s, sa_family, sockopt,
+						    (const void *) &tos, sizeof(tos));
+
+	return tos_return;
+}
+
+#else
+
+int
+ngx_set_traffic_class(ngx_socket_t s, unsigned int traffic_class, unsigned int sa_family, unsigned int sockopt)
+{
+	return 0;
+}
+
+#endif
diff -rpuN nginx-1.6.2/src/os/unix/ngx_socket.h nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_socket.h
--- nginx-1.6.2/src/os/unix/ngx_socket.h	2014-11-24 11:55:39.513073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_socket.h	2014-11-27 17:18:13.401955203 +0000
@@ -41,6 +41,11 @@ int ngx_blocking(ngx_socket_t s);
 int ngx_tcp_nopush(ngx_socket_t s);
 int ngx_tcp_push(ngx_socket_t s);

+int ngx_set_traffic_class(ngx_socket_t s, unsigned int traffic_class, unsigned int sa_family, unsigned int sockopt);
+
+#define ngx_traffic_class(s, t)  ngx_set_traffic_class(s, t, IPPROTO_IP, IP_TOS)
+#define ngx_traffic_class6(s, t) ngx_set_traffic_class(s, t, IPPROTO_IPV6, IPV6_TCLASS)
+
 #if (NGX_LINUX)

 #define ngx_tcp_nopush_n   "setsockopt(TCP_CORK)"
diff -rpuN nginx-1.6.2/src/os/unix/ngx_writev_chain.c nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_writev_chain.c
--- nginx-1.6.2/src/os/unix/ngx_writev_chain.c	2014-11-24 11:55:39.501073052 +0000
+++ nginx-1.6.2-traffic-xaccel-classid/src/os/unix/ngx_writev_chain.c	2014-11-28 14:31:53.480845948 +0000
@@ -30,6 +30,12 @@ ngx_writev_chain(ngx_connection_t *c, ng
     ngx_event_t   *wev;
     struct iovec  *iov, iovs[NGX_IOVS];

+	unsigned int tos;
+	unsigned int sa_family;
+	socklen_t	 sa_family_len;
+	int			 tos_return;
+	unsigned int traffic_class;
+
     wev = c->write;

     if (!wev->ready) {
@@ -69,6 +75,12 @@ ngx_writev_chain(ngx_connection_t *c, ng

         vec.nelts = 0;

+		/* set connection traffic class */
+		ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev_chain() setting traffic_class: %d (fd: %d)",
+                       c->traffic_class, c->fd);
+
+		ngx_connection_traffic_class(c);
+
         /* create the iovec and coalesce the neighbouring bufs */

         for (cl = in; cl && send < limit; cl = cl->next) {
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to