From patchwork Wed Jun 29 02:02:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nirapada Ghosh X-Patchwork-Id: 641785 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3rfQst5c4wz9ssM for ; Wed, 29 Jun 2016 12:02:26 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 9A2D4108B5; Tue, 28 Jun 2016 19:02:24 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 92EE21059E for ; Tue, 28 Jun 2016 19:02:23 -0700 (PDT) Received: from bar5.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id B7B701E0473 for ; Tue, 28 Jun 2016 20:02:22 -0600 (MDT) X-ASG-Debug-ID: 1467165740-09eadd41fb92940001-byXFYA Received: from mx3-pf2.cudamail.com ([192.168.14.1]) by bar5.cudamail.com with ESMTP id 7xx4AMn9pcI7O2eG (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 28 Jun 2016 20:02:20 -0600 (MDT) X-Barracuda-Envelope-From: nirapada@host.local.domain X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.1 Received: from unknown (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by mx3-pf2.cudamail.com with ESMTPS (AES256-SHA encrypted); 29 Jun 2016 02:02:17 -0000 Received-SPF: none (mx3-pf2.cudamail.com: domain at host.local.domain does not designate permitted sender hosts) X-Barracuda-Apparent-Source-IP: 148.163.156.1 X-Barracuda-RBL-IP: 148.163.156.1 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u5T1x9ZA083371 for ; Tue, 28 Jun 2016 22:02:16 -0400 Received: from e06smtp09.uk.ibm.com (e06smtp09.uk.ibm.com [195.75.94.105]) by mx0a-001b2d01.pphosted.com with ESMTP id 23v09nrtcn-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 28 Jun 2016 22:02:16 -0400 Received: from localhost by e06smtp09.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 29 Jun 2016 03:02:13 +0100 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp09.uk.ibm.com (192.168.101.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 29 Jun 2016 03:02:10 +0100 X-IBM-Helo: d06dlp02.portsmouth.uk.ibm.com X-IBM-MailFrom: nirapada@host.local.domain X-IBM-RcptTo: dev@openvswitch.org Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id 595222190046 for ; Wed, 29 Jun 2016 03:01:40 +0100 (BST) Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u5T22AOo3146000 for ; Wed, 29 Jun 2016 02:02:10 GMT Received: from d06av02.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u5T22At1005407 for ; Tue, 28 Jun 2016 20:02:10 -0600 Received: from host.local.domain ([9.80.196.104]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u5T22810005354 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 28 Jun 2016 20:02:09 -0600 Received: by host.local.domain (Postfix, from userid 501) id 3594E163EBCF; Tue, 28 Jun 2016 19:02:08 -0700 (PDT) X-CudaMail-Envelope-Sender: nirapada@host.local.domain From: nghosh@us.ibm.com To: dev@openvswitch.org X-CudaMail-MID: CM-V2-627065891 X-CudaMail-DTE: 062816 X-CudaMail-Originating-IP: 148.163.156.1 Date: Tue, 28 Jun 2016 19:02:06 -0700 X-ASG-Orig-Subj: [##CM-V2-627065891##][PATCH V12] Function tracer to trace all function calls X-Mailer: git-send-email 2.7.4 (Apple Git-66) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16062902-0036-0000-0000-000001F71959 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16062902-0037-0000-0000-00001185D30A Message-Id: <1467165726-21960-1-git-send-email-nghosh@us.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-06-29_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=43 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606290018 X-GBUdb-Analysis: 0, 148.163.156.1, Ugly c=0.297854 p=-0.111111 Source Normal X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.14.1] X-Barracuda-Start-Time: 1467165740 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using global scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_RULE7568M, BSF_SC5_MJ1963, NO_REAL_NAME, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30850 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 NO_REAL_NAME From: does not include a real name 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [PATCH V12] Function tracer to trace all function calls X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: Nirapada Ghosh In some circumstances, we might need to figure out where in code, the CPU time is being spent most, so as to pinpoint the bottleneck and thereby resolve it with proper changes. Using '-finstrument-functions' flag, that can be achieved, and this patch exactly does that. There is a python file [generate_ft_report.py] with the patch, that may be used to convert this trace output to a human readable format with symbol names instead of address and their execution times. This tool uses addr2line that expects the executable to be built with -g flag. To enable this feature, ovs needs needs to be configured with "--enable-ft" command line argument [i.e. configure --enable-ft] This instrumentation logs the tracing output in separate log files namely func_trace_.log. It does not use VLOG mechanism for logging as that will make the patch very complicated to avoid recursion in the trace routine. This feature starts dumping output, only in debug mode, which means ovs-appctl -t vlog/set any:any:dbg should be used to enable this logging. Currently, only ovn-northd, ovn-controller, vswitchd are instrumented. It is intended to be used for debugging purposes. Signed-off-by: Nirapada Ghosh --- configure.ac | 10 +++ include/openvswitch/vlog.h | 1 + lib/vlog.c | 23 ++++++ ovn/controller/automake.mk | 5 ++ ovn/controller/ovn-controller.c | 10 +++ ovn/northd/automake.mk | 5 ++ ovn/northd/ovn-northd.c | 10 +++ third-party/automake.mk | 6 ++ third-party/function_tracer.c | 143 ++++++++++++++++++++++++++++++++++++++ third-party/generate_ft_report.py | 79 +++++++++++++++++++++ utilities/automake.mk | 1 + vswitchd/automake.mk | 5 ++ vswitchd/ovs-vswitchd.c | 9 +++ 13 files changed, 307 insertions(+) create mode 100644 third-party/function_tracer.c create mode 100644 third-party/generate_ft_report.py diff --git a/configure.ac b/configure.ac index 05d80d5..4abb2ea 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,16 @@ AC_PROG_MKDIR_P AC_PROG_FGREP AC_PROG_EGREP +AC_ARG_ENABLE(ft, +[ --enable-ft Turn on function-tracing], +[case "${enableval}" in + yes) ft=true ;; + no) ft=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-ft) ;; +esac],[ft=false]) +AM_CONDITIONAL(ENABLE_FT, test x$ft = xtrue) + + AC_ARG_VAR([PERL], [path to Perl interpreter]) AC_PATH_PROG([PERL], perl, no) if test "$PERL" = no; then diff --git a/include/openvswitch/vlog.h b/include/openvswitch/vlog.h index de64cbd..2df8796 100644 --- a/include/openvswitch/vlog.h +++ b/include/openvswitch/vlog.h @@ -57,6 +57,7 @@ enum vlog_level { VLL_N_LEVELS }; +void __attribute__ ((no_instrument_function)) vlog_directory(char *, int); const char *vlog_get_level_name(enum vlog_level); enum vlog_level vlog_get_level_val(const char *name); diff --git a/lib/vlog.c b/lib/vlog.c index 333337b..2670dde 100644 --- a/lib/vlog.c +++ b/lib/vlog.c @@ -1262,6 +1262,29 @@ vlog_should_drop(const struct vlog_module *module, enum vlog_level level, return false; } +void __attribute__ ((no_instrument_function)) +vlog_directory(char *dir,int len) +{ + int dir_len; + if (log_file_name == NULL) { + dir_len = strlen(ovs_logdir()); + if (dir_len > len) { + *dir = '\0'; + } + snprintf(dir, dir_len, "%s", ovs_logdir()); + } else { + char *fname = strrchr(log_file_name,'/'); + if (fname) { + dir_len = strlen(log_file_name) - strlen(fname)+1; + if (dir_len > len) { + *dir = '\0'; + } else { + snprintf(dir, dir_len, "%s", log_file_name); + } + } + } +} + void vlog_rate_limit(const struct vlog_module *module, enum vlog_level level, struct vlog_rate_limit *rl, const char *message, ...) diff --git a/ovn/controller/automake.mk b/ovn/controller/automake.mk index cf57bbd..8e8f3bc 100644 --- a/ovn/controller/automake.mk +++ b/ovn/controller/automake.mk @@ -20,6 +20,11 @@ ovn_controller_ovn_controller_SOURCES = \ ovn/controller/ovn-controller.h \ ovn/controller/physical.c \ ovn/controller/physical.h + +if ENABLE_FT +ovn_controller_ovn_controller_SOURCES += third-party/function_tracer.c +endif + ovn_controller_ovn_controller_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la man_MANS += ovn/controller/ovn-controller.8 EXTRA_DIST += ovn/controller/ovn-controller.8.xml diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 47e6824..c0bc9a0 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -61,11 +61,20 @@ static unixctl_cb_func ct_zone_list; #define DEFAULT_BRIDGE_NAME "br-int" +static bool g_command_line_args_parsed = false; static void parse_options(int argc, char *argv[]); +bool __attribute__ ((no_instrument_function)) is_cmd_line_args_parsed(void); + OVS_NO_RETURN static void usage(void); static char *ovs_remote; +bool __attribute__ ((no_instrument_function)) +is_cmd_line_args_parsed(void) +{ + return g_command_line_args_parsed; +} + struct local_datapath * get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key) { @@ -608,6 +617,7 @@ parse_options(int argc, char *argv[]) VLOG_FATAL("exactly zero or one non-option argument required; " "use --help for usage"); } + g_command_line_args_parsed = true; } static void diff --git a/ovn/northd/automake.mk b/ovn/northd/automake.mk index 6e713fc..4b02045 100644 --- a/ovn/northd/automake.mk +++ b/ovn/northd/automake.mk @@ -1,6 +1,11 @@ # ovn-northd bin_PROGRAMS += ovn/northd/ovn-northd ovn_northd_ovn_northd_SOURCES = ovn/northd/ovn-northd.c + +if ENABLE_FT +ovn_northd_ovn_northd_SOURCES += third-party/function_tracer.c +endif + ovn_northd_ovn_northd_LDADD = \ ovn/lib/libovn.la \ ovsdb/libovsdb.la \ diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index c2cf15e..750e0c7 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -42,6 +42,9 @@ VLOG_DEFINE_THIS_MODULE(ovn_northd); +static bool g_command_line_args_parsed = false; +bool __attribute__ ((no_instrument_function)) is_cmd_line_args_parsed(void); + static unixctl_cb_func ovn_northd_exit; struct northd_context { @@ -122,6 +125,12 @@ enum ovn_stage { #undef PIPELINE_STAGE }; +bool __attribute__ ((no_instrument_function)) +is_cmd_line_args_parsed(void) +{ + return g_command_line_args_parsed; +} + /* Due to various hard-coded priorities need to implement ACLs, the * northbound database supports a smaller range of ACL priorities than * are available to logical flows. This value is added to an ACL @@ -2692,6 +2701,7 @@ parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) } free(short_options); + g_command_line_args_parsed = true; } static void diff --git a/third-party/automake.mk b/third-party/automake.mk index fea5ac7..39a79be 100644 --- a/third-party/automake.mk +++ b/third-party/automake.mk @@ -1,2 +1,8 @@ +if ENABLE_FT +CFLAGS += -g -finstrument-functions \ + -ldl -export-dynamic -lrt \ + -finstrument-functions-exclude-function-list=snprintf,fprintf +endif + docs += third-party/README.md EXTRA_DIST += third-party/ofp-tcpdump.patch diff --git a/third-party/function_tracer.c b/third-party/function_tracer.c new file mode 100644 index 0000000..1ba64c6 --- /dev/null +++ b/third-party/function_tracer.c @@ -0,0 +1,143 @@ +/* Copyright (c) 2016 IBM, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file implements routines needed to log all function calls' + * entry and exit timestamps along with it's hex address. With + * python tool generate_ft_report.py, this log can be converted with + * symbol names for offline analysis. + */ + +#include +#include +#include +#include +#include +#include +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(trace); + +#define LOG_FILE_NAME_LEN 256 +#define LOG_DIR_NAME_LEN 128 +#define LOG_FILENAME_PREFIX "func_trace" +#define CURRENT_LOG_LEVEL this_module.min_level + +/* File pointer for logging the trace output. */ +static FILE *log_fp; + +/* External functions used here */ +void __attribute__ ((no_instrument_function)) ft_log_open(void); +bool __attribute__ ((no_instrument_function)) is_cmd_line_args_parsed(void); + +/* Prototypes for the functions declared/used in this file. */ +void __attribute__ ((constructor,no_instrument_function)) ft_begin(void); +void __attribute__ ((destructor,no_instrument_function)) ft_end(void); +void __attribute__ ((no_instrument_function)) ft(const char * direction, + void *func, void * caller); +void __attribute__ ((no_instrument_function)) __cyg_profile_func_enter( + void *func, void *caller); +void __attribute__ ((no_instrument_function)) __cyg_profile_func_exit( + void *func, void *caller); +int __attribute__ ((no_instrument_function)) format_time(struct timeval *lt, + char *buf, + size_t size); + +void __attribute__ ((constructor,no_instrument_function)) +ft_begin(void) +{ + /* Nothing at this point, but needed */ +} + +void __attribute__ ((no_instrument_function)) +ft_log_open(void) +{ + char log_name[LOG_FILE_NAME_LEN]; + char dir_name[LOG_DIR_NAME_LEN]; + + vlog_directory(dir_name, LOG_DIR_NAME_LEN); + snprintf(log_name, LOG_FILE_NAME_LEN, "%s/%s_%d.log", + dir_name, LOG_FILENAME_PREFIX, getpid()); + if ((log_fp = fopen(log_name, "w")) == NULL) { + fprintf(stderr, "Failed to open output trace file: %s\n", log_name); + } +} + + +void __attribute__ ((destructor,no_instrument_function)) +ft_end(void) +{ + if (log_fp != NULL) { + fclose(log_fp); + } +} + +/* Gets the current timestamp into the input buffer in ascii format */ +int __attribute__ ((no_instrument_function)) +format_time(struct timeval *lt, char *buf, size_t size) +{ + struct tm gm_time; + int bytes_written = -1; + + gmtime_r(<->tv_sec,&gm_time); + bytes_written = strftime(buf, size, "%Y-%m-%dT%H:%M:%S", &gm_time); + if ((bytes_written > 0) && ((size_t) bytes_written < size)) { + int tmp = snprintf(buf + bytes_written, + size - (size_t) bytes_written, ".%06d", + (int) lt->tv_usec); + bytes_written = (tmp > 0) ? bytes_written + tmp : -1; + } + return bytes_written; +} + + +void __attribute__ ((no_instrument_function)) +ft(const char *direction, void *func, void *caller) +{ + char timestr[64]; + struct timeval ltime; + + if (log_fp == NULL && is_cmd_line_args_parsed()) { + ft_log_open(); + } + if ((!is_cmd_line_args_parsed()) || (log_fp == NULL)) { + return; + } + if (gettimeofday(<ime, NULL) != 0) { + return; + } + if (format_time(<ime, timestr, sizeof(timestr)) <= 0) { + return; + } + fprintf(log_fp, "%s>%s>%p>%p\n", timestr, + direction, func, caller); + fflush(log_fp); +} + +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_enter(void *func, void *caller) +{ + if (CURRENT_LOG_LEVEL >= VLL_DBG) { + ft("entry", func, caller); + } +} + +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_exit(void *func, void *caller) +{ + if (CURRENT_LOG_LEVEL >= VLL_DBG) { + ft("exit", func, caller); + } +} diff --git a/third-party/generate_ft_report.py b/third-party/generate_ft_report.py new file mode 100644 index 0000000..defc429 --- /dev/null +++ b/third-party/generate_ft_report.py @@ -0,0 +1,79 @@ +# Copyright (c) 2016 IBM, Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +#!/usr/bin/env python +import sys +import subprocess +from datetime import datetime + +# functions hold the details regarding when it was called, when it was complete +functions = {} + +def find_symbol_name(func_addr, exe): + """Give the hex address of a method, this returns the symbol name + """ + p = subprocess.Popen("addr2line -e " + exe + ' --functions ' + + func_addr, stdout=subprocess.PIPE, shell=True) + (out,err) = p.communicate() + if not err: + tokens = out.split() + return tokens[0] + return func_addr + "(unknown)" + +def time_diff(time1, time2): + """This method finds the delta between two times passed + """ + date_obj1 = datetime.strptime(time1, '%Y-%m-%dT%H:%M:%S.%f') + date_obj2 = datetime.strptime(time2, '%Y-%m-%dT%H:%M:%S.%f') + delta = date_obj2 - date_obj1 + return delta + +def update_and_print(tstamp, direction, called, caller, + serial, exe, verbose=False): + """This method updates the exit-point of a function in functions map, + finds out the execution time of that function and prints in human- + readable format. + """ + func_name = find_symbol_name(called, exe) + if direction == "exit": + ## Find out corresponding entry point, + try: + entry = functions[func_name] + if verbose: + print "ENTRY:%s EXIT %s" %(entry['timestamp'], tstamp) + diff = time_diff(entry['timestamp'],tstamp) + print "%d %s %s %s" %(entry['serial'], func_name, + entry['caller'], diff) + except Exception, ex: + print "Exception %s" %ex + else: + functions[func_name] = {'timestamp':tstamp, 'caller':caller, + 'serial':serial} + + +def main(): + if len(sys.argv) != 3: + print "Usage: %s " %sys.argv[0] + return + exe = sys.argv[1] + filename = sys.argv[2] + serial = 0 + with open(filename) as f: + for line in f: + serial += 1 + tokens = line.strip().split('>') + #arguments (timestamp, dirn, called, caller,serial,exe) + update_and_print(tokens[0], tokens[1], tokens[2], + tokens[3], serial, exe) + +if __name__ == "__main__": + main() diff --git a/utilities/automake.mk b/utilities/automake.mk index 9d5b425..54e50d5 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -59,6 +59,7 @@ EXTRA_DIST += \ utilities/ovs-vlan-test.in \ utilities/ovs-vsctl-bashcomp.bash \ utilities/qemu-wrap.py \ + third-party/generate_ft_report.py \ utilities/checkpatch.py MAN_ROOTS += \ utilities/ovs-appctl.8.in \ diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk index 8d7f3ea..6b12124 100644 --- a/vswitchd/automake.mk +++ b/vswitchd/automake.mk @@ -11,6 +11,11 @@ vswitchd_ovs_vswitchd_SOURCES = \ vswitchd/system-stats.h \ vswitchd/xenserver.c \ vswitchd/xenserver.h + +if ENABLE_FT +vswitchd_ovs_vswitchd_SOURCES += third-party/function_tracer.c +endif + vswitchd_ovs_vswitchd_LDADD = \ ofproto/libofproto.la \ lib/libsflow.la \ diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c index 72448bb..b910a3c 100644 --- a/vswitchd/ovs-vswitchd.c +++ b/vswitchd/ovs-vswitchd.c @@ -51,6 +51,8 @@ VLOG_DEFINE_THIS_MODULE(vswitchd); +static bool g_command_line_args_parsed = false; +bool __attribute__ ((no_instrument_function)) is_cmd_line_args_parsed(void); /* --mlockall: If set, locks all process memory into physical RAM, preventing * the kernel from paging any of its memory to disk. */ static bool want_mlockall; @@ -60,6 +62,12 @@ static unixctl_cb_func ovs_vswitchd_exit; static char *parse_options(int argc, char *argv[], char **unixctl_path); OVS_NO_RETURN static void usage(void); +bool __attribute__ ((no_instrument_function)) +is_cmd_line_args_parsed(void) +{ + return g_command_line_args_parsed; +} + int main(int argc, char *argv[]) { @@ -228,6 +236,7 @@ parse_options(int argc, char *argv[], char **unixctl_pathp) argc -= optind; argv += optind; + g_command_line_args_parsed = true; switch (argc) { case 0: