NFVBENCH-180: Add a 'no_e2e_check' option to skip "end to end" connectivity check
[nfvbench.git] / nfvbench / nfvbench.py
index 06ca19d..314b828 100644 (file)
@@ -88,8 +88,7 @@ class NFVBench(object):
         try:
             # recalc the running config based on the base config and options for this run
             self._update_config(opts)
-            if int(self.config.cache_size) < 0:
-                self.config.cache_size = self.config.flow_count
+
             # check that an empty openrc file (no OpenStack) is only allowed
             # with EXT chain
             if not self.config.openrc_file and self.config.service_chain != ChainType.EXT:
@@ -223,6 +222,14 @@ class NFVBench(object):
         if config.flow_count % 2:
             config.flow_count += 1
 
+        # Possibly adjust the cache size
+        if config.cache_size < 0:
+            config.cache_size = config.flow_count
+
+        # The size must be capped to 10000 (where does this limit come from?)
+        if config.cache_size > 10000:
+            config.cache_size = 10000
+
         config.duration_sec = float(config.duration_sec)
         config.interval_sec = float(config.interval_sec)
         config.pause_sec = float(config.pause_sec)
@@ -235,7 +242,6 @@ class NFVBench(object):
             if config.flavor.vcpus < 2:
                 raise Exception("Flavor vcpus must be >= 2")
 
-
         config.ndr_run = (not config.no_traffic and
                           'ndr' in config.rate.strip().lower().split('_'))
         config.pdr_run = (not config.no_traffic and
@@ -274,6 +280,23 @@ class NFVBench(object):
         self.config_plugin.validate_config(config, self.specs.openstack)
 
 
+def bool_arg(x):
+    """Argument type to be used in parser.add_argument()
+    When a boolean like value is expected to be given
+    """
+    return (str(x).lower() != 'false') \
+        and (str(x).lower() != 'no') \
+        and (str(x).lower() != '0')
+
+
+def int_arg(x):
+    """Argument type to be used in parser.add_argument()
+    When an integer type value is expected to be given
+    (returns 0 if argument is invalid, hexa accepted)
+    """
+    return int(x, 0)
+
+
 def _parse_opts_from_cli():
     parser = argparse.ArgumentParser()
 
@@ -476,7 +499,38 @@ def _parse_opts_from_cli():
                         metavar='<vlan>',
                         help='Port to port or port to switch to port L2 loopback with VLAN id')
 
+    parser.add_argument('--user-info', dest='user_info',
+                        action='store',
+                        metavar='<data>',
+                        help='Custom data to be included as is in the json report config branch - '
+                               + ' example, pay attention! no space: '
+                               + '--user-info=\'{"status":"explore","description":'
+                               + '{"target":"lab","ok":true,"version":2020}}\'')
+
+    parser.add_argument('--vlan-tagging', dest='vlan_tagging',
+                        type=bool_arg,
+                        metavar='<boolean>',
+                        action='store',
+                        default=None,
+                        help='Override the NFVbench \'vlan_tagging\' parameter')
+
+    parser.add_argument('--intf-speed', dest='intf_speed',
+                        metavar='<speed>',
+                        action='store',
+                        default=None,
+                        help='Override the NFVbench \'intf_speed\' '
+                                + 'parameter (e.g. 10Gbps, auto, 16.72Gbps)')
+
+    parser.add_argument('--cores', dest='cores',
+                        type=int_arg,
+                        metavar='<number>',
+                        action='store',
+                        default=None,
+                        help='Override the T-Rex \'cores\' parameter')
+
     parser.add_argument('--cache-size', dest='cache_size',
+                        type=int_arg,
+                        metavar='<size>',
                         action='store',
                         default='0',
                         help='Specify the FE cache size (default: 0, flow-count if < 0)')
@@ -484,12 +538,17 @@ def _parse_opts_from_cli():
     parser.add_argument('--service-mode', dest='service_mode',
                         action='store_true',
                         default=False,
-                        help='Enable T-Rex service mode for debugging only')
+                        help='Enable T-Rex service mode (for debugging purpose)')
+
+    parser.add_argument('--no-e2e-check', dest='no_e2e_check',
+                        action='store_true',
+                        default=False,
+                        help='Skip "end to end" connectivity check (on test purpose)')
 
     parser.add_argument('--no-flow-stats', dest='no_flow_stats',
                         action='store_true',
                         default=False,
-                        help='Disable extra flow stats (on high load traffic)')
+                        help='Disable additional flow stats (on high load traffic)')
 
     parser.add_argument('--no-latency-stats', dest='no_latency_stats',
                         action='store_true',
@@ -501,6 +560,15 @@ def _parse_opts_from_cli():
                         default=False,
                         help='Disable latency measurements (no streams)')
 
+    parser.add_argument('--debug-mask', dest='debug_mask',
+                        type=int_arg,
+                        metavar='<mask>',
+                        action='store',
+                        default='0x00000000',
+                        help='General purpose register (debugging flags), '
+                                + 'the hexadecimal notation (0x...) is accepted.'
+                                + 'Designed for development needs.')
+
     opts, unknown_opts = parser.parse_known_args()
     return opts, unknown_opts
 
@@ -571,7 +639,8 @@ def main():
             factory = getattr(factory_module, config['factory_class'])()
         except AttributeError:
             raise Exception("Requested factory module '{m}' or class '{c}' was not found."
-                            .format(m=config['factory_module'], c=config['factory_class']))
+                            .format(m=config['factory_module'],
+                                    c=config['factory_class'])) from AttributeError
         # create config plugin for this platform
         config_plugin = factory.get_config_plugin_class()(config)
         config = config_plugin.get_config()
@@ -599,7 +668,8 @@ def main():
         config.name = ''
         if opts.config:
             # do not check extra_specs in flavor as it can contain any key/value pairs
-            whitelist_keys = ['extra_specs']
+            # the same principle applies also to the optional user_info open property
+            whitelist_keys = ['extra_specs', 'user_info']
             # override default config options with start config at path parsed from CLI
             # check if it is an inline yaml/json config or a file name
             if os.path.isfile(opts.config):
@@ -618,6 +688,17 @@ def main():
                 LOG.addHandler(fluent_logger)
                 break
 
+        # convert 'user_info' opt from json string to dictionnary
+        # and merge the result with the current config dictionnary
+        if opts.user_info:
+            opts.user_info = json.loads(opts.user_info)
+            if config.user_info:
+                config.user_info = config.user_info + opts.user_info
+            else:
+                config.user_info = opts.user_info
+            # hide the option to further _update_config()
+            opts.user_info = None
+
         # traffic profile override options
         override_custom_traffic(config, opts.frame_sizes, opts.unidir)