blob: 3f160587bd58174b82e11549a6ef2f7a8dad9e8b [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"`
Andrea Campanella6f5f3552022-03-10 17:14:25 +010097 NniDhcpTrapVid uint32 `yaml:"nni_dhcp_trap_vid"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010098}
Matteo Scandolo40e067f2019-10-16 16:59:41 -070099
Elia Battistonb7bea222022-02-18 16:25:00 +0100100type PonPortsConfig struct {
101 Number uint32 `yaml:"num_pon_ports"`
102 Ranges []PonRangeConfig `yaml:"ranges"`
103}
104
105type IdRange struct {
106 StartId uint32 `yaml:"start"`
107 EndId uint32 `yaml:"end"`
108}
109
110type PonTechnology int
111
112var ponTechnologyValues = []string{
113 "GPON", "XGS-PON",
114}
115
116func (t PonTechnology) String() string {
117 return ponTechnologyValues[t]
118}
119
120const (
121 GPON PonTechnology = iota
122 XGSPON
123)
124
125func PonTechnologyFromString(s string) (PonTechnology, error) {
126 for i, val := range ponTechnologyValues {
127 if val == s {
128 return PonTechnology(i), nil
129 }
130 }
131 log.WithFields(log.Fields{
132 "ValidValues": strings.Join(ponTechnologyValues[:], ", "),
133 }).Errorf("%s-is-not-a-valid-pon-technology", s)
134 return -1, fmt.Errorf("%s-is-not-a-valid-pon-technology", s)
135}
136
137//Constants for default allocation ranges
138const (
139 defaultOnuIdStart = 1
140 defaultAllocIdStart = 1024
141 defaultGemPortIdPerAllocId = 8
142 defaultGemportIdStart = 1024
143)
144
145type PonRangeConfig struct {
146 PonRange IdRange `yaml:"pon_id_range"`
147 Technology string `yaml:"tech"`
148 OnuRange IdRange `yaml:"onu_id_range"`
149 AllocIdRange IdRange `yaml:"alloc_id_range"`
150 GemportRange IdRange `yaml:"gemport_id_range"`
151}
152
153func GetPonConfigById(id uint32) (*PonRangeConfig, error) {
154 if PonsConfig == nil {
155 return nil, fmt.Errorf("pons-config-nil")
156 }
157
158 for _, r := range PonsConfig.Ranges {
159 if id >= r.PonRange.StartId && id <= r.PonRange.EndId {
160 return &r, nil
161 }
162 }
163
164 return nil, fmt.Errorf("pon-config-for-id-%d-not-found", id)
165}
166
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100167type BBSimConfig struct {
Matteo Scandolocfedba42022-02-14 16:08:54 -0800168 ConfigFile string
169 ServiceConfigFile string
170 PonsConfigFile string
171 DhcpRetry bool `yaml:"dhcp_retry"`
172 AuthRetry bool `yaml:"auth_retry"`
173 LogLevel string `yaml:"log_level"`
174 LogCaller bool `yaml:"log_caller"`
175 Delay int `yaml:"delay"`
176 CpuProfile *string `yaml:"cpu_profile"`
177 OpenOltAddress string `yaml:"openolt_address"`
178 ApiAddress string `yaml:"api_address"`
179 RestApiAddress string `yaml:"rest_api_address"`
180 LegacyApiAddress string `yaml:"legacy_api_address"`
181 LegacyRestApiAddress string `yaml:"legacy_rest_api_address"`
182 SadisRestAddress string `yaml:"sadis_rest_address"`
183 SadisServer bool `yaml:"sadis_server"`
184 KafkaAddress string `yaml:"kafka_address"`
185 Events bool `yaml:"enable_events"`
186 ControlledActivation string `yaml:"controlled_activation"`
187 EnablePerf bool `yaml:"enable_perf"`
188 KafkaEventTopic string `yaml:"kafka_event_topic"`
189 DmiServerAddress string `yaml:"dmi_server_address"`
190 BandwidthProfileFormat string `yaml:"bp_format"`
Matteo Scandolo7011fc92022-03-16 15:50:15 -0700191 InjectOmciUnknownMe bool `yaml:"inject_omci_unknown_me"`
Matteo Scandolocfedba42022-02-14 16:08:54 -0800192 InjectOmciUnknownAttributes bool `yaml:"inject_omci_unknown_attributes"`
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000193 OmccVersion int `yaml:"omcc_version"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100194}
Matteo Scandoloc1147092019-10-29 09:38:33 -0700195
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100196type BBRConfig struct {
197 Log string `yaml:"log"`
198 LogLevel string `yaml:"log_level"`
199 LogCaller bool `yaml:"log_caller"`
200}
201
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202type ServiceYaml struct {
203 Name string
204 CTag int `yaml:"c_tag"`
205 STag int `yaml:"s_tag"`
206 NeedsEapol bool `yaml:"needs_eapol"`
Matteo Scandolo8a574812021-05-20 15:18:53 -0700207 NeedsDhcp bool `yaml:"needs_dhcp"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700208 NeedsIgmp bool `yaml:"needs_igmp"`
Andrea Campanella29890452022-02-03 16:00:19 +0100209 NeedsPPPoE bool `yaml:"needs_pppoe"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700210 CTagAllocation string `yaml:"c_tag_allocation"`
211 STagAllocation string `yaml:"s_tag_allocation"`
212 TechnologyProfileID int `yaml:"tp_id"`
213 UniTagMatch int `yaml:"uni_tag_match"`
214 ConfigureMacAddress bool `yaml:"configure_mac_address"`
Andrea Campanella29890452022-02-03 16:00:19 +0100215 EnableMacLearning bool `yaml:"enable_mac_learning"`
Matteo Scandolo8d281372020-09-03 16:23:37 -0700216 UsPonCTagPriority uint8 `yaml:"us_pon_c_tag_priority"`
217 UsPonSTagPriority uint8 `yaml:"us_pon_s_tag_priority"`
218 DsPonCTagPriority uint8 `yaml:"ds_pon_c_tag_priority"`
219 DsPonSTagPriority uint8 `yaml:"ds_pon_s_tag_priority"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700220}
221type YamlServiceConfig struct {
222 Workflow string
223 Services []ServiceYaml `yaml:"services,flow"`
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100224}
225
Matteo Scandolo4a036262020-08-17 15:56:13 -0700226func (cfg *YamlServiceConfig) String() string {
227 str := fmt.Sprintf("[workflow: %s, Services: ", cfg.Workflow)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100228
Matteo Scandolo4a036262020-08-17 15:56:13 -0700229 for _, s := range cfg.Services {
230 str = fmt.Sprintf("%s[", str)
231 str = fmt.Sprintf("%sname=%s, c_tag=%d, s_tag=%d, ",
232 str, s.Name, s.CTag, s.STag)
233 str = fmt.Sprintf("%sc_tag_allocation=%s, s_tag_allocation=%s, ",
234 str, s.CTagAllocation, s.STagAllocation)
235 str = fmt.Sprintf("%sneeds_eapol=%t, needs_dhcp=%t, needs_igmp=%t",
Matteo Scandolo8a574812021-05-20 15:18:53 -0700236 str, s.NeedsEapol, s.NeedsDhcp, s.NeedsIgmp)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700237 str = fmt.Sprintf("%stp_id=%d, uni_tag_match=%d",
238 str, s.TechnologyProfileID, s.UniTagMatch)
239 str = fmt.Sprintf("%s]", str)
240 }
241 str = fmt.Sprintf("%s]", str)
242 return str
243}
244
245var (
Elia Battistonb7bea222022-02-18 16:25:00 +0100246 Config *GlobalConfig
247 Services []ServiceYaml
248 PonsConfig *PonPortsConfig
Matteo Scandolo4a036262020-08-17 15:56:13 -0700249)
250
251// Load the BBSim configuration. This is a combination of CLI parameters and YAML files
252// We proceed in this order:
253// - Read CLI parameters
254// - Using those we read the yaml files (config and services)
255// - we merge the configuration (CLI has priority over yaml files)
256func LoadConfig() {
257
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000258 Config = GetDefaultOps()
Matteo Scandolo4a036262020-08-17 15:56:13 -0700259
260 cliConf := readCliParams()
261
262 yamlConf, err := loadBBSimConf(cliConf.BBSim.ConfigFile)
263
264 if err != nil {
265 log.WithFields(log.Fields{
266 "file": cliConf.BBSim.ConfigFile,
267 "err": err,
268 }).Fatal("Can't read config file")
269 }
270
271 // merging Yaml and Default Values
272 if err := mergo.Merge(Config, yamlConf, mergo.WithOverride); err != nil {
273 log.WithFields(log.Fields{
274 "err": err,
275 }).Fatal("Can't merge YAML and Config")
276 }
277
278 // merging CLI values on top of the yaml ones
279 if err := mergo.Merge(Config, cliConf, mergo.WithOverride); err != nil {
280 log.WithFields(log.Fields{
281 "err": err,
282 }).Fatal("Can't merge CLI and Config")
283 }
284
285 services, err := loadBBSimServices(Config.BBSim.ServiceConfigFile)
286
287 if err != nil {
288 log.WithFields(log.Fields{
289 "file": Config.BBSim.ServiceConfigFile,
290 "err": err,
291 }).Fatal("Can't read services file")
292 }
293
294 Services = services
295
Elia Battistonb7bea222022-02-18 16:25:00 +0100296 //A blank filename means we should fall back to bbsim defaults
297 if Config.BBSim.PonsConfigFile == "" {
298 PonsConfig, err = getDefaultPonsConfig()
299 if err != nil {
300 log.WithFields(log.Fields{
301 "err": err,
302 }).Fatal("Can't load Pon interfaces defaults.")
303 }
304 } else {
305 PonsConfig, err = loadBBSimPons(Config.BBSim.PonsConfigFile)
306
307 if err != nil {
308 log.WithFields(log.Fields{
309 "file": Config.BBSim.PonsConfigFile,
310 "err": err,
311 }).Fatal("Can't read services file")
312 }
313 }
314
315 if err := validatePonsConfig(PonsConfig); err != nil {
316 log.WithFields(log.Fields{
317 "file": Config.BBSim.PonsConfigFile,
318 "err": err,
319 }).Fatal("Invalid Pon interfaces configuration")
320 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700321}
322
323func readCliParams() *GlobalConfig {
324
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000325 conf := GetDefaultOps()
Matteo Scandolo4a036262020-08-17 15:56:13 -0700326
327 configFile := flag.String("config", conf.BBSim.ConfigFile, "Configuration file path")
328 servicesFile := flag.String("services", conf.BBSim.ServiceConfigFile, "Service Configuration file path")
Elia Battistonb7bea222022-02-18 16:25:00 +0100329 ponsFile := flag.String("pon_port_config_file", conf.BBSim.PonsConfigFile, "Pon Interfaces Configuration file path")
Matteo Scandolo94967142021-05-28 11:37:06 -0700330 sadisBpFormat := flag.String("bp_format", conf.BBSim.BandwidthProfileFormat, "Bandwidth profile format, 'mef' or 'ietf'")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700331
332 olt_id := flag.Int("olt_id", conf.Olt.ID, "OLT device ID")
333 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 +0100334 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 -0700335 pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
336 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 +0100337 uni := flag.Int("uni", int(conf.Olt.UniPorts), "Number of Ethernet UNI Ports per ONU device to be emulated")
338 pots := flag.Int("pots", int(conf.Olt.PotsPorts), "Number of POTS UNI Ports per ONU device to be emulated")
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100339 NniDchpTrapVid := flag.Int("nni_dhcp_trap_vid", int(conf.Olt.NniDhcpTrapVid), "Vlan to trap the DHCP packets on")
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700340
Matteo Scandolo93566702020-09-30 15:19:27 -0700341 oltRebootDelay := flag.Int("oltRebootDelay", conf.Olt.OltRebootDelay, "Time that BBSim should before restarting after a reboot")
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000342 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 -0700343
344 openolt_address := flag.String("openolt_address", conf.BBSim.OpenOltAddress, "IP address:port")
345 api_address := flag.String("api_address", conf.BBSim.ApiAddress, "IP address:port")
346 rest_api_address := flag.String("rest_api_address", conf.BBSim.RestApiAddress, "IP address:port")
amit.ghosh258d14c2020-10-02 15:13:38 +0200347 dmi_server_address := flag.String("dmi_server_address", conf.BBSim.DmiServerAddress, "IP address:port")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700348
349 profileCpu := flag.String("cpuprofile", "", "write cpu profile to file")
350
351 logLevel := flag.String("logLevel", conf.BBSim.LogLevel, "Set the log level (trace, debug, info, warn, error)")
352 logCaller := flag.Bool("logCaller", conf.BBSim.LogCaller, "Whether to print the caller filename or not")
353
354 delay := flag.Int("delay", conf.BBSim.Delay, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")
355
356 controlledActivation := flag.String("ca", conf.BBSim.ControlledActivation, "Set the mode for controlled activation of PON ports and ONUs")
357 enablePerf := flag.Bool("enableperf", conf.BBSim.EnablePerf, "Setting this flag will cause BBSim to not store data like traffic schedulers, flows of ONUs etc..")
358 enableEvents := flag.Bool("enableEvents", conf.BBSim.Events, "Enable sending BBSim events on configured kafka server")
359 kafkaAddress := flag.String("kafkaAddress", conf.BBSim.KafkaAddress, "IP:Port for kafka")
360 kafkaEventTopic := flag.String("kafkaEventTopic", conf.BBSim.KafkaEventTopic, "Ability to configure the topic on which BBSim publishes events on Kafka")
361 dhcpRetry := flag.Bool("dhcpRetry", conf.BBSim.DhcpRetry, "Set this flag if BBSim should retry DHCP upon failure until success")
362 authRetry := flag.Bool("authRetry", conf.BBSim.AuthRetry, "Set this flag if BBSim should retry EAPOL (Authentication) upon failure until success")
Matteo Scandolo7011fc92022-03-16 15:50:15 -0700363 injectOmciUnknownMe := flag.Bool("injectOmciUnknownMe", conf.BBSim.InjectOmciUnknownMe, "Generate an extra MibDB packet with ClassID 37 (Intentionally left blank)")
364 injectOmciUnknownAttributes := flag.Bool("injectOmciUnknownAttributes", conf.BBSim.InjectOmciUnknownAttributes, "Modifies the ONU2-G MibDB packet to add Unknown Attributes")
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000365 omccVersion := flag.Int("omccVersion", conf.BBSim.OmccVersion, "Set OMCC version to be returned in OMCI response of ME Onu2G")
Matteo Scandolo93566702020-09-30 15:19:27 -0700366
Matteo Scandolo4a036262020-08-17 15:56:13 -0700367 flag.Parse()
368
369 conf.Olt.ID = int(*olt_id)
370 conf.Olt.NniPorts = uint32(*nni)
Elia Battiston420c9092022-02-02 12:17:54 +0100371 conf.Olt.NniSpeed = uint32(*nni_speed)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700372 conf.Olt.PonPorts = uint32(*pon)
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700373 conf.Olt.UniPorts = uint32(*uni)
Elia Battistonac63b112022-01-12 18:40:49 +0100374 conf.Olt.PotsPorts = uint32(*pots)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700375 conf.Olt.OnusPonPort = uint32(*onu)
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100376 conf.Olt.NniDhcpTrapVid = uint32(*NniDchpTrapVid)
Matteo Scandolo93566702020-09-30 15:19:27 -0700377 conf.Olt.OltRebootDelay = *oltRebootDelay
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000378 conf.Olt.OmciResponseRate = uint8(*omci_response_rate)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700379 conf.BBSim.ConfigFile = *configFile
380 conf.BBSim.ServiceConfigFile = *servicesFile
Elia Battistonb7bea222022-02-18 16:25:00 +0100381 conf.BBSim.PonsConfigFile = *ponsFile
Matteo Scandolo4a036262020-08-17 15:56:13 -0700382 conf.BBSim.CpuProfile = profileCpu
383 conf.BBSim.LogLevel = *logLevel
384 conf.BBSim.LogCaller = *logCaller
385 conf.BBSim.Delay = *delay
386 conf.BBSim.ControlledActivation = *controlledActivation
387 conf.BBSim.EnablePerf = *enablePerf
388 conf.BBSim.Events = *enableEvents
389 conf.BBSim.KafkaAddress = *kafkaAddress
390 conf.BBSim.OpenOltAddress = *openolt_address
391 conf.BBSim.ApiAddress = *api_address
392 conf.BBSim.RestApiAddress = *rest_api_address
393 conf.BBSim.KafkaEventTopic = *kafkaEventTopic
394 conf.BBSim.AuthRetry = *authRetry
395 conf.BBSim.DhcpRetry = *dhcpRetry
amit.ghosh258d14c2020-10-02 15:13:38 +0200396 conf.BBSim.DmiServerAddress = *dmi_server_address
Matteo Scandolo7011fc92022-03-16 15:50:15 -0700397 conf.BBSim.InjectOmciUnknownMe = *injectOmciUnknownMe
Matteo Scandolocfedba42022-02-14 16:08:54 -0800398 conf.BBSim.InjectOmciUnknownAttributes = *injectOmciUnknownAttributes
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000399 conf.BBSim.OmccVersion = *omccVersion
Matteo Scandolo4a036262020-08-17 15:56:13 -0700400
401 // update device id if not set
402 if conf.Olt.DeviceId == "" {
403 conf.Olt.DeviceId = net.HardwareAddr{0xA, 0xA, 0xA, 0xA, 0xA, byte(conf.Olt.ID)}.String()
404 }
405
Matteo Scandolo94967142021-05-28 11:37:06 -0700406 // check that the BP format is valid
407 if (*sadisBpFormat != BP_FORMAT_MEF) && (*sadisBpFormat != BP_FORMAT_IETF) {
408 log.Fatalf("Invalid parameter 'bp_format', supported values are %s and %s, you provided %s", BP_FORMAT_MEF, BP_FORMAT_IETF, *sadisBpFormat)
409 }
410 conf.BBSim.BandwidthProfileFormat = *sadisBpFormat
411
Matteo Scandoloc11074d2020-09-14 14:59:24 -0700412 return conf
Matteo Scandolo4a036262020-08-17 15:56:13 -0700413}
414
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000415func GetDefaultOps() *GlobalConfig {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700416
417 c := &GlobalConfig{
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100418 BBSimConfig{
Elia Battistonb7bea222022-02-18 16:25:00 +0100419 ConfigFile: "configs/bbsim.yaml",
420 ServiceConfigFile: "configs/att-services.yaml",
421 // PonsConfigFile is left intentionally blank here
422 // to use the default values computed at runtime depending
423 // on the loaded Services
Matteo Scandolocfedba42022-02-14 16:08:54 -0800424 PonsConfigFile: "",
425 LogLevel: "debug",
426 LogCaller: false,
427 Delay: 200,
428 OpenOltAddress: ":50060",
429 ApiAddress: ":50070",
430 RestApiAddress: ":50071",
431 LegacyApiAddress: ":50072",
432 LegacyRestApiAddress: ":50073",
433 SadisRestAddress: ":50074",
434 SadisServer: true,
435 KafkaAddress: ":9092",
436 Events: false,
437 ControlledActivation: "default",
438 EnablePerf: false,
439 KafkaEventTopic: "",
440 DhcpRetry: false,
441 AuthRetry: false,
442 DmiServerAddress: ":50075",
443 BandwidthProfileFormat: BP_FORMAT_MEF,
Matteo Scandolo7011fc92022-03-16 15:50:15 -0700444 InjectOmciUnknownMe: false,
Matteo Scandolocfedba42022-02-14 16:08:54 -0800445 InjectOmciUnknownAttributes: false,
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000446 OmccVersion: 0xA3,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100447 },
448 OltConfig{
449 Vendor: "BBSim",
450 Model: "asfvolt16",
451 HardwareVersion: "emulated",
452 FirmwareVersion: "",
453 DeviceSerialNumber: "BBSM00000001",
454 PonPorts: 1,
455 NniPorts: 1,
Elia Battiston420c9092022-02-02 12:17:54 +0100456 NniSpeed: 10000, //Mbps
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100457 OnusPonPort: 1,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100458 ID: 0,
Matteo Scandolo93566702020-09-30 15:19:27 -0700459 OltRebootDelay: 60,
Pragya Arya996a0892020-03-09 21:47:52 +0530460 PortStatsInterval: 20,
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000461 OmciResponseRate: 10,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700462 UniPorts: 4,
Elia Battistonac63b112022-01-12 18:40:49 +0100463 PotsPorts: 0,
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100464 NniDhcpTrapVid: 0,
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100465 },
466 BBRConfig{
467 LogLevel: "debug",
468 LogCaller: false,
469 },
470 }
471 return c
472}
473
Elia Battistonb7bea222022-02-18 16:25:00 +0100474func getDefaultPonsConfig() (*PonPortsConfig, error) {
475
476 if Config == nil {
477 return nil, fmt.Errorf("Config is nil")
478 }
479 if Services == nil {
480 return nil, fmt.Errorf("Services is nil")
481 }
482
483 //The default should replicate the old way bbsim used to compute resource ranges based on the configuration
484 // 1 allocId per Service * UNI
485 allocIdPerOnu := uint32(Config.Olt.UniPorts * uint32(len(Services)))
486 return &PonPortsConfig{
487 Number: Config.Olt.PonPorts,
488 Ranges: []PonRangeConfig{
489 {
490 PonRange: IdRange{0, Config.Olt.PonPorts - 1},
491 Technology: XGSPON.String(),
492 // we need one ONU ID available per ONU, but the smaller the range the smaller the pool created in the openolt adapter
493 OnuRange: IdRange{defaultOnuIdStart, defaultOnuIdStart + (Config.Olt.OnusPonPort - 1)},
494 // 1 allocId per Service * UNI * ONU
495 AllocIdRange: IdRange{defaultAllocIdStart, defaultAllocIdStart + (Config.Olt.OnusPonPort * allocIdPerOnu)},
496 // up to 8 gemport-id per tcont/alloc-id
497 GemportRange: IdRange{defaultGemportIdStart, defaultGemportIdStart + Config.Olt.OnusPonPort*allocIdPerOnu*defaultGemPortIdPerAllocId},
498 },
499 },
500 }, nil
501}
502
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100503// LoadBBSimConf loads the BBSim configuration from a YAML file
Matteo Scandolo4a036262020-08-17 15:56:13 -0700504func loadBBSimConf(filename string) (*GlobalConfig, error) {
Holger Hildebrandtb9a3dd02022-05-12 08:20:41 +0000505 yamlConfig := GetDefaultOps()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100506
507 yamlFile, err := ioutil.ReadFile(filename)
508 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700509 log.WithFields(log.Fields{
510 "err": err,
511 "filename": filename,
512 }).Error("Cannot load BBSim configuration file. Using defaults.")
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100513 return yamlConfig, nil
514 }
515
516 err = yaml.Unmarshal(yamlFile, yamlConfig)
517 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700518 return nil, err
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100519 }
520
521 return yamlConfig, nil
522}
523
Elia Battistonb7bea222022-02-18 16:25:00 +0100524// loadBBSimPons loads the configuration of PON interfaces from a YAML file
525func loadBBSimPons(filename string) (*PonPortsConfig, error) {
526 yamlPonsConfig, err := getDefaultPonsConfig()
527 if err != nil {
528 log.WithFields(log.Fields{
529 "err": err,
530 }).Error("Can't load Pon interfaces defaults.")
531 return nil, err
532 }
533
534 yamlFile, err := ioutil.ReadFile(filename)
535 if err != nil {
536 log.WithFields(log.Fields{
537 "err": err,
538 "filename": filename,
539 }).Error("Cannot load Pon interfaces configuration file. Using defaults.")
540 return yamlPonsConfig, nil
541 }
542
543 err = yaml.Unmarshal(yamlFile, yamlPonsConfig)
544 if err != nil {
545 return nil, err
546 }
547
548 return yamlPonsConfig, nil
549}
550
551// validatePonsConfig checks if the configuration to use for the definition of Pon interfaces is valid
552func validatePonsConfig(pons *PonPortsConfig) error {
553
554 if pons.Number == 0 {
555 return fmt.Errorf("no-pon-ports")
556 }
557
558 definedPorts := make([]int, pons.Number)
559
560 for rIndex, resRange := range pons.Ranges {
561 if _, err := PonTechnologyFromString(resRange.Technology); err != nil {
562 return err
563 }
564
565 if resRange.PonRange.EndId < resRange.PonRange.StartId {
566 return fmt.Errorf("invalid-pon-ports-limits-in-range-%d", rIndex)
567 }
568
569 //Keep track of the defined pons
570 for p := resRange.PonRange.StartId; p <= resRange.PonRange.EndId; p++ {
571 if p > uint32(len(definedPorts)-1) {
572 return fmt.Errorf("pon-port-%d-in-range-%d-but-max-is-%d", p, rIndex, pons.Number-1)
573 }
574 definedPorts[p]++
575
576 if definedPorts[p] > 1 {
577 return fmt.Errorf("pon-port-%d-has-duplicate-definition-in-range-%d", p, rIndex)
578 }
579 }
580
581 if resRange.OnuRange.EndId < resRange.OnuRange.StartId {
582 return fmt.Errorf("invalid-onus-limits-in-range-%d", rIndex)
583 }
584 if resRange.AllocIdRange.EndId < resRange.AllocIdRange.StartId {
585 return fmt.Errorf("invalid-allocid-limits-in-range-%d", rIndex)
586 }
587 if resRange.GemportRange.EndId < resRange.GemportRange.StartId {
588 return fmt.Errorf("invalid-gemport-limits-in-range-%d", rIndex)
589 }
590 }
591
592 //Check if the ranges define all the pons
593 for i, num := range definedPorts {
594 if num < 1 {
595 return fmt.Errorf("pon-port-%d-is-not-defined-in-ranges", i)
596 }
597 }
598
599 return nil
600}
601
Matteo Scandolo4a036262020-08-17 15:56:13 -0700602// LoadBBSimServices parses a file describing the services that need to be created for each UNI
603func loadBBSimServices(filename string) ([]ServiceYaml, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100604
Matteo Scandolo4a036262020-08-17 15:56:13 -0700605 yamlServiceCfg := YamlServiceConfig{}
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100606
Matteo Scandolo4a036262020-08-17 15:56:13 -0700607 yamlFile, err := ioutil.ReadFile(filename)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700608 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700609 return nil, err
Matteo Scandolof65e6872020-04-15 15:18:43 -0700610 }
611
Matteo Scandolo4a036262020-08-17 15:56:13 -0700612 err = yaml.Unmarshal([]byte(yamlFile), &yamlServiceCfg)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700613 if err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700614 return nil, err
Matteo Scandolof65e6872020-04-15 15:18:43 -0700615 }
616
Matteo Scandolo4a036262020-08-17 15:56:13 -0700617 for _, service := range yamlServiceCfg.Services {
618
619 if service.CTagAllocation == "" || service.STagAllocation == "" {
620 log.Fatal("c_tag_allocation and s_tag_allocation are mandatory fields")
621 }
622
623 if _, err := tagAllocationFromString(string(service.CTagAllocation)); err != nil {
624 log.WithFields(log.Fields{
625 "err": err,
626 }).Fatal("c_tag_allocation is not valid")
627 }
Matteo Scandolof65e6872020-04-15 15:18:43 -0700628 }
629
Matteo Scandolo4a036262020-08-17 15:56:13 -0700630 log.WithFields(log.Fields{
631 "services": yamlServiceCfg.String(),
632 }).Debug("BBSim services description correctly loaded")
633 return yamlServiceCfg.Services, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700634}
635
Matteo Scandolo4a036262020-08-17 15:56:13 -0700636// This is only used by BBR
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700637func GetBBROpts() BBRCliOptions {
638
639 bbsimIp := flag.String("bbsimIp", "127.0.0.1", "BBSim IP")
640 bbsimPort := flag.String("bbsimPort", "50060", "BBSim Port")
641 bbsimApiPort := flag.String("bbsimApiPort", "50070", "BBSim API Port")
Matteo Scandolof5c537e2019-10-28 16:45:57 -0700642 logFile := flag.String("logfile", "", "Log to a file")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700643
Matteo Scandoloc11074d2020-09-14 14:59:24 -0700644 LoadConfig()
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700645
646 bbrOptions := BBRCliOptions{
Matteo Scandolo4a036262020-08-17 15:56:13 -0700647 Config,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700648 *bbsimIp,
649 *bbsimPort,
650 *bbsimApiPort,
Matteo Scandolof5c537e2019-10-28 16:45:57 -0700651 *logFile,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700652 }
653
654 return bbrOptions
655}