/*
 * Copyright 2018-present Open Networking Foundation

 * 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.
 */

package common

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"strings"

	"github.com/imdario/mergo"
	log "github.com/sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var tagAllocationValues = []string{
	"unknown",
	"shared",
	"unique",
}

const (
	BP_FORMAT_MEF  = "mef"
	BP_FORMAT_IETF = "ietf"
)

type TagAllocation int

func (t TagAllocation) String() string {
	return tagAllocationValues[t]
}

func tagAllocationFromString(s string) (TagAllocation, error) {
	for i, v := range tagAllocationValues {
		if v == strings.TrimSpace(s) {
			return TagAllocation(i), nil
		}
	}
	log.WithFields(log.Fields{
		"ValidValues": strings.Join(tagAllocationValues[1:], ", "),
	}).Errorf("%s-is-not-a-valid-tag-allocation", s)
	return TagAllocation(0), fmt.Errorf("%s-is-not-a-valid-tag-allocation", s)
}

const (
	_ TagAllocation = iota
	TagAllocationShared
	TagAllocationUnique
)

type BBRCliOptions struct {
	*GlobalConfig
	BBSimIp      string
	BBSimPort    string
	BBSimApiPort string
	LogFile      string
}

type GlobalConfig struct {
	BBSim BBSimConfig
	Olt   OltConfig
	BBR   BBRConfig
}

type OltConfig struct {
	Model              string `yaml:"model"`
	Vendor             string `yaml:"vendor"`
	HardwareVersion    string `yaml:"hardware_version"`
	FirmwareVersion    string `yaml:"firmware_version"`
	DeviceId           string `yaml:"device_id"`
	DeviceSerialNumber string `yaml:"device_serial_number"`
	PonPorts           uint32 `yaml:"pon_ports"`
	NniPorts           uint32 `yaml:"nni_ports"`
	NniSpeed           uint32 `yaml:"nni_speed"`
	OnusPonPort        uint32 `yaml:"onus_per_port"`
	ID                 int    `yaml:"id"`
	OltRebootDelay     int    `yaml:"reboot_delay"`
	PortStatsInterval  int    `yaml:"port_stats_interval"`
	OmciResponseRate   uint8  `yaml:"omci_response_rate"`
	UniPorts           uint32 `yaml:"uni_ports"`
	PotsPorts          uint32 `yaml:"pots_ports"`
}

type PonPortsConfig struct {
	Number uint32           `yaml:"num_pon_ports"`
	Ranges []PonRangeConfig `yaml:"ranges"`
}

type IdRange struct {
	StartId uint32 `yaml:"start"`
	EndId   uint32 `yaml:"end"`
}

type PonTechnology int

var ponTechnologyValues = []string{
	"GPON", "XGS-PON",
}

func (t PonTechnology) String() string {
	return ponTechnologyValues[t]
}

const (
	GPON PonTechnology = iota
	XGSPON
)

func PonTechnologyFromString(s string) (PonTechnology, error) {
	for i, val := range ponTechnologyValues {
		if val == s {
			return PonTechnology(i), nil
		}
	}
	log.WithFields(log.Fields{
		"ValidValues": strings.Join(ponTechnologyValues[:], ", "),
	}).Errorf("%s-is-not-a-valid-pon-technology", s)
	return -1, fmt.Errorf("%s-is-not-a-valid-pon-technology", s)
}

//Constants for default allocation ranges
const (
	defaultOnuIdStart          = 1
	defaultAllocIdStart        = 1024
	defaultGemPortIdPerAllocId = 8
	defaultGemportIdStart      = 1024
)

type PonRangeConfig struct {
	PonRange     IdRange `yaml:"pon_id_range"`
	Technology   string  `yaml:"tech"`
	OnuRange     IdRange `yaml:"onu_id_range"`
	AllocIdRange IdRange `yaml:"alloc_id_range"`
	GemportRange IdRange `yaml:"gemport_id_range"`
}

