From b252b4a043b900a2a7585c0b091f03794c8d4a7e Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Fri, 25 Feb 2022 12:36:53 +0100 Subject: [PATCH] net: get missing config variables from config_2g3g Don't ask the user to copy config_2g3g and manually keep it in sync with config_2g3g with each change anymore. Instead, let the user config be a diff on top of config_2g3g. This is in preparation to adding new variables for use with OsmoBSCNAT. Change-Id: I5870d39aee8be84c2024f8a2a71ee4a734a4fc7c --- net/README | 68 ++++++++++++++++++++++++++++++++++------------ net/fill_config.py | 63 ++++++++++++++++++++++++++++-------------- 2 files changed, 93 insertions(+), 38 deletions(-) diff --git a/net/README b/net/README index 73a8d2f..f3c388a 100644 --- a/net/README +++ b/net/README @@ -10,28 +10,55 @@ contributions of any improvements you may have! === Quick Start -cp config_2g3g config_mine -$EDITOR config_mine -# update IP addresses and device names as required +* Open config_2g3g in a text editor (original config) +* Open a new file in a text editor (your config) +* Copy over all lines you want to change in your config and edit them there +* Your resulting minimal config could look like this: -mkdir my_network -cd my_network -../fill_config.py ../config_mine ../templates + TERMINAL="tmux" -./run.sh -# Launches numerous x-terminals with one component running in each. -# Logs and pcap traces are being taken automatically. + ETH_DEV=enp0s25 -# hit enter in the original first terminal to tear down all programs. -# Enter a name to save logs, otherwise all logging will be stored -# under autolog/ + TO_RAN_IP="192.168.1.123" + TO_RAN_IU_IP="192.168.1.42" -Then possibly modify the config and refresh: + MCC=999 + MNC=99 -# tweak config? -$EDITOR ../config_mine -../fill_config.py -# picks up same ../config_mine and ../templates from last time + BTS0_IPA_UNIT="1234 0" + BTS0_ARFCN=800 + +* Create a network directory and generate configs: + + $ mkdir my_network + $ cd my_network + $ ../fill_config.py ../config_mine ../templates + +* Run the network: + + $ ./run.sh + + This launches numerous terminals with one component running in each. + Logs and pcap traces are being taken automatically. + +* Tear down: + + Hit enter in the original first terminal to tear down all programs. + Enter a name to save logs, otherwise all logging will be stored + under autolog/. + +* Regenerate configs: + + Modify your config and regenerate the network configs as follows, the same + original config, your config and templates will be used as last time. + + $ $EDITOR ../config_mine + $ ../fill_config.py + + ('make regen' also works) + + +=== Advanced usage / more examples # own templates? cp -r ../templates ../templates_mine @@ -67,7 +94,7 @@ A *directory* contains template files that are filled with specific values by th fill_config.py script. See e.g. templates/. A *file* contains local config items as name=val pairs that are put into the -templates. See e.g. config_2g3g. +templates. It is usually a subset of config_2g3g. The fill_config.py script helps to fill the templates with the config values. Simply invoke fill_config.py with a dir argument (templates dir) and a file argument (specific @@ -77,6 +104,11 @@ temporary files (sockets etc.) should be placed inside this folder. If one or both are omitted, the script tries to re-use the most recent paths, they were stored in local files '.last_config' and '.last_templates'. +The -o parameter of fill_config.py can be used to supply a different original +config file than config_2g3g. If it is omitted, the path is read from a +'.last_config_orig' file inside the network directory if present, and config_2g3g +is used otherwise. + The result is a complete set of .cfg files that match your local machine and network config. diff --git a/net/fill_config.py b/net/fill_config.py index f68f572..8d1b959 100755 --- a/net/fill_config.py +++ b/net/fill_config.py @@ -8,7 +8,9 @@ import argparse def file_newer(path_a, than_path_b): return os.path.getmtime(path_a) > os.path.getmtime(than_path_b) +DEFAULT_ORIG_CONFIG = os.path.normpath(os.path.realpath(__file__) + "/../config_2g3g") LAST_LOCAL_CONFIG_FILE = '.last_config' +LAST_ORIG_CONFIG_FILE = '.last_config_orig' LAST_TMPL_DIR = '.last_templates' parser = argparse.ArgumentParser(description=__doc__, @@ -18,10 +20,14 @@ parser.add_argument('sources', metavar='SRC', nargs='*', parser.add_argument('-s', '--check-stale', dest='check_stale', action='store_true', help='only verify age of generated files vs. config and templates.' ' Exit nonzero when any source file is newer. Do not write anything.') +parser.add_argument('-o', '--original-config', + help='get missing variables from this file, default is config_2g3g' + ' or the file used previously to fill an existing template dir') args = parser.parse_args() local_config_file = None +orig_config_file = args.original_config tmpl_dir = None for src in args.sources: @@ -37,6 +43,12 @@ for src in args.sources: if local_config_file is None and os.path.isfile(LAST_LOCAL_CONFIG_FILE): local_config_file = open(LAST_LOCAL_CONFIG_FILE).read().strip() +if orig_config_file is None: + if os.path.isfile(LAST_ORIG_CONFIG_FILE): + orig_config_file = open(LAST_ORIG_CONFIG_FILE).read().strip() + else: + orig_config_file = DEFAULT_ORIG_CONFIG + if tmpl_dir is None and os.path.isfile(LAST_TMPL_DIR): tmpl_dir = open(LAST_TMPL_DIR).read().strip() @@ -48,47 +60,57 @@ if not local_config_file or not os.path.isfile(local_config_file): print("No such config file: %r" % local_config_file) exit(1) +if not os.path.isfile(orig_config_file): + print("No such config file: %r" % orig_config_file) + exit(1) + local_config_file = os.path.realpath(local_config_file) tmpl_dir = os.path.realpath(tmpl_dir) net_dir = os.path.realpath(".") print(f'using config file: {local_config_file}') +print(f'with original: {orig_config_file}') print(f'on templates: {tmpl_dir}') print(f'with NET_DIR: {net_dir}') with open(LAST_LOCAL_CONFIG_FILE, 'w') as last_file: last_file.write(local_config_file) +with open(LAST_ORIG_CONFIG_FILE, 'w') as last_file: + last_file.write(orig_config_file) with open(LAST_TMPL_DIR, 'w') as last_file: last_file.write(tmpl_dir) -# read in variable values from config file +# read in variable values from config files # NET_DIR is the folder where fill_config.py was started local_config = {"NET_DIR": net_dir} -line_nr = 0 -for line in open(local_config_file): - line_nr += 1 - line = line.strip('\n') +for config_file in [orig_config_file, local_config_file]: + current_config_identifiers = ["NET_DIR"] + line_nr = 0 + for line in open(config_file): + line_nr += 1 + line = line.strip('\n') - if line.startswith('#'): - continue + if line.startswith('#'): + continue - if not '=' in line: - if line: - print("Error: %r line %d: %r" % (local_config_file, line_nr, line)) - exit(1) - continue + if not '=' in line: + if line: + print("Error: %r line %d: %r" % (config_file, line_nr, line)) + exit(1) + continue - split_pos = line.find('=') - name = line[:split_pos] - val = line[split_pos + 1:] + split_pos = line.find('=') + name = line[:split_pos] + val = line[split_pos + 1:] - if val.startswith('"') and val.endswith('"'): - val = val[1:-1] + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] - if name in local_config: - print("Error: duplicate identifier in %r line %d: %r" % (local_config_file, line_nr, line)) - local_config[name] = val + if name in current_config_identifiers: + print("Error: duplicate identifier in %r line %d: %r" % (config_file, line_nr, line)) + local_config[name] = val + current_config_identifiers += [name] # replace variable names with above values recursively replace_re = re.compile('\$\{([A-Z_][A-Za-z0-9_]*)\}') @@ -240,6 +262,7 @@ for tmpl_name in sorted(os.listdir(tmpl_dir)): if args.check_stale: check_stale(local_config_file, dst) + check_stale(orig_config_file, dst) check_stale(tmpl_src, dst) local_config['_fname'] = tmpl_name