diff --git a/src/cfgutils.c b/src/cfgutils.c index 14bef8e86..221860882 100644 --- a/src/cfgutils.c +++ b/src/cfgutils.c @@ -1752,6 +1752,8 @@ processProtocolEntry(config_t* config, yaml_document_t* doc, yaml_node_t* node) --g_prot_sequence; destroyProtEntry(protocol_context); DBG(NULL); + } else { + setExternalProto(protocol_context); } protocol_context = NULL; } diff --git a/src/dbg.c b/src/dbg.c index 7c74192b5..ddc71c031 100644 --- a/src/dbg.c +++ b/src/dbg.c @@ -358,3 +358,43 @@ scopeLogHex(cfg_log_level_t level, const void *data, size_t size, const char *fo } scopeLog(level, " %04x: %s %s", i-16, hex, txt); } + +void +scopeHexDump(cfg_log_level_t level, src_data_t dtype, void *buf, size_t len) +{ + size_t dlen; + + if (!buf) return; + + if (dtype == BUF) { + // simple buffer, pass it through + dlen = len > 64 ? 64 : len; + scopeLogHex(level, buf, dlen, "BUF:"); + } else if (dtype == MSG) { + // buffer is a msghdr for sendmsg/recvmsg + int i; + struct msghdr *msg = (struct msghdr *)buf; + struct iovec *iov; + + for (i = 0; i < msg->msg_iovlen; i++) { + iov = &msg->msg_iov[i]; + dlen = iov->iov_len > 64 ? 64 : iov->iov_len; + if (iov && iov->iov_base && (iov->iov_len > 0)) { + scopeLogHex(level, iov->iov_base, dlen, "MSG:"); + } + } + } else if ( dtype == IOV) { + // buffer is an iovec, len is the iovcnt + int i; + struct iovec *iov = (struct iovec *)buf; + + for (i = 0; i < len; i++) { + if (iov[i].iov_base && (iov[i].iov_len > 0)) { + dlen = iov[i].iov_len > 64 ? 64 : iov[i].iov_len; + scopeLogHex(level, iov[i].iov_base, dlen, "IOV:"); + } + } + } else { + DBG(NULL); // just a note + } +} diff --git a/src/dbg.h b/src/dbg.h index cc4cee4ed..0c76f3854 100644 --- a/src/dbg.h +++ b/src/dbg.h @@ -5,6 +5,7 @@ #include #include "log.h" #include "scopetypes.h" +#include "state.h" typedef struct _dbg_t dbg_t; @@ -73,6 +74,7 @@ extern bool g_ismusl; void scopeLog(cfg_log_level_t, const char *, ...) PRINTF_FORMAT(2,3); void scopeLogHex(cfg_log_level_t, const void *, size_t, const char *, ...) PRINTF_FORMAT(4,5); void scopeBacktrace(cfg_log_level_t); +void scopeHexDump(cfg_log_level_t, src_data_t, void *, size_t); #define scopeLogError(...) scopeLog(CFG_LOG_ERROR, __VA_ARGS__) #define scopeLogWarn(...) scopeLog(CFG_LOG_WARN, __VA_ARGS__) diff --git a/src/httpstate.c b/src/httpstate.c index 770dc1484..74e4c0ca4 100644 --- a/src/httpstate.c +++ b/src/httpstate.c @@ -812,6 +812,15 @@ doHttpBuffer(http_state_t states[HTTP_NUM], net_info *net, char *buf, size_t len return FALSE; } +bool +detectHttp(void *buf, size_t len) +{ + if ((len >= HTTP2_MAGIC_LEN && !scope_strncmp(buf, HTTP2_MAGIC, HTTP2_MAGIC_LEN)) || + (searchExec(g_http_start, buf, len) != -1)) return TRUE; + + return FALSE; +} + bool doHttp(uint64_t id, int sockfd, net_info *net, char *buf, size_t len, metric_t src, src_data_t dtype) { diff --git a/src/httpstate.h b/src/httpstate.h index 4ea45f434..b73dd3463 100644 --- a/src/httpstate.h +++ b/src/httpstate.h @@ -8,5 +8,6 @@ void initHttpState(void); bool doHttp(uint64_t, int, net_info*, char*, size_t, metric_t, src_data_t); void resetHttp(http_state_t httpstate[HTTP_NUM]); +bool detectHttp(void *, size_t); #endif // __HTTPSTATE_H__ diff --git a/src/state.c b/src/state.c index 4e95b5db0..8b2685607 100644 --- a/src/state.c +++ b/src/state.c @@ -32,6 +32,8 @@ #define FS_ENTRIES 1024 #define NUM_ATTEMPTS 100 #define MAX_CONVERT (size_t)256 +#define MIN_PKT 0 +#define MIN_TLS_LEN 5 extern rtconfig g_cfg; @@ -52,6 +54,8 @@ static search_t* g_http_redirect = NULL; static protocol_def_t *g_tls_protocol_def = NULL; static protocol_def_t *g_http_protocol_def = NULL; static protocol_def_t *g_statsd_protocol_def = NULL; +static bool g_userHTTP = FALSE; +static bool g_userTLS = FALSE; // Linked list, indexed by channel ID, of net_info pointers used in // doProtocol() when it's not provided with a valid file descriptor. @@ -195,6 +199,7 @@ addProtocol(request_t *req) return FALSE; } + setExternalProto(proto); return TRUE; } @@ -912,6 +917,46 @@ doUpdateState(metric_t type, int fd, ssize_t size, const char *funcop, const cha } } +static bool +notifyProtocol(int sockfd, net_info *net, protocol_def_t *protoDef) +{ + protocol_info *proto; + + if (protoDef->detect && ctlEvtSourceEnabled(g_ctl, CFG_SRC_NET)) { + if ((proto = scope_calloc(1, sizeof(struct protocol_info_t))) == NULL) { + return FALSE; + } + + proto->evtype = EVT_PROTO; + proto->ptype = EVT_DETECT; + proto->len = sizeof(protocol_def_t); + proto->fd = sockfd; + if (net) proto->uid = net->uid; + proto->data = (char *)scope_strdup(protoDef->protname); + cmdPostEvent(g_ctl, (char *)proto); + return TRUE; + } + + return FALSE; +} + +/* + * Called when we add a protocol entry. + * If a user protocol entry defines HTTP &/or TLS, then save. + * Just noting that they are available at this time. + */ +void +setExternalProto(protocol_def_t *proto) +{ + if (scope_strcasecmp(proto->protname, "HTTP") == 0) { + g_userHTTP = TRUE; + } + + if (scope_strcasecmp(proto->protname, "TLS") == 0) { + g_userTLS = TRUE; + } +} + bool isProtocolSet(int fd) { @@ -926,7 +971,6 @@ setProtocol(int sockfd, protocol_def_t *protoDef, net_info *net, char *buf, size { char *data, *cpdata = NULL; pcre2_match_data *match_data; - protocol_info *proto; bool ret = FALSE; // nothing we can do; don't risk reading past end of a buffer @@ -941,7 +985,8 @@ setProtocol(int sockfd, protocol_def_t *protoDef, net_info *net, char *buf, size // precedence to a len defined with the protocol definition // if a len was not provided in the definition use the one passed // therefore, len is now protoDef->len - if (protoDef->len > 0) { + // however, don't allow the cvlen to be larger than the packet len + if ((protoDef->len > 0) && (protoDef->len <= len)) { cvlen = protoDef->len; } @@ -976,22 +1021,10 @@ setProtocol(int sockfd, protocol_def_t *protoDef, net_info *net, char *buf, size net->protoProtoDef = protoDef; } - if (protoDef->detect && ctlEvtSourceEnabled(g_ctl, CFG_SRC_NET)) { - if ((proto = scope_calloc(1, sizeof(struct protocol_info_t))) == NULL) - { - if (cpdata) - scope_free(cpdata); - if (match_data) - pcre2_match_data_free(match_data); - return FALSE; - } - proto->evtype = EVT_PROTO; - proto->ptype = EVT_DETECT; - proto->len = sizeof(protocol_def_t); - proto->fd = sockfd; - if (net) proto->uid = net->uid; - proto->data = (char *)scope_strdup(protoDef->protname); - cmdPostEvent(g_ctl, (char *)proto); + if (notifyProtocol(sockfd, net, protoDef) == FALSE) { + if (cpdata) scope_free(cpdata); + if (match_data) pcre2_match_data_free(match_data); + return FALSE; } ret = TRUE; // matched @@ -1027,7 +1060,7 @@ setProtocolByType(int sockfd, protocol_def_t *protoDef, net_info *net, char *buf ret = ret || setProtocol(sockfd, protoDef, net, iov->iov_base, iov->iov_len); } } - } else if ( dtype == IOV) { + } else if (dtype == IOV) { // buffer is an iovec, len is the iovcnt int i; struct iovec *iov = (struct iovec *)buf; @@ -1143,17 +1176,39 @@ extractPayload(int sockfd, net_info *net, void *buf, size_t len, metric_t src, s * * Sets net->tlsDetect and net->tlsProtoDef. */ +static bool +detectTLSBinary(net_info *net, void *buf, size_t len) +{ + unsigned char *data = buf; + + // 16030[0-3].{4}0[12] 16 03 00|01|02|03 *+2 01|02 + // example: 16 03 01 00 ff 01 00 00 + if ((net && (g_userTLS == FALSE)) && (len >= MIN_TLS_LEN) && + (data[0] == (char)0x16) && (data[1] == (char)0x03) && + ((data[2] == (char)0x00) || (data[2] == (char)0x01) || + (data[2] == (char)0x02) ||(data[2] == (char)0x03))) { + net->tlsDetect = DETECT_TRUE; + net->tlsProtoDef = g_tls_protocol_def; + return TRUE; + } else if (net && (g_userHTTP == FALSE) && detectHttp(buf, len)) { + net->tlsDetect = DETECT_FALSE; + net->tlsProtoDef = g_http_protocol_def; + return TRUE; + } + + return FALSE; +} + static void -detectTLS(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_data_t dtype) +detectTLSRegex(int sockfd, net_info *net, void *buf, size_t len, src_data_t dtype) { int rc; - unsigned char *data = buf; unsigned int ptype; + unsigned char *data = buf; protocol_def_t *tls_proto_def = g_tls_protocol_def; // use ours by default // Look for an overridden TLS entry from the protocol detector configs - for (ptype = 0; ptype <= g_prot_sequence; ptype++) - { + for (ptype = 0; ptype <= g_prot_sequence; ptype++) { protocol_def_t *tmp_proto_def; if ((tmp_proto_def = lstFind(g_protlist, ptype)) && (scope_strcmp(tmp_proto_def->protname, "TLS") == 0)) { @@ -1168,17 +1223,53 @@ detectTLS(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_da size_t alen = (tls_proto_def->len * 2) + 1; char cpdata[alen]; scope_memset(cpdata, 0, alen); - for (i = 0; i < tls_proto_def->len; i++) - { - scope_snprintf(&cpdata[i << 1], 3, "%02x", data[i]); + + if (dtype == BUF) { + size_t dlen = (tls_proto_def->len <= len) ? tls_proto_def->len : len; + for (i = 0; i < dlen; i++) { + scope_snprintf(&cpdata[i << 1], 3, "%02x", data[i]); + } + } else if (dtype == MSG) { + int j; + struct msghdr *msg = (struct msghdr *)buf; + struct iovec *iov; + for (i = 0; i < msg->msg_iovlen; i++) { + iov = &msg->msg_iov[i]; + if (iov && iov->iov_base && (iov->iov_len > 0)) { + unsigned char *data = iov->iov_base; + size_t dlen = (tls_proto_def->len <= iov->iov_len) ? + tls_proto_def->len : iov->iov_len; + + for (j = 0; j < dlen; j++) { + scope_snprintf(&cpdata[j << 1], 3, "%02x", data[j]); + } + } + } + } else if (dtype == IOV) { + // buffer is an iovec, len is the iovcnt + int j; + struct iovec *iov = (struct iovec *)buf; + for (i = 0; i < len; i++) { + if (iov[i].iov_base && (iov[i].iov_len > 0)) { + unsigned char *data = iov[i].iov_base; + size_t dlen = (tls_proto_def->len <= iov[i].iov_len) ? + tls_proto_def->len : iov[i].iov_len; + + for (j = 0; j < dlen; j++) { + scope_snprintf(&cpdata[j << 1], 3, "%02x", data[j]); + } + } + } + } else { + DBG(NULL); // how do we even get here? + return; // no need to continue; } // Apply the regex to the hex-string payload pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(tls_proto_def->re, NULL); if ((rc = pcre2_match_wrapper(tls_proto_def->re, (PCRE2_SPTR)cpdata, (PCRE2_SIZE)alen, 0, 0, - match_data, NULL)) > 0) - { + match_data, NULL)) > 0) { // matched, set the detect-state to TRUE net->tlsDetect = DETECT_TRUE; net->tlsProtoDef = tls_proto_def; @@ -1186,9 +1277,7 @@ detectTLS(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_da if (tls_proto_def->detect) { // TODO send TLS protocol-detect event } - } - else - { + } else { // didn't match, set the detect-state to FALSE net->tlsDetect = DETECT_FALSE; if (rc != PCRE2_ERROR_NOMATCH) @@ -1197,23 +1286,69 @@ detectTLS(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_da scopeLog(CFG_LOG_DEBUG, "%s: fd:%d TLS regex failed", __FUNCTION__, sockfd); } } + pcre2_match_data_free(match_data); } static void -detectProtocol(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_data_t dtype) +detectTLS(int sockfd, net_info *net, char *buf, size_t len, src_data_t dtype) +{ + bool rc = FALSE; + + if (dtype == BUF) { + // simple buffer, pass it through + rc = detectTLSBinary(net, buf, len); + } else if (dtype == MSG) { + // buffer is a msghdr for sendmsg/recvmsg + int i; + struct msghdr *msg = (struct msghdr *)buf; + struct iovec *iov; + for (i = 0; i < msg->msg_iovlen; i++) { + iov = &msg->msg_iov[i]; + if ((iov && iov->iov_base && (iov->iov_len > 0)) && + ((rc = detectTLSBinary(net, iov->iov_base, iov->iov_len)) == TRUE)) { + break; + } + } + } else if (dtype == IOV) { + // buffer is an iovec, len is the iovcnt + int i; + struct iovec *iov = (struct iovec *)buf; + for (i = 0; i < len; i++) { + if ((iov[i].iov_base && (iov[i].iov_len > 0)) && + ((rc = detectTLSBinary(net, iov[i].iov_base, iov[i].iov_len)) == TRUE)) { + break; + } + } + } else { + DBG(NULL); // just a note + } + + if (rc == FALSE) detectTLSRegex(sockfd, net, buf, len, dtype); + return; +} + +static bool +detectProtoByString(int sockfd, net_info *net, void *buf, size_t len) +{ + if (net && (g_userHTTP == FALSE) && detectHttp(buf, len)) { + net->protoDetect = DETECT_TRUE; + net->protoProtoDef = g_http_protocol_def; + notifyProtocol(sockfd, net, g_http_protocol_def); + return TRUE; + } + + return FALSE; +} + +static void +detectProtoByRegex(int sockfd, net_info *net, void *buf, size_t len, metric_t src, src_data_t dtype) { unsigned int ptype; protocol_def_t *protoDef; bool sawHTTP = FALSE; bool sawSTATSD = FALSE; - // No need to try protocol detection in raw TLS data - if (net && net->tlsDetect == DETECT_TRUE // TLS detected already - && (src == NETRX || src == NETTX)) { // raw payload - return; - } - // Check first against the protocol entries in the configs. for (ptype = 0; ptype <= g_prot_sequence; ptype++) { if ((protoDef = lstFind(g_protlist, ptype)) != NULL) { @@ -1229,13 +1364,59 @@ detectProtocol(int sockfd, net_info *net, void *buf, size_t len, metric_t src, s // Try default protocol definitions if they haven't been overridden. if (!sawHTTP && setProtocolByType(sockfd, g_http_protocol_def, net, buf, len, dtype)) { - return; + return; } + if (!sawSTATSD && setProtocolByType(sockfd, g_statsd_protocol_def, net, buf, len, dtype)) { - return; + return; } } +static void +detectProtocol(int sockfd, net_info *net, char *buf, size_t len, metric_t src, src_data_t dtype) +{ + bool rc = FALSE; + + // No need to try protocol detection in raw TLS data + if (net && (net->tlsDetect == DETECT_TRUE) // TLS detected already + && ((src == NETRX) || (src == NETTX))) { // raw payload + return; + } + + if (dtype == BUF) { + // simple buffer, pass it through + rc = detectProtoByString(sockfd, net, buf, len); + } else if (dtype == MSG) { + // buffer is a msghdr for sendmsg/recvmsg + int i; + struct msghdr *msg = (struct msghdr *)buf; + struct iovec *iov; + for (i = 0; i < msg->msg_iovlen; i++) { + iov = &msg->msg_iov[i]; + if (iov && iov->iov_base && (iov->iov_len > 0) && + ((rc = detectProtoByString(sockfd, net, iov->iov_base, iov->iov_len)) == TRUE)) { + break; + } + } + } else if (dtype == IOV) { + // buffer is an iovec, len is the iovcnt + int i; + struct iovec *iov = (struct iovec *)buf; + for (i = 0; i < len; i++) { + if (iov[i].iov_base && (iov[i].iov_len > 0) && + ((rc = detectProtoByString(sockfd, net, iov[i].iov_base, iov[i].iov_len)) == TRUE)) { + break; + } + } + } else { + DBG(NULL); // just a note + } + + if (rc == FALSE) detectProtoByRegex(sockfd, net, buf, len, src, dtype); + + return; +} + // Alternative to getNetEntry() that returns a net_info for the given channel // ID instead of for a socket descriptor. We fallback to using this when we // can't get the descriptor in TLS/SSL read/write operations. @@ -1272,37 +1453,43 @@ doProtocol(uint64_t id, int sockfd, void *buf, size_t len, metric_t src, src_dat // Find the net_info for the channel net_info *net = getNetEntry(sockfd); // first try by descriptor if (!net) net = getChannelNetEntry(id); // fallback to using channel ID - - scopeLogHexDebug(buf, len > 64 ? 64 : len, // limit hexdump to 64 - "DEBUG: doProtocol(id=%ld, fd=%d, len=%ld, src=%s, dtyp=%s) TLS=%s PROTO=%s", - id, sockfd, len, - src == NETRX ? "NETRX" : - src == NETTX ? "NETTX" : - src == TLSRX ? "TLSRX" : - src == TLSTX ? "TLSTX" : "?", - dtype == BUF ? "BUF" : - dtype == MSG ? "MSG" : - dtype == IOV ? "IOV" : - dtype == NONE ? "NONE" : "?", - net == NULL ? "NULL" : - net->tlsDetect == DETECT_PENDING ? "PENDING" : - net->tlsDetect == DETECT_TRUE ? "TRUE" : - net->tlsDetect == DETECT_FALSE ? "FALSE" : "INVALID", - net == NULL ? "NULL" : - net->protoDetect == DETECT_PENDING ? "PENDING" : - net->protoDetect == DETECT_TRUE ? "TRUE" : - net->protoDetect == DETECT_FALSE ? "FALSE" : "INVALID" - ); +#ifdef DEBUG + scopeLog(CFG_LOG_DEBUG, "DEBUG: doProtocol (id=%ld, fd=%d, len=%ld, src=%s, dtype=%s) TLS=%s PROTO=%s", + id, sockfd, len, + src == NETRX ? "NETRX" : + src == NETTX ? "NETTX" : + src == TLSRX ? "TLSRX" : + src == TLSTX ? "TLSTX" : + "?", + dtype == BUF ? "BUF" : + dtype == MSG ? "MSG" : + dtype == IOV ? "IOV" : + dtype == NONE ? "NONE" : + "?", + net == NULL ? "NULL" : + net->tlsDetect == DETECT_PENDING ? "PENDING" : + net->tlsDetect == DETECT_TRUE ? "TRUE" : + net->tlsDetect == DETECT_FALSE ? "FALSE" : + "INVALID", + net == NULL ? "NULL" : + net->protoDetect == DETECT_PENDING ? "PENDING" : + net->protoDetect == DETECT_TRUE ? "TRUE" : + net->protoDetect == DETECT_FALSE ? "FALSE" : + "INVALID"); + + cfg_log_level_t cfg_level = logLevel(g_log); + if (cfg_level <= CFG_LOG_DEBUG) scopeHexDump(CFG_LOG_DEBUG, dtype, buf, len); +#endif // Ignore empty payloads that should have been blocked by our interpositions - if (!len) { + if (len <= MIN_PKT) { scopeLogDebug("DEBUG: fd:%d ignoring empty payload", sockfd); return 0; } // Do TLS detection if not already done if (net && net->tlsDetect == DETECT_PENDING) { - detectTLS(sockfd, net, buf, len, src, dtype); + detectTLS(sockfd, net, buf, len, dtype); } // Only process unencrypted payloads @@ -1328,7 +1515,6 @@ doProtocol(uint64_t id, int sockfd, void *buf, size_t len, metric_t src, src_dat if (cfgMtcWatchEnable(g_cfg.staticfg, CFG_MTC_STATSD) && !scope_strcasecmp(net->protoProtoDef->protname, "STATSD")) { - doMetricCapture(id, sockfd, net, buf, len, src, dtype); } } @@ -1984,7 +2170,7 @@ doURL(int sockfd, const void *buf, size_t len, metric_t src) int doRecv(int sockfd, ssize_t rc, const void *buf, size_t len, src_data_t src) { - if (checkNetEntry(sockfd) == TRUE) { + if (checkNetEntry(sockfd) == TRUE) { if (!g_netinfo[sockfd].active) { doAddNewSock(sockfd); } diff --git a/src/state.h b/src/state.h index 966ffbc5c..4ae4db097 100644 --- a/src/state.h +++ b/src/state.h @@ -78,5 +78,5 @@ void setRemoteClose(int, int); void setFSContentType(int, fs_content_type_t); fs_content_type_t getFSContentType(int); bool isProtocolSet(int); - +void setExternalProto(protocol_def_t *); #endif // __STATE_H__ diff --git a/test/bench/http/http.sh b/test/bench/http/http.sh index 98abc5d44..3f167faf6 100755 --- a/test/bench/http/http.sh +++ b/test/bench/http/http.sh @@ -2,31 +2,157 @@ # Requires nginx, scope, ab # Configure /etc/nginx/nginx.conf with: worker_processes 1 -unscoped_nginx() { - printf "Unscoped Nginx:\n" +unscoped2_h2_nginx() { + printf "Unscoped Nginx HTTP2:\n" sudo nginx -s stop + sleep 3 sudo nginx PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') - ab -c 1 -n 10000 http://127.0.0.1:80/ > /dev/null 2>&1 + h2load -c 1 -n 100 https://127.0.0.1:443/ #> /dev/null 2>&1 END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') printf "Start:\t%s\n" $START printf "End:\t%s\n" $END - printf "Diff:\t%s\n" $(($END-$START)) + printf "Diff:\t%s\n" $((($END-$START) / 100)) } -scoped_nginx() { - printf "\nScoped Nginx:\n" +scoped2_h2_nginx() { + printf "\nScoped Nginx HTTP2:\n" sudo nginx -s stop - sudo ../../../bin/linux/x86_64/scope run -- nginx + sudo -E ../../../bin/linux/x86_64/ldscope nginx + sleep 2 PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') - ab -c 1 -n 10000 http://127.0.0.1:80/ > /dev/null 2>&1 + h2load -c 1 -n 1 https://127.0.0.1:443/ #> /dev/null 2>&1 END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') printf "Start:\t%s\n" $START printf "End:\t%s\n" $END - printf "Diff:\t%s\n" $(($END-$START)) + printf "Diff:\t%s\n" $((($END-$START) / 100)) } -unscoped_nginx -scoped_nginx +unscoped2_w2_nginx() { + printf "Unscoped Nginx HTTP2:\n" + nn=0 + sys=0.00 + usr=0.00 + val=0 + uv=0 + sudo nginx -s stop + sudo nginx + sleep 1 + + PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') + START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + + while [[ $nn -lt "1" ]]; do + /usr/bin/time -f "%S %U" -o temp wget2 --no-check-certificate --http2 https://localhost/ + sleep 1 + nn=$((nn+1)) + + val=`cat temp | cut -d " " -f 1` + x=$sys + y=$val + sys="$x + $y" + echo "sys = `bc <<< $sys`" + + val=`cat temp | cut -d " " -f 2` + x=$usr + y=$val + usr="$x + $y" + echo $usr + echo "usr = `bc <<< $usr`" + done + + END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + printf "Start:\t%s\n" $START + printf "End:\t%s\n" $END + printf "Diff:\t%s\n\n" $(($END-$START)) + printf "system time: %s \n" `bc <<< $sys` + printf "user time: %s\n" `bc <<< $usr` + + x="$sys + $usr" + echo "Total time: `bc <<< $x`" + + rm index.html* + rm temp +} + +scoped2_w2_nginx() { + printf "\nScoped Nginx HTTP2:\n" + nn=0 + sys=0.00 + usr=0.00 + val=0 + uv=0 + sudo nginx -s stop + sudo -E ../../../bin/linux/x86_64/ldscope nginx + sleep 1 + + PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') + START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + + while [[ $nn -lt "1" ]]; do + /usr/bin/time -f "%S %U" -o temp wget2 --no-check-certificate --http2 https://localhost/ + sleep 1 + nn=$((nn+1)) + + val=`cat temp | cut -d " " -f 1` + x=$sys + y=$val + sys="$x + $y" + echo "sys = `bc <<< $sys`" + + val=`cat temp | cut -d " " -f 2` + x=$usr + y=$val + usr="$x + $y" + echo $usr + echo "usr = `bc <<< $usr`" + done + + END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + printf "Start:\t%s\n" $START + printf "End:\t%s\n" $END + printf "Diff:\t%s\n\n" $(($END-$START)) + printf "system time: %s \n" `bc <<< $sys` + printf "user time: %s\n" `bc <<< $usr` + + x="$sys + $usr" + echo "Total time: `bc <<< $x`" + + rm index.html* + rm temp +} + +unscoped1_nginx() { + printf "Unscoped Nginx HTTP1:\n" + sudo nginx -s stop + sudo nginx + PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') + START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + ab -c 1 -n 100 http://127.0.0.1:80/ > /dev/null 2>&1 + END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + printf "Start:\t%s\n" $START + printf "End:\t%s\n" $END + printf "Diff:\t%s\n" $((($END-$START) / 100)) +} + +scoped1_nginx() { + printf "\nScoped Nginx HTTP1:\n" + sudo nginx -s stop + sudo -E ../../../bin/linux/x86_64/ldscope nginx + PID=$(ps -ef | grep www-data | grep -v grep | awk '{ print $2 }') + START=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + ab -c 1 -n 100 http://127.0.0.1:80/ > /dev/null 2>&1 + END=$(cat /proc/$PID/schedstat | awk '{ print $1 }') + printf "Start:\t%s\n" $START + printf "End:\t%s\n" $END + printf "Diff:\t%s\n" $((($END-$START) / 100)) +} + +unscoped1_nginx +scoped1_nginx +#unscoped2_h2_nginx +#scoped2_h2_nginx +#unscoped2_w2_nginx +#scoped2_w2_nginx