func GetPonConfigById(id uint32) (*PonRangeConfig, error) {
	if PonsConfig == nil {
		return nil, fmt.Errorf("pons-config-nil")
	}

	for _, r := range PonsConfig.Ranges {
		if id >= r.PonRange.StartId && id <= r.PonRange.EndId {
			return &r, nil
		}
	}

	return nil, fmt.Errorf("pon-config-for-id-%d-not-found", id)
}

type BBSimConfig struct {
	ConfigFile                  string
	ServiceConfigFile           string
	PonsConfigFile              string
	DhcpRetry                   bool    `yaml:"dhcp_retry"`
	AuthRetry                   bool    `yaml:"auth_retry"`
	LogLevel                    string  `yaml:"log_level"`
	LogCaller                   bool    `yaml:"log_caller"`
	Delay                       int     `yaml:"delay"`
	CpuProfile                  *string `yaml:"cpu_profile"`
	OpenOltAddress              string  `yaml:"openolt_address"`
	ApiAddress                  string  `yaml:"api_address"`
	RestApiAddress              string  `yaml:"rest_api_address"`
	LegacyApiAddress            string  `yaml:"legacy_api_address"`
	LegacyRestApiAddress        string  `yaml:"legacy_rest_api_address"`
	SadisRestAddress            string  `yaml:"sadis_rest_address"`
	SadisServer                 bool    `yaml:"sadis_server"`
	KafkaAddress                string  `yaml:"kafka_address"`
	Events                      bool    `yaml:"enable_events"`
	ControlledActivation        string  `yaml:"controlled_activation"`
	EnablePerf                  bool    `yaml:"enable_perf"`
	KafkaEventTopic             string  `yaml:"kafka_event_topic"`
	DmiServerAddress            string  `yaml:"dmi_server_address"`
	BandwidthProfileFormat      string  `yaml:"bp_format"`
	InjectOmciUnknownAttributes bool    `yaml:"inject_omci_unknown_attributes"`
}

type BBRConfig struct {
	Log       string `yaml:"log"`
	LogLevel  string `yaml:"log_level"`
	LogCaller bool   `yaml:"log_caller"`
}

type ServiceYaml struct {
	Name                string
	CTag                int    `yaml:"c_tag"`
	STag                int    `yaml:"s_tag"`
	NeedsEapol          bool   `yaml:"needs_eapol"`
	NeedsDhcp           bool   `yaml:"needs_dhcp"`
	NeedsIgmp           bool   `yaml:"needs_igmp"`
	NeedsPPPoE          bool   `yaml:"needs_pppoe"`
	CTagAllocation      string `yaml:"c_tag_allocation"`
	STagAllocation      string `yaml:"s_tag_allocation"`
	TechnologyProfileID int    `yaml:"tp_id"`
	UniTagMatch         int    `yaml:"uni_tag_match"`
	ConfigureMacAddress bool   `yaml:"configure_mac_address"`
	EnableMacLearning   bool   `yaml:"enable_mac_learning"`
	UsPonCTagPriority   uint8  `yaml:"us_pon_c_tag_priority"`
	UsPonSTagPriority   uint8  `yaml:"us_pon_s_tag_priority"`
	DsPonCTagPriority   uint8  `yaml:"ds_pon_c_tag_priority"`
	DsPonSTagPriority   uint8  `yaml:"ds_pon_s_tag_priority"`
}
type YamlServiceConfig struct {
	Workflow string
	Services []ServiceYaml `yaml:"services,flow"`
}

func (cfg *YamlServiceConfig) String() string {
	str := fmt.Sprintf("[workflow: %s, Services: ", cfg.Workflow)

	for _, s := range cfg.Services {
		str = fmt.Sprintf("%s[", str)
		str = fmt.Sprintf("%sname=%s, c_tag=%d, s_tag=%d, ",
			str, s.Name, s.CTag, s.STag)
		str = fmt.Sprintf("%sc_tag_allocation=%s, s_tag_allocation=%s, ",
			str, s.CTagAllocation, s.STagAllocation)
		str = fmt.Sprintf("%sneeds_eapol=%t, needs_dhcp=%t, needs_igmp=%t",
			str, s.NeedsEapol, s.NeedsDhcp, s.NeedsIgmp)
		str = fmt.Sprintf("%stp_id=%d, uni_tag_match=%d",
			str, s.TechnologyProfileID, s.UniTagMatch)
		str = fmt.Sprintf("%s]", str)
	}
	str = fmt.Sprintf("%s]", str)
	return str
}

