blob: 58cec201d197fd216cdb223e3460b11ab54ddbc6 [file] [log] [blame]
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package common
18
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010019import (
20 "flag"
21 "fmt"
22 "io/ioutil"
23 "net"
Matteo Scandolof65e6872020-04-15 15:18:43 -070024 "strings"
Shrey Baid64cda472020-04-24 18:58:18 +053025
Matteo Scandolo4a036262020-08-17 15:56:13 -070026 "github.com/imdario/mergo"
Shrey Baid64cda472020-04-24 18:58:18 +053027 log "github.com/sirupsen/logrus"
Matteo Scandolo4a036262020-08-17 15:56:13 -070028 "gopkg.in/yaml.v2"
Matteo Scandolof65e6872020-04-15 15:18:43 -070029)
Matteo Scandolo40e067f2019-10-16 16:59:41 -070030
Matteo Scandolof65e6872020-04-15 15:18:43 -070031var tagAllocationValues = []string{
32 "unknown",
33 "shared",
34 "unique",
35}
36
Matteo Scandolo94967142021-05-28 11:37:06 -070037const (
38 BP_FORMAT_MEF = "mef"
39 BP_FORMAT_IETF = "ietf"
40)
41
Matteo Scandolof65e6872020-04-15 15:18:43 -070042type TagAllocation int
43
44func (t TagAllocation) String() string {
45 return tagAllocationValues[t]
46}
47
48func tagAllocationFromString(s string) (TagAllocation, error) {
49 for i, v := range tagAllocationValues {
Matteo Scandolo4a036262020-08-17 15:56:13 -070050 if v == strings.TrimSpace(s) {
Matteo Scandolof65e6872020-04-15 15:18:43 -070051 return TagAllocation(i), nil
52 }
53 }
54 log.WithFields(log.Fields{
55 "ValidValues": strings.Join(tagAllocationValues[1:], ", "),
56 }).Errorf("%s-is-not-a-valid-tag-allocation", s)
Shrey Baid688b4242020-07-10 20:40:10 +053057 return TagAllocation(0), fmt.Errorf("%s-is-not-a-valid-tag-allocation", s)
Matteo Scandolof65e6872020-04-15 15:18:43 -070058}
59
60const (
61 _ TagAllocation = iota
62 TagAllocationShared
63 TagAllocationUnique
64)
65
Matteo Scandolo40e067f2019-10-16 16:59:41 -070066type BBRCliOptions struct {
Matteo Scandolo4a036262020-08-17 15:56:13 -070067 *GlobalConfig
Matteo Scandolo40e067f2019-10-16 16:59:41 -070068 BBSimIp string
69 BBSimPort string
70 BBSimApiPort string
Matteo Scandolof5c537e2019-10-28 16:45:57 -070071 LogFile string
Matteo Scandolo40e067f2019-10-16 16:59:41 -070072}
73
Matteo Scandolo4a036262020-08-17 15:56:13 -070074type GlobalConfig struct {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010075 BBSim BBSimConfig
76 Olt OltConfig
77 BBR BBRConfig
78}
Matteo Scandolo40e067f2019-10-16 16:59:41 -070079
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010080type OltConfig struct {
81 Model string `yaml:"model"`
82 Vendor string `yaml:"vendor"`
83 HardwareVersion string `yaml:"hardware_version"`
84 FirmwareVersion string `yaml:"firmware_version"`
85 DeviceId string `yaml:"device_id"`
86 DeviceSerialNumber string `yaml:"device_serial_number"`
87 PonPorts uint32 `yaml:"pon_ports"`
88 NniPorts uint32 `yaml:"nni_ports"`
Elia Battiston420c9092022-02-02 12:17:54 +010089 NniSpeed uint32 `yaml:"nni_speed"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010090 OnusPonPort uint32 `yaml:"onus_per_port"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010091 ID int `yaml:"id"`
92 OltRebootDelay int `yaml:"reboot_delay"`
Shrey Baid688b4242020-07-10 20:40:10 +053093 PortStatsInterval int `yaml:"port_stats_interval"`
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000094 OmciResponseRate uint8 `yaml:"omci_response_rate"`
Mahir Gunyela1753ae2021-06-23 00:24:56 -070095 UniPorts uint32 `yaml:"uni_ports"`
Elia Battistonac63b112022-01-12 18:40:49 +010096 PotsPorts uint32 `yaml:"pots_ports"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010097}
Matteo Scandolo40e067f2019-10-16 16:59:41 -070098
Elia Battistonb7bea222022-02-18 16:25:00 +010099type PonPortsConfig struct {
100 Number uint32 `yaml:"num_pon_ports"`
101 Ranges []PonRangeConfig `yaml:"ranges"`
102}
103
104type IdRange struct {
105 StartId uint32 `yaml:"start"`
106 EndId uint32 `yaml:"end"`
107}
108
109type PonTechnology int
110
111var ponTechnologyValues = []string{
112 "GPON", "XGS-PON",
113}
114
115func (t PonTechnology) String() string {
116 return ponTechnologyValues[t]
117}
118
119const (
120 GPON PonTechnology = iota
121 XGSPON
122)
123
124func PonTechnologyFromString(s string) (PonTechnology, error) {
125 for i, val := range ponTechnologyValues {
126 if val == s {
127 return PonTechnology(i), nil
128 }
129 }
130 log.WithFields(log.Fields{
131 "ValidValues": strings.Join(ponTechnologyValues[:], ", "),
132 }).Errorf("%s-is-not-a-valid-pon-technology", s)
133 return -1, fmt.Errorf("%s-is-not-a-valid-pon-technology", s)
134}
135
136//Constants for default allocation ranges
137const (
138 defaultOnuIdStart = 1
139 defaultAllocIdStart = 1024
140 defaultGemPortIdPerAllocId = 8
141 defaultGemportIdStart = 1024
142)
143
144type PonRangeConfig struct {
145 PonRange IdRange `yaml:"pon_id_range"`
146 Technology string `yaml:"tech"`
147 OnuRange IdRange `yaml:"onu_id_range"`
148 AllocIdRange IdRange `yaml:"alloc_id_range"`
149 GemportRange IdRange `yaml:"gemport_id_range"`
150}
151
152func GetPonConfigById(id uint32) (*PonRangeConfig, error) {
153 if PonsConfig == nil {
154 return nil, fmt.Errorf("pons-config-nil")
155 }
156
157 for _, r := range PonsConfig.Ranges {
158 if id >= r.PonRange.StartId && id <= r.PonRange.EndId {
159 return &r, nil
160 }
161 }
162
163 return nil, fmt.Errorf("pon-config-for-id-%d-not-found", id)
164}
165
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100166type BBSimConfig struct {
Matteo Scandolo94967142021-05-28 11:37:06 -0700167 ConfigFile string
168 ServiceConfigFile string
Elia Battistonb7bea222022-02-18 16:25:00 +0100169 PonsConfigFile string
Matteo Scandolo94967142021-05-28 11:37:06 -0700170 DhcpRetry bool `yaml:"dhcp_retry"`
171 AuthRetry bool `yaml:"auth_retry"`
172 LogLevel string `yaml:"log_level"`
173 LogCaller bool `yaml:"log_caller"`
174 Delay int `yaml:"delay"`
175 CpuProfile *string `yaml:"cpu_profile"`
176 OpenOltAddress string `yaml:"openolt_address"`
177 ApiAddress string `yaml:"api_address"`
178 RestApiAddress string `yaml:"rest_api_address"`
179 LegacyApiAddress string `yaml:"legacy_api_address"`
180 LegacyRestApiAddress string `yaml:"legacy_rest_api_address"`
181 SadisRestAddress string `yaml:"sadis_rest_address"`
182 SadisServer bool `yaml:"sadis_server"`
183 KafkaAddress string `yaml:"kafka_address"`
184 Events bool `yaml:"enable_events"`
185 ControlledActivation string `yaml:"controlled_activation"`
186 EnablePerf bool `yaml:"enable_perf"`
187 KafkaEventTopic string `yaml:"kafka_event_topic"`
188 DmiServerAddress string `yaml:"dmi_server_address"`
189 BandwidthProfileFormat string `yaml:"bp_format"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100190}
Matteo Scandoloc1147092019-10-29 09:38:33 -0700191
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100192type BBRConfig struct {
193 Log string `yaml:"log"`
194 LogLevel string `yaml:"log_level"`
195 LogCaller bool `yaml:"log_caller"`
196}
197
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198type ServiceYaml struct {
199 Name string
200 CTag int `yaml:"c_tag"`
201 STag int `yaml:"s_tag"`
202 NeedsEapol bool `yaml:"needs_eapol"`
Matteo Scandolo8a574812021-05-20 15:18:53 -0700203 NeedsDhcp bool `yaml:"needs_dhcp"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 NeedsIgmp bool `yaml:"needs_igmp"`
Andrea Campanella29890452022-02-03 16:00:19 +0100205 NeedsPPPoE bool `yaml:"needs_pppoe"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 CTagAllocation string `yaml:"c_tag_allocation"`
207 STagAllocation string `yaml:"s_tag_allocation"`
208 TechnologyProfileID int `yaml:"tp_id"`
209 UniTagMatch int `yaml:"uni_tag_match"`
210 ConfigureMacAddress bool `yaml:"configure_mac_address"`
Andrea Campanella29890452022-02-03 16:00:19 +0100211 EnableMacLearning bool `yaml:"enable_mac_learning"`
Matteo Scandolo8d281372020-09-03 16:23:37 -0700212 UsPonCTagPriority uint8 `yaml:"us_pon_c_tag_priority"`
213 UsPonSTagPriority uint8 `yaml:"us_pon_s_tag_priority"`
214 DsPonCTagPriority uint8 `yaml:"ds_pon_c_tag_priority"`
215 DsPonSTagPriority uint8 `yaml:"ds_pon_s_tag_priority"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700216}
217type YamlServiceConfig struct {
218 Workflow string
219 Services []ServiceYaml `yaml:"services,flow"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100220}
221
Matteo Scandolo4a036262020-08-17 15:56:13 -0700222func (cfg *YamlServiceConfig) String() string {
223 str := fmt.Sprintf("[workflow: %s, Services: ", cfg.Workflow)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100224
Matteo Scandolo4a036262020-08-17 15:56:13 -0700225 for _, s := range cfg.Services {
226 str = fmt.Sprintf("%s[", str)
227 str = fmt.Sprintf("%sname=%s, c_tag=%d, s_tag=%d, ",
228 str, s.Name, s.CTag, s.STag)
229 str = fmt.Sprintf("%sc_tag_allocation=%s, s_tag_allocation=%s, ",
230 str, s.CTagAllocation, s.STagAllocation)
231 str = fmt.Sprintf("%sneeds_eapol=%t, needs_dhcp=%t, needs_igmp=%t",
Matteo Scandolo8a574812021-05-20 15:18:53 -0700232 str, s.NeedsEapol, s.NeedsDhcp, s.NeedsIgmp)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700233 str = fmt.Sprintf("%stp_id=%d, uni_tag_match=%d",
234 str, s.TechnologyProfileID, s.UniTagMatch)
235 str = fmt.Sprintf("%s]", str)
236 }
237 str = fmt.Sprintf("%s]", str)
238 return str
239}
240
241var (
Elia Battistonb7bea222022-02-18 16:25:00 +0100242 Config *GlobalConfig
243 Services []ServiceYaml
244 PonsConfig *PonPortsConfig
Matteo Scandolo4a036262020-08-17 15:56:13 -0700245)
246
247// Load the BBSim configuration. This is a combination of CLI parameters and YAML files
248// We proceed in this order:
249// - Read CLI parameters
250// - Using those we read the yaml files (config and services)
251// - we merge the configuration (CLI has priority over yaml files)
252func LoadConfig() {
253
254 Config = getDefaultOps()
255
256 cliConf := readCliParams()
257
258 yamlConf, err := loadBBSimConf(cliConf.BBSim.ConfigFile)
259
260 if err != nil {
261 log.WithFields(log.Fields{
262 "file": cliConf.BBSim.ConfigFile,
263 "err": err,
264 }).Fatal("Can't read config file")
265 }
266
267 // merging Yaml and Default Values
268 if err := mergo.Merge(Config, yamlConf, mergo.WithOverride); err != nil {
269 log.WithFields(log.Fields{
270 "err": err,
271 }).Fatal("Can't merge YAML and Config")
272 }
273
274 // merging CLI values on top of the yaml ones
275 if err := mergo.Merge(Config, cliConf, mergo.WithOverride); err != nil {
276 log.WithFields(log.Fields{
277 "err": err,
278 }).Fatal("Can't merge CLI and Config")
279 }
280
281 services, err := loadBBSimServices(Config.BBSim.ServiceConfigFile)
282
283 if err != nil {
284 log.WithFields(log.Fields{
285 "file": Config.BBSim.ServiceConfigFile,
286 "err": err,
287 }).Fatal("Can't read services file")
288 }
289
290 Services = services
291
Elia Battistonb7bea222022-02-18 16:25:00 +0100292 //A blank filename means we should fall back to bbsim defaults
293 if Config.BBSim.PonsConfigFile == "" {
294 PonsConfig, err = getDefaultPonsConfig()
295 if err != nil {
296 log.WithFields(log.Fields{
297 "err": err,
298 }).Fatal("Can't load Pon interfaces defaults.")
299 }
300 } else {
301 PonsConfig, err = loadBBSimPons(Config.BBSim.PonsConfigFile)
302
303 if err != nil {
304 log.WithFields(log.Fields{
305 "file": Config.BBSim.PonsConfigFile,
306 "err": err,
307 }).Fatal("Can't read services file")
308 }
309 }
310
311 if err := validatePonsConfig(PonsConfig); err != nil {
312 log.WithFields(log.Fields{
313 "file": Config.BBSim.PonsConfigFile,
314 "err": err,
315 }).Fatal("Invalid Pon interfaces configuration")
316 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700317}
318
319func readCliParams() *GlobalConfig {
320
Matteo Scandoloc11074d2020-09-14 14:59:24 -0700321 conf := getDefaultOps()
Matteo Scandolo4a036262020-08-17 15:56:13 -0700322
323 configFile := flag.String("config", conf.BBSim.ConfigFile, "Configuration file path")
324 servicesFile := flag.String("services", conf.BBSim.ServiceConfigFile, "Service Configuration file path")
Elia Battistonb7bea222022-02-18 16:25:00 +0100325 ponsFile := flag.String("pon_port_config_file", conf.BBSim.PonsConfigFile, "Pon Interfaces Configuration file path")
Matteo Scandolo94967142021-05-28 11:37:06 -0700326 sadisBpFormat := flag.String("bp_format", conf.BBSim.BandwidthProfileFormat, "Bandwidth profile format, 'mef' or 'ietf'")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700327
328 olt_id := flag.Int("olt_id", conf.Olt.ID, "OLT device ID")
329 nni := flag.Int("nni", int(conf.Olt.NniPorts), "Number of NNI ports per OLT device to be emulated")
Elia Battiston420c9092022-02-02 12:17:54 +0100330 nni_speed := flag.Uint("nni_speed", uint(conf.Olt.NniSpeed), "Reported speed of the NNI ports in Mbps")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700331 pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
332 onu := flag.Int("onu", int(conf.Olt.OnusPonPort), "Number of ONU devices per PON port to be emulated")
Elia Battistonac63b112022-01-12 18:40:49 +0100333 uni := flag.Int("uni", int(conf.Olt.UniPorts), "Number of Ethernet UNI Ports per ONU device to be emulated")
334 pots := flag.Int("pots", int(conf.Olt.PotsPorts), "Number of POTS UNI Ports per ONU device to be emulated")
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700335
Matteo Scandolo93566702020-09-30 15:19:27 -0700336 oltRebootDelay := flag.Int("oltRebootDelay", conf.Olt.OltRebootDelay, "Time that BBSim should before restarting after a reboot")
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000337 omci_response_rate := flag.Int("omci_response_rate", int(conf.Olt.OmciResponseRate), "Amount of OMCI messages to respond to")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700338
339 openolt_address := flag.String("openolt_address", conf.BBSim.OpenOltAddress, "IP address:port")
340 api_address := flag.String("api_address", conf.BBSim.ApiAddress, "IP address:port")
341 rest_api_address := flag.String("rest_api_address", conf.BBSim.RestApiAddress, "IP address:port")
amit.ghosh258d14c2020-10-02 15:13:38 +0200342 dmi_server_address := flag.String("dmi_server_address", conf.BBSim.DmiServerAddress, "IP address:port")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700343
344 profileCpu := flag.String("cpuprofile", "", "write cpu profile to file")
345
346 logLevel := flag.String("logLevel", conf.BBSim.LogLevel, "Set the log level (trace, debug, info, warn, error)")
347 logCaller := flag.Bool("logCaller", conf.BBSim.LogCaller, "Whether to print the caller filename or not")
348
349 delay := flag.Int("delay", conf.BBSim.Delay, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")
350
351 controlledActivation := flag.String("ca", conf.BBSim.ControlledActivation, "Set the mode for controlled activation of PON ports and ONUs")
352 enablePerf := flag.Bool("enableperf", conf.BBSim.EnablePerf, "Setting this flag will cause BBSim to not store data like traffic schedulers, flows of ONUs etc..")
353 enableEvents := flag.Bool("enableEvents", conf.BBSim.Events, "Enable sending BBSim events on configured kafka server")
354 kafkaAddress := flag.String("kafkaAddress", conf.BBSim.KafkaAddress, "IP:Port for kafka")
355 kafkaEventTopic := flag.String("kafkaEventTopic", conf.BBSim.KafkaEventTopic, "Ability to configure the topic on which BBSim publishes events on Kafka")
356 dhcpRetry := flag.Bool("dhcpRetry", conf.BBSim.DhcpRetry, "Set this flag if BBSim should retry DHCP upon failure until success")
357 authRetry := flag.Bool("authRetry", conf.BBSim.AuthRetry, "Set this flag if BBSim should retry EAPOL (Authentication) upon failure until success")
Matteo Scandolo93566702020-09-30 15:19:27 -0700358
Matteo Scandolo4a036262020-08-17 15:56:13 -0700359 flag.Parse()
360
361 conf.Olt.ID = int(*olt_id)
362 conf.Olt.NniPorts = uint32(*nni)
Elia Battiston420c9092022-02-02 12:17:54 +0100363 conf.Olt.NniSpeed = uint32(*nni_speed)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700364 conf.Olt.PonPorts = uint32(*pon)
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700365 conf.Olt.UniPorts = uint32(*uni)
Elia Battistonac63b112022-01-12 18:40:49 +0100366 conf.Olt.PotsPorts = uint32(*pots)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700367 conf.Olt.OnusPonPort = uint32(*onu)
Matteo Scandolo93566702020-09-30 15:19:27 -0700368 conf.Olt.OltRebootDelay = *oltRebootDelay
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000369 conf.Olt.OmciResponseRate = uint8(*omci_response_rate)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700370 conf.BBSim.ConfigFile = *configFile
371 conf.BBSim.ServiceConfigFile = *servicesFile
Elia Battistonb7bea222022-02-18 16:25:00 +0100372 conf.BBSim.PonsConfigFile = *ponsFile
Matteo Scandolo4a036262020-08-17 15:56:13 -0700373 conf.BBSim.CpuProfile = profileCpu
374 conf.BBSim.LogLevel = *logLevel
375 conf.BBSim.LogCaller = *logCaller
376 conf.BBSim.Delay = *delay
377 conf.BBSim.ControlledActivation = *controlledActivation
378 conf.BBSim.EnablePerf = *enablePerf
379 conf.BBSim.Events = *enableEvents
380 conf.BBSim.KafkaAddress = *kafkaAddress
381 conf.BBSim.OpenOltAddress = *openolt_address
382 conf.BBSim.ApiAddress = *api_address
383 conf.BBSim.RestApiAddress = *rest_api_address
384 conf.BBSim.KafkaEventTopic = *kafkaEventTopic
385 conf.BBSim.AuthRetry = *authRetry
386 conf.BBSim.DhcpRetry = *dhcpRetry
amit.ghosh258d14c2020-10-02 15:13:38 +0200387 conf.BBSim.DmiServerAddress = *dmi_server_address
Matteo Scandolo4a036262020-08-17 15:56:13 -0700388
389 // update device id if not set
390 if conf.Olt.DeviceId == "" {
391 conf.Olt.DeviceId = net.HardwareAddr{0xA, 0xA, 0xA, 0xA, 0xA, byte(conf.Olt.ID)}.String()
392 }
393
Matteo Scandolo94967142021-05-28 11:37:06 -0700394 // check that the BP format is valid
395 if (*sadisBpFormat != BP_FORMAT_MEF) && (*sadisBpFormat != BP_FORMAT_IETF) {
396 log.Fatalf("Invalid parameter 'bp_format', supported values are %s and %s, you provided %s", BP_FORMAT_MEF, BP_FORMAT_IETF, *sadisBpFormat)
397 }
398 conf.BBSim.BandwidthProfileFormat = *sadisBpFormat
399
Matteo Scandoloc11074d2020-09-14 14:59:24 -0700400 return conf
Matteo Scandolo4a036262020-08-17 15:56:13 -0700401}
402
403func getDefaultOps() *GlobalConfig {
404
405 c := &GlobalConfig{
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100406 BBSimConfig{
Elia Battistonb7bea222022-02-18 16:25:00 +0100407 ConfigFile: "configs/bbsim.yaml",
408 ServiceConfigFile: "configs/att-services.yaml",
409 // PonsConfigFile is left intentionally blank here
410 // to use the default values computed at runtime depending
411 // on the loaded Services
412 PonsConfigFile: "",
Matteo Scandolo94967142021-05-28 11:37:06 -0700413 LogLevel: "debug",
414 LogCaller: false,
415 Delay: 200,
416 OpenOltAddress: ":50060",
417 ApiAddress: ":50070",
418 RestApiAddress: ":50071",
419 LegacyApiAddress: ":50072",
420 LegacyRestApiAddress: ":50073",
421 SadisRestAddress: ":50074",
422 SadisServer: true,
423 KafkaAddress: ":9092",
424 Events: false,
425 ControlledActivation: "default",
426 EnablePerf: false,
427 KafkaEventTopic: "",
428 DhcpRetry: false,
429 AuthRetry: false,
430 DmiServerAddress: ":50075",
431 BandwidthProfileFormat: BP_FORMAT_MEF,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100432 },
433 OltConfig{
434 Vendor: "BBSim",
435 Model: "asfvolt16",
436 HardwareVersion: "emulated",
437 FirmwareVersion: "",
438 DeviceSerialNumber: "BBSM00000001",
439 PonPorts: 1,
440 NniPorts: 1,
Elia Battiston420c9092022-02-02 12:17:54 +0100441 NniSpeed: 10000, //Mbps
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100442 OnusPonPort: 1,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100443 ID: 0,
Matteo Scandolo93566702020-09-30 15:19:27 -0700444 OltRebootDelay: 60,
Pragya Arya996a0892020-03-09 21:47:52 +0530445 PortStatsInterval: 20,
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000446 OmciResponseRate: 10,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700447 UniPorts: 4,
Elia Battistonac63b112022-01-12 18:40:49 +0100448 PotsPorts: 0,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100449 },
450 BBRConfig{
451 LogLevel: "debug",
452 LogCaller: false,
453 },
454 }
455 return c
456}
457
Elia Battistonb7bea222022-02-18 16:25:00 +0100458func getDefaultPonsConfig() (*PonPortsConfig, error) {
459
460 if Config == nil {
461 return nil, fmt.Errorf("Config is nil")
462 }
463 if Services == nil {
464 return nil, fmt.Errorf("Services is nil")
465 }
466
467 //The default should replicate the old way bbsim used to compute resource ranges based on the configuration
468 // 1 allocId per Service * UNI
469 allocIdPerOnu := uint32(Config.Olt.UniPorts * uint32(len(Services)))
470 return &PonPortsConfig{
471 Number: Config.Olt.PonPorts,
472 Ranges: []PonRangeConfig{
473 {
474 PonRange: IdRange{0, Config.Olt.PonPorts - 1},
475 Technology: XGSPON.String(),
476 // we need one ONU ID available per ONU, but the smaller the range the smaller the pool created in the openolt adapter
477 OnuRange: IdRange{defaultOnuIdStart, defaultOnuIdStart + (Config.Olt.OnusPonPort - 1)},
478 // 1 allocId per Service * UNI * ONU
479 AllocIdRange: IdRange{defaultAllocIdStart, defaultAllocIdStart + (Config.Olt.OnusPonPort * allocIdPerOnu)},
480 // up to 8 gemport-id per tcont/alloc-id
481 GemportRange: IdRange{defaultGemportIdStart, defaultGemportIdStart + Config.Olt.OnusPonPort*allocIdPerOnu*defaultGemPortIdPerAllocId},
482 },
483 },
484 }, nil
485}
486
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100487// LoadBBSimConf loads the BBSim configuration from a YAML file
Matteo Scandolo4a036262020-08-17 15:56:13 -0700488func loadBBSimConf(filename string) (*GlobalConfig, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100489 yamlConfig := getDefaultOps()
490
491 yamlFile, err := ioutil.ReadFile(filename)
492 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700493 log.WithFields(log.Fields{
494 "err": err,
495 "filename": filename,
496 }).Error("Cannot load BBSim configuration file. Using defaults.")
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100497 return yamlConfig, nil
498 }
499
500 err = yaml.Unmarshal(yamlFile, yamlConfig)
501 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700502 return nil, err
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100503 }
504
505 return yamlConfig, nil
506}
507
Elia Battistonb7bea222022-02-18 16:25:00 +0100508// loadBBSimPons loads the configuration of PON interfaces from a YAML file
509func loadBBSimPons(filename string) (*PonPortsConfig, error) {
510 yamlPonsConfig, err := getDefaultPonsConfig()
511 if err != nil {
512 log.WithFields(log.Fields{
513 "err": err,
514 }).Error("Can't load Pon interfaces defaults.")
515 return nil, err
516 }
517
518 yamlFile, err := ioutil.ReadFile(filename)
519 if err != nil {
520 log.WithFields(log.Fields{
521 "err": err,
522 "filename": filename,
523 }).Error("Cannot load Pon interfaces configuration file. Using defaults.")
524 return yamlPonsConfig, nil
525 }
526
527 err = yaml.Unmarshal(yamlFile, yamlPonsConfig)
528 if err != nil {
529 return nil, err
530 }
531
532 return yamlPonsConfig, nil
533}
534
535// validatePonsConfig checks if the configuration to use for the definition of Pon interfaces is valid
536func validatePonsConfig(pons *PonPortsConfig) error {
537
538 if pons.Number == 0 {
539 return fmt.Errorf("no-pon-ports")
540 }
541
542 definedPorts := make([]int, pons.Number)
543
544 for rIndex, resRange := range pons.Ranges {
545 if _, err := PonTechnologyFromString(resRange.Technology); err != nil {
546 return err
547 }
548
549 if resRange.PonRange.EndId < resRange.PonRange.StartId {
550 return fmt.Errorf("invalid-pon-ports-limits-in-range-%d", rIndex)
551 }
552
553 //Keep track of the defined pons
554 for p := resRange.PonRange.StartId; p <= resRange.PonRange.EndId; p++ {
555 if p > uint32(len(definedPorts)-1) {
556 return fmt.Errorf("pon-port-%d-in-range-%d-but-max-is-%d", p, rIndex, pons.Number-1)
557 }
558 definedPorts[p]++
559
560 if definedPorts[p] > 1 {
561 return fmt.Errorf("pon-port-%d-has-duplicate-definition-in-range-%d", p, rIndex)
562 }
563 }
564
565 if resRange.OnuRange.EndId < resRange.OnuRange.StartId {
566 return fmt.Errorf("invalid-onus-limits-in-range-%d", rIndex)
567 }
568 if resRange.AllocIdRange.EndId < resRange.AllocIdRange.StartId {
569 return fmt.Errorf("invalid-allocid-limits-in-range-%d", rIndex)
570 }
571 if resRange.GemportRange.EndId < resRange.GemportRange.StartId {
572 return fmt.Errorf("invalid-gemport-limits-in-range-%d", rIndex)
573 }
574 }
575
576 //Check if the ranges define all the pons
577 for i, num := range definedPorts {
578 if num < 1 {
579 return fmt.Errorf("pon-port-%d-is-not-defined-in-ranges", i)
580 }
581 }
582
583 return nil
584}
585
Matteo Scandolo4a036262020-08-17 15:56:13 -0700586// LoadBBSimServices parses a file describing the services that need to be created for each UNI
587func loadBBSimServices(filename string) ([]ServiceYaml, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100588
Matteo Scandolo4a036262020-08-17 15:56:13 -0700589 yamlServiceCfg := YamlServiceConfig{}
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100590
Matteo Scandolo4a036262020-08-17 15:56:13 -0700591 yamlFile, err := ioutil.ReadFile(filename)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700592 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700593 return nil, err
Matteo Scandolof65e6872020-04-15 15:18:43 -0700594 }
595
Matteo Scandolo4a036262020-08-17 15:56:13 -0700596 err = yaml.Unmarshal([]byte(yamlFile), &yamlServiceCfg)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700597 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700598 return nil, err
Matteo Scandolof65e6872020-04-15 15:18:43 -0700599 }
600
Matteo Scandolo4a036262020-08-17 15:56:13 -0700601 for _, service := range yamlServiceCfg.Services {
602
603 if service.CTagAllocation == "" || service.STagAllocation == "" {
604 log.Fatal("c_tag_allocation and s_tag_allocation are mandatory fields")
605 }
606
607 if _, err := tagAllocationFromString(string(service.CTagAllocation)); err != nil {
608 log.WithFields(log.Fields{
609 "err": err,
610 }).Fatal("c_tag_allocation is not valid")
611 }
Matteo Scandolof65e6872020-04-15 15:18:43 -0700612 }
613
Matteo Scandolo4a036262020-08-17 15:56:13 -0700614 log.WithFields(log.Fields{
615 "services": yamlServiceCfg.String(),
616 }).Debug("BBSim services description correctly loaded")
617 return yamlServiceCfg.Services, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700618}
619
Matteo Scandolo4a036262020-08-17 15:56:13 -0700620// This is only used by BBR
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700621func GetBBROpts() BBRCliOptions {
622
623 bbsimIp := flag.String("bbsimIp", "127.0.0.1", "BBSim IP")
624 bbsimPort := flag.String("bbsimPort", "50060", "BBSim Port")
625 bbsimApiPort := flag.String("bbsimApiPort", "50070", "BBSim API Port")
Matteo Scandolof5c537e2019-10-28 16:45:57 -0700626 logFile := flag.String("logfile", "", "Log to a file")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700627
Matteo Scandoloc11074d2020-09-14 14:59:24 -0700628 LoadConfig()
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700629
630 bbrOptions := BBRCliOptions{
Matteo Scandolo4a036262020-08-17 15:56:13 -0700631 Config,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700632 *bbsimIp,
633 *bbsimPort,
634 *bbsimApiPort,
Matteo Scandolof5c537e2019-10-28 16:45:57 -0700635 *logFile,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700636 }
637
638 return bbrOptions
639}