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