var (
	Config     *GlobalConfig
	Services   []ServiceYaml
	PonsConfig *PonPortsConfig
)

// Load the BBSim configuration. This is a combination of CLI parameters and YAML files
// We proceed in this order:
// - Read CLI parameters
// - Using those we read the yaml files (config and services)
// - we merge the configuration (CLI has priority over yaml files)
func LoadConfig() {

	Config = getDefaultOps()

	cliConf := readCliParams()

	yamlConf, err := loadBBSimConf(cliConf.BBSim.ConfigFile)

	if err != nil {
		log.WithFields(log.Fields{
			"file": cliConf.BBSim.ConfigFile,
			"err":  err,
		}).Fatal("Can't read config file")
	}

	// merging Yaml and Default Values
	if err := mergo.Merge(Config, yamlConf, mergo.WithOverride); err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Fatal("Can't merge YAML and Config")
	}

	// merging CLI values on top of the yaml ones
	if err := mergo.Merge(Config, cliConf, mergo.WithOverride); err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Fatal("Can't merge CLI and Config")
	}

	services, err := loadBBSimServices(Config.BBSim.ServiceConfigFile)

	if err != nil {
		log.WithFields(log.Fields{
			"file": Config.BBSim.ServiceConfigFile,
			"err":  err,
		}).Fatal("Can't read services file")
	}

	Services = services

	//A blank filename means we should fall back to bbsim defaults
	if Config.BBSim.PonsConfigFile == "" {
		PonsConfig, err = getDefaultPonsConfig()
		if err != nil {
			log.WithFields(log.Fields{
				"err": err,
			}).Fatal("Can't load Pon interfaces defaults.")
		}
	} else {
		PonsConfig, err = loadBBSimPons(Config.BBSim.PonsConfigFile)

		if err != nil {
			log.WithFields(log.Fields{
				"file": Config.BBSim.PonsConfigFile,
				"err":  err,
			}).Fatal("Can't read services file")
		}
	}

	if err := validatePonsConfig(PonsConfig); err != nil {
		log.WithFields(log.Fields{
			"file": Config.BBSim.PonsConfigFile,
			"err":  err,
		}).Fatal("Invalid Pon interfaces configuration")
	}
}

func readCliParams() *GlobalConfig {

	conf := getDefaultOps()

	configFile := flag.String("config", conf.BBSim.ConfigFile, "Configuration file path")
	servicesFile := flag.String("services", conf.BBSim.ServiceConfigFile, "Service Configuration file path")
	ponsFile := flag.String("pon_port_config_file", conf.BBSim.PonsConfigFile, "Pon Interfaces Configuration file path")
	sadisBpFormat := flag.String("bp_format", conf.BBSim.BandwidthProfileFormat, "Bandwidth profile format, 'mef' or 'ietf'")

	olt_id := flag.Int("olt_id", conf.Olt.ID, "OLT device ID")
	nni := flag.Int("nni", int(conf.Olt.NniPorts), "Number of NNI ports per OLT device to be emulated")
	nni_speed := flag.Uint("nni_speed", uint(conf.Olt.NniSpeed), "Reported speed of the NNI ports in Mbps")
	pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
	onu := flag.Int("onu", int(conf.Olt.OnusPonPort), "Number of ONU devices per PON port to be emulated")
	uni := flag.Int("uni", int(conf.Olt.UniPorts), "Number of Ethernet UNI Ports per ONU device to be emulated")
	pots := flag.Int("pots", int(conf.Olt.PotsPorts), "Number of POTS UNI Ports per ONU device to be emulated")

	oltRebootDelay := flag.Int("oltRebootDelay", conf.Olt.OltRebootDelay, "Time that BBSim should before restarting after a reboot")
	omci_response_rate := flag.Int("omci_response_rate", int(conf.Olt.OmciResponseRate), "Amount of OMCI messages to respond to")

	openolt_address := flag.String("openolt_address", conf.BBSim.OpenOltAddress, "IP address:port")
	api_address := flag.String("api_address", conf.BBSim.ApiAddress, "IP address:port")
	rest_api_address := flag.String("rest_api_address", conf.BBSim.RestApiAddress, "IP address:port")
	dmi_server_address := flag.String("dmi_server_address", conf.BBSim.DmiServerAddress, "IP address:port")

	profileCpu := flag.String("cpuprofile", "", "write cpu profile to file")

	logLevel := flag.String("logLevel", conf.BBSim.LogLevel, "Set the log level (trace, debug, info, warn, error)")
	logCaller := flag.Bool("logCaller", conf.BBSim.LogCaller, "Whether to print the caller filename or not")

	delay := flag.Int("delay", conf.BBSim.Delay, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")

	controlledActivation := flag.String("ca", conf.BBSim.ControlledActivation, "Set the mode for controlled activation of PON ports and ONUs")
	enablePerf := flag.Bool("enableperf", conf.BBSim.EnablePerf, "Setting this flag will cause BBSim to not store data like traffic schedulers, flows of ONUs etc..")
	enableEvents := flag.Bool("enableEvents", conf.BBSim.Events, "Enable sending BBSim events on configured kafka server")
	kafkaAddress := flag.String("kafkaAddress", conf.BBSim.KafkaAddress, "IP:Port for kafka")
	kafkaEventTopic := flag.String("kafkaEventTopic", conf.BBSim.KafkaEventTopic, "Ability to configure the topic on which BBSim publishes events on Kafka")
	dhcpRetry := flag.Bool("dhcpRetry", conf.BBSim.DhcpRetry, "Set this flag if BBSim should retry DHCP upon failure until success")
	authRetry := flag.Bool("authRetry", conf.BBSim.AuthRetry, "Set this flag if BBSim should retry EAPOL (Authentication) upon failure until success")
	injectOmciUnknownAttributes := flag.Bool("injectOmciUnknownAttributes", conf.BBSim.InjectOmciUnknownAttributes, "Generate a MibDB packet with Unknown Attributes")

	flag.Parse()

	conf.Olt.ID = int(*olt_id)
	conf.Olt.NniPorts = uint32(*nni)
	conf.Olt.NniSpeed = uint32(*nni_speed)
	conf.Olt.PonPorts = uint32(*pon)
	conf.Olt.UniPorts = uint32(*uni)
	conf.Olt.PotsPorts = uint32(*pots)
	conf.Olt.OnusPonPort = uint32(*onu)
	conf.Olt.OltRebootDelay = *oltRebootDelay
	conf.Olt.OmciResponseRate = uint8(*omci_response_rate)
	conf.BBSim.ConfigFile = *configFile
	conf.BBSim.ServiceConfigFile = *servicesFile
	conf.BBSim.PonsConfigFile = *ponsFile
	conf.BBSim.CpuProfile = profileCpu
	conf.BBSim.LogLevel = *logLevel
	conf.BBSim.LogCaller = *logCaller
	conf.BBSim.Delay = *delay
	conf.BBSim.ControlledActivation = *controlledActivation
	conf.BBSim.EnablePerf = *enablePerf
	conf.BBSim.Events = *enableEvents
	conf.BBSim.KafkaAddress = *kafkaAddress
	conf.BBSim.OpenOltAddress = *openolt_address
	conf.BBSim.ApiAddress = *api_address
	conf.BBSim.RestApiAddress = *rest_api_address
	conf.BBSim.KafkaEventTopic = *kafkaEventTopic
	conf.BBSim.AuthRetry = *authRetry
	conf.BBSim.DhcpRetry = *dhcpRetry
	conf.BBSim.DmiServerAddress = *dmi_server_address
	conf.BBSim.InjectOmciUnknownAttributes = *injectOmciUnknownAttributes

	// update device id if not set
	if conf.Olt.DeviceId == "" {
		conf.Olt.DeviceId = net.HardwareAddr{0xA, 0xA, 0xA, 0xA, 0xA, byte(conf.Olt.ID)}.String()
	}

	// check that the BP format is valid
	if (*sadisBpFormat != BP_FORMAT_MEF) && (*sadisBpFormat != BP_FORMAT_IETF) {
		log.Fatalf("Invalid parameter 'bp_format', supported values are %s and %s, you provided %s", BP_FORMAT_MEF, BP_FORMAT_IETF, *sadisBpFormat)
	}
	conf.BBSim.BandwidthProfileFormat = *sadisBpFormat

	return conf
}

func getDefaultOps() *GlobalConfig {

	c := &GlobalConfig{
		BBSimConfig{
			ConfigFile:        "configs/bbsim.yaml",
			ServiceConfigFile: "configs/att-services.yaml",
			// PonsConfigFile is left intentionally blank here
			// to use the default values computed at runtime depending
			// on the loaded Services
			PonsConfigFile:              "",
			LogLevel:                    "debug",
			LogCaller:                   false,
			Delay:                       200,
			OpenOltAddress:              ":50060",
			ApiAddress:                  ":50070",
			RestApiAddress:              ":50071",
			LegacyApiAddress:            ":50072",
			LegacyRestApiAddress:        ":50073",
			SadisRestAddress:            ":50074",
			SadisServer:                 true,
			KafkaAddress:                ":9092",
			Events:                      false,
			ControlledActivation:        "default",
			EnablePerf:                  false,
			KafkaEventTopic:             "",
			DhcpRetry:                   false,
			AuthRetry:                   false,
			DmiServerAddress:            ":50075",
			BandwidthProfileFormat:      BP_FORMAT_MEF,
			InjectOmciUnknownAttributes: false,
		},
		OltConfig{
			Vendor:             "BBSim",
			Model:              "asfvolt16",
			HardwareVersion:    "emulated",
			FirmwareVersion:    "",
			DeviceSerialNumber: "BBSM00000001",
			PonPorts:           1,
			NniPorts:           1,
			NniSpeed:           10000, //Mbps
			OnusPonPort:        1,
			ID:                 0,
			OltRebootDelay:     60,
			PortStatsInterval:  20,
			OmciResponseRate:   10,
			UniPorts:           4,
			PotsPorts:          0,
		},
		BBRConfig{
			LogLevel:  "debug",
			LogCaller: false,
		},
	}
	return c
}

func getDefaultPonsConfig() (*PonPortsConfig, error) {

	if Config == nil {
		return nil, fmt.Errorf("Config is nil")
	}
	if Services == nil {
		return nil, fmt.Errorf("Services is nil")
	}

	//The default should replicate the old way bbsim used to compute resource ranges based on the configuration
	// 1 allocId per Service * UNI
	allocIdPerOnu := uint32(Config.Olt.UniPorts * uint32(len(Services)))
	return &PonPortsConfig{
		Number: Config.Olt.PonPorts,
		Ranges: []PonRangeConfig{
			{
				PonRange:   IdRange{0, Config.Olt.PonPorts - 1},
				Technology: XGSPON.String(),
				// we need one ONU ID available per ONU, but the smaller the range the smaller the pool created in the openolt adapter
				OnuRange: IdRange{defaultOnuIdStart, defaultOnuIdStart + (Config.Olt.OnusPonPort - 1)},
				// 1 allocId per Service * UNI * ONU
				AllocIdRange: IdRange{defaultAllocIdStart, defaultAllocIdStart + (Config.Olt.OnusPonPort * allocIdPerOnu)},
				// up to 8 gemport-id per tcont/alloc-id
				GemportRange: IdRange{defaultGemportIdStart, defaultGemportIdStart + Config.Olt.OnusPonPort*allocIdPerOnu*defaultGemPortIdPerAllocId},
			},
		},
	}, nil
}

// LoadBBSimConf loads the BBSim configuration from a YAML file
func loadBBSimConf(filename string) (*GlobalConfig, error) {
	yamlConfig := getDefaultOps()

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		log.WithFields(log.Fields{
			"err":      err,
			"filename": filename,
		}).Error("Cannot load BBSim configuration file. Using defaults.")
		return yamlConfig, nil
	}

	err = yaml.Unmarshal(yamlFile, yamlConfig)
	if err != nil {
		return nil, err
	}

	return yamlConfig, nil
}

// loadBBSimPons loads the configuration of PON interfaces from a YAML file
func loadBBSimPons(filename string) (*PonPortsConfig, error) {
	yamlPonsConfig, err := getDefaultPonsConfig()
	if err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Error("Can't load Pon interfaces defaults.")
		return nil, err
	}

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		log.WithFields(log.Fields{
			"err":      err,
			"filename": filename,
		}).Error("Cannot load Pon interfaces configuration file. Using defaults.")
		return yamlPonsConfig, nil
	}

	err = yaml.Unmarshal(yamlFile, yamlPonsConfig)
	if err != nil {
		return nil, err
	}

	return yamlPonsConfig, nil
}

// validatePonsConfig checks if the configuration to use for the definition of Pon interfaces is valid
func validatePonsConfig(pons *PonPortsConfig) error {

	if pons.Number == 0 {
		return fmt.Errorf("no-pon-ports")
	}

	definedPorts := make([]int, pons.Number)

	for rIndex, resRange := range pons.Ranges {
		if _, err := PonTechnologyFromString(resRange.Technology); err != nil {
			return err
		}

		if resRange.PonRange.EndId < resRange.PonRange.StartId {
			return fmt.Errorf("invalid-pon-ports-limits-in-range-%d", rIndex)
		}

		//Keep track of the defined pons
		for p := resRange.PonRange.StartId; p <= resRange.PonRange.EndId; p++ {
			if p > uint32(len(definedPorts)-1) {
				return fmt.Errorf("pon-port-%d-in-range-%d-but-max-is-%d", p, rIndex, pons.Number-1)
			}
			definedPorts[p]++

			if definedPorts[p] > 1 {
				return fmt.Errorf("pon-port-%d-has-duplicate-definition-in-range-%d", p, rIndex)
			}
		}

		if resRange.OnuRange.EndId < resRange.OnuRange.StartId {
			return fmt.Errorf("invalid-onus-limits-in-range-%d", rIndex)
		}
		if resRange.AllocIdRange.EndId < resRange.AllocIdRange.StartId {
			return fmt.Errorf("invalid-allocid-limits-in-range-%d", rIndex)
		}
		if resRange.GemportRange.EndId < resRange.GemportRange.StartId {
			return fmt.Errorf("invalid-gemport-limits-in-range-%d", rIndex)
		}
	}

	//Check if the ranges define all the pons
	for i, num := range definedPorts {
		if num < 1 {
			return fmt.Errorf("pon-port-%d-is-not-defined-in-ranges", i)
		}
	}

	return nil
}

// LoadBBSimServices parses a file describing the services that need to be created for each UNI
func loadBBSimServices(filename string) ([]ServiceYaml, error) {

	yamlServiceCfg := YamlServiceConfig{}

	yamlFile, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal([]byte(yamlFile), &yamlServiceCfg)
	if err != nil {
		return nil, err
	}

	for _, service := range yamlServiceCfg.Services {

		if service.CTagAllocation == "" || service.STagAllocation == "" {
			log.Fatal("c_tag_allocation and s_tag_allocation are mandatory fields")
		}

		if _, err := tagAllocationFromString(string(service.CTagAllocation)); err != nil {
			log.WithFields(log.Fields{
				"err": err,
			}).Fatal("c_tag_allocation is not valid")
		}
	}

	log.WithFields(log.Fields{
		"services": yamlServiceCfg.String(),
	}).Debug("BBSim services description correctly loaded")
	return yamlServiceCfg.Services, nil
}

// This is only used by BBR
func GetBBROpts() BBRCliOptions {

	bbsimIp := flag.String("bbsimIp", "127.0.0.1", "BBSim IP")
	bbsimPort := flag.String("bbsimPort", "50060", "BBSim Port")
	bbsimApiPort := flag.String("bbsimApiPort", "50070", "BBSim API Port")
	logFile := flag.String("logfile", "", "Log to a file")

	LoadConfig()

	bbrOptions := BBRCliOptions{
		Config,
		*bbsimIp,
		*bbsimPort,
		*bbsimApiPort,
		*logFile,
	}

	return bbrOptions
}
