SEBA-927 implemenation of controlled PON and ONU activation
updated controlledActivation to enum
Change-Id: I63ba732338f3df79f01a30703d9e6118d95bf8aa
diff --git a/cmd/bbr/bbr.go b/cmd/bbr/bbr.go
index 6ffcce6..4c83789 100644
--- a/cmd/bbr/bbr.go
+++ b/cmd/bbr/bbr.go
@@ -77,6 +77,7 @@
true, // this parameter is not important in the BBR Case
true, // this parameter is not important in the BBR Case
0, // this parameter does not matter in the BBR case
+ options.BBSim.ControlledActivation,
true,
)
oltMock := bbrdevices.OltMock{
diff --git a/cmd/bbsim/bbsim.go b/cmd/bbsim/bbsim.go
index 8ffb941..f2a1c37 100644
--- a/cmd/bbsim/bbsim.go
+++ b/cmd/bbsim/bbsim.go
@@ -146,14 +146,15 @@
}
log.WithFields(log.Fields{
- "OltID": options.Olt.ID,
- "NumNniPerOlt": options.Olt.NniPorts,
- "NumPonPerOlt": options.Olt.PonPorts,
- "NumOnuPerPon": options.Olt.OnusPonPort,
- "TotalOnus": options.Olt.PonPorts * options.Olt.OnusPonPort,
- "EnableAuth": options.BBSim.EnableAuth,
- "Dhcp": options.BBSim.EnableDhcp,
- "Delay": options.BBSim.Delay,
+ "OltID": options.Olt.ID,
+ "NumNniPerOlt": options.Olt.NniPorts,
+ "NumPonPerOlt": options.Olt.PonPorts,
+ "NumOnuPerPon": options.Olt.OnusPonPort,
+ "TotalOnus": options.Olt.PonPorts * options.Olt.OnusPonPort,
+ "EnableAuth": options.BBSim.EnableAuth,
+ "Dhcp": options.BBSim.EnableDhcp,
+ "Delay": options.BBSim.Delay,
+ "ControlledActivation": options.BBSim.ControlledActivation,
}).Info("BroadBand Simulator is on")
// control channels, they are only closed when the goroutine needs to be terminated
@@ -169,6 +170,7 @@
options.BBSim.EnableAuth,
options.BBSim.EnableDhcp,
options.BBSim.Delay,
+ options.BBSim.ControlledActivation,
false,
)
diff --git a/configs/bbsim.yaml b/configs/bbsim.yaml
index 4e087cc..77ffa62 100644
--- a/configs/bbsim.yaml
+++ b/configs/bbsim.yaml
@@ -9,6 +9,7 @@
openolt_address: ":50060"
api_address: ":50070"
rest_api_address: ":50071"
+ controlled_activation: "default"
# legacy_api_address: ":50072"
# legacy_rest_api_address: ":50073"
# sadis_rest_address: ":50073"
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index cec8803..7ec4ab3 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -136,13 +136,39 @@
olt := devices.GetOLT()
onu, err := olt.FindOnuBySn(req.SerialNumber)
-
if err != nil {
res.StatusCode = int32(codes.NotFound)
res.Message = err.Error()
return res, err
}
+ pon, _ := olt.GetPonById(onu.PonPortID)
+ if pon.InternalState.Current() != "enabled" {
+ err := fmt.Errorf("PON port %d not enabled", onu.PonPortID)
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot poweron ONU: %s", err.Error())
+
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+
+ if onu.InternalState.Current() == "created" {
+ if err := onu.InternalState.Event("initialize"); err != nil {
+ logger.WithFields(log.Fields{
+ "OnuId": onu.ID,
+ "IntfId": onu.PonPortID,
+ "OnuSn": onu.Sn(),
+ }).Errorf("Cannot poweron ONU: %s", err.Error())
+ res.StatusCode = int32(codes.FailedPrecondition)
+ res.Message = err.Error()
+ return res, err
+ }
+ }
+
if err := onu.InternalState.Event("discover"); err != nil {
logger.WithFields(log.Fields{
"OnuId": onu.ID,
diff --git a/internal/bbsim/devices/helpers.go b/internal/bbsim/devices/helpers.go
index 07cfe3a..5a27202 100644
--- a/internal/bbsim/devices/helpers.go
+++ b/internal/bbsim/devices/helpers.go
@@ -22,6 +22,24 @@
"strconv"
)
+type mode int
+
+// Constants for Controlled Activation modes
+const (
+ Default mode = iota
+ OnlyONU
+ OnlyPON
+ Both
+)
+
+// ControlledActivationModes maps string to int value of mode
+var ControlledActivationModes = map[string]mode{
+ "default": Default,
+ "only-onu": OnlyONU,
+ "only-pon": OnlyPON,
+ "both": Both,
+}
+
var newFSM = fsm.NewFSM
func getOperStateFSM(cb fsm.Callback) *fsm.FSM {
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index 016f148..f68ee9e 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -47,17 +47,17 @@
sync.Mutex
// BBSIM Internals
- ID int
- SerialNumber string
- NumNni int
- NumPon int
- NumOnuPerPon int
- InternalState *fsm.FSM
- channel chan Message
- nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
- nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
-
- Delay int
+ ID int
+ SerialNumber string
+ NumNni int
+ NumPon int
+ NumOnuPerPon int
+ InternalState *fsm.FSM
+ channel chan Message
+ nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
+ nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
+ Delay int
+ ControlledActivation mode
Pons []*PonPort
Nnis []*NniPort
@@ -78,7 +78,7 @@
return &olt
}
-func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, isMock bool) *OltDevice {
+func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, ca string, isMock bool) *OltDevice {
oltLogger.WithFields(log.Fields{
"ID": oltId,
"NumNni": nni,
@@ -100,6 +100,13 @@
Delay: delay,
}
+ if val, ok := ControlledActivationModes[ca]; ok {
+ olt.ControlledActivation = val
+ } else {
+ oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
+ olt.ControlledActivation = Default
+ }
+
// OLT State machine
// NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
olt.InternalState = fsm.NewFSM(
@@ -132,7 +139,7 @@
// create PON ports
availableCTag := cTagInit
for i := 0; i < pon; i++ {
- p := CreatePonPort(olt, uint32(i))
+ p := CreatePonPort(&olt, uint32(i))
// create ONU devices
for j := 0; j < onuPerPon; j++ {
@@ -209,22 +216,33 @@
// TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
time.Sleep(1 * time.Second) // we need to give the OLT the time to respond to all the pending gRPC request before stopping the server
if err := o.StopOltServer(); err != nil {
+ oltLogger.Errorf("Error in stopping OLT server")
return err
}
+ for _, pon := range olt.Pons {
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: DOWN,
+ PonPortID: pon.ID,
+ },
+ }
+ o.channel <- msg
+
+ for _, onu := range pon.Onus {
+ if onu.InternalState.Current() != "initialized" {
+ onu.InternalState.Event("disable")
+ }
+ }
+ }
+
// terminate the OLT's processOltMessages go routine
close(o.channel)
// terminate the OLT's processNniPacketIns go routine
go o.nniHandle.Close()
close(o.nniPktInChannel)
- for i := range olt.Pons {
- for _, onu := range olt.Pons[i].Onus {
- // NOTE while the olt is off, restore the ONU to the initial state
- onu.InternalState.SetState("created")
- }
- }
-
time.Sleep(time.Duration(rebootDelay) * time.Second)
if err := o.InternalState.Event("initialize"); err != nil {
@@ -277,6 +295,7 @@
// Enable implements the OpenOLT EnableIndicationServer functionality
func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
oltLogger.Debug("Enable OLT called")
+ rebootFlag := false
// If enabled has already been called then an enabled context has
// been created. If this is the case then we want to cancel all the
@@ -285,6 +304,7 @@
o.Lock()
if o.enableContext != nil && o.enableContextCancel != nil {
o.enableContextCancel()
+ rebootFlag = true
}
o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
o.Unlock()
@@ -321,25 +341,35 @@
go o.processOmciMessages(o.enableContext, stream, &wg)
- // send PON Port indications
- for i, pon := range o.Pons {
- msg := Message{
- Type: PonIndication,
- Data: PonIndicationMessage{
- OperState: UP,
- PonPortID: pon.ID,
- },
- }
- o.channel <- msg
-
- for _, onu := range o.Pons[i].Onus {
- if err := onu.InternalState.Event("initialize"); err != nil {
- log.Errorf("Error initializing ONU: %v", err)
- continue
+ if rebootFlag == true {
+ for _, pon := range o.Pons {
+ if pon.InternalState.Current() == "disabled" {
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: UP,
+ PonPortID: pon.ID,
+ },
+ }
+ o.channel <- msg
}
- if err := onu.InternalState.Event("discover"); err != nil {
- log.Errorf("Error discover ONU: %v", err)
- return err
+ }
+ } else {
+
+ // 1. controlledActivation == Default: Send both PON and ONUs indications
+ // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
+
+ if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
+ // send PON Port indications
+ for _, pon := range o.Pons {
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: UP,
+ PonPortID: pon.ID,
+ },
+ }
+ o.channel <- msg
}
}
}
@@ -468,25 +498,11 @@
}).Debug("Sent Indication_IntfOperInd for NNI")
}
-func (o *OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
- pon, _ := o.GetPonById(msg.PonPortID)
- if msg.OperState == UP {
- if err := pon.OperState.Event("enable"); err != nil {
- log.WithFields(log.Fields{
- "Type": pon.Type,
- "IntfId": pon.ID,
- "OperState": pon.OperState.Current(),
- }).Errorf("Can't move PON Port to enable state: %v", err)
- }
- } else if msg.OperState == DOWN {
- if err := pon.OperState.Event("disable"); err != nil {
- log.WithFields(log.Fields{
- "Type": pon.Type,
- "IntfId": pon.ID,
- "OperState": pon.OperState.Current(),
- }).Errorf("Can't move PON Port to disable state: %v", err)
- }
- }
+func (o *OltDevice) sendPonIndication(ponPortID uint32) {
+
+ stream := *o.OpenoltStream
+ pon, _ := o.GetPonById(ponPortID)
+ // Send IntfIndication for PON port
discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
IntfId: pon.ID,
OperState: pon.OperState.Current(),
@@ -502,6 +518,7 @@
"OperState": pon.OperState.Current(),
}).Debug("Sent Indication_IntfInd")
+ // Send IntfOperIndication for PON port
operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Type: pon.Type,
IntfId: pon.ID,
@@ -561,7 +578,14 @@
o.sendNniIndication(msg, stream)
case PonIndication:
msg, _ := message.Data.(PonIndicationMessage)
- o.sendPonIndication(msg, stream)
+ pon, _ := o.GetPonById(msg.PonPortID)
+ if msg.OperState == UP {
+ pon.OperState.Event("enable")
+ pon.InternalState.Event("enable")
+ } else if msg.OperState == DOWN {
+ pon.OperState.Event("disable")
+ pon.InternalState.Event("disable")
+ }
default:
oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
}
@@ -645,26 +669,6 @@
}).Warn("Stopped handling NNI Channel")
}
-func (o *OltDevice) handleReenableOlt() {
- // enable OLT
- oltMsg := Message{
- Type: OltIndication,
- Data: OltIndicationMessage{
- OperState: UP,
- },
- }
- o.channel <- oltMsg
-
- for i := range olt.Pons {
- for _, onu := range olt.Pons[i].Onus {
- if err := onu.InternalState.Event("discover"); err != nil {
- log.Errorf("Error discover ONU: %v", err)
- }
- }
- }
-
-}
-
// returns an ONU with a given Serial Number
func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
// TODO this function can be a performance bottleneck when we have many ONUs,
@@ -788,16 +792,17 @@
}).Info("Disabling OLT")
for _, pon := range o.Pons {
- // disable PONs
- msg := Message{
- Type: PonIndication,
- Data: PonIndicationMessage{
- OperState: DOWN,
- PonPortID: pon.ID,
- },
+ if pon.InternalState.Current() == "enabled" {
+ // disable PONs
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: DOWN,
+ PonPortID: pon.ID,
+ },
+ }
+ o.channel <- msg
}
-
- o.channel <- msg
}
// Note that we are not disabling the NNI as the real OLT does not.
@@ -825,8 +830,18 @@
return nil
}
-func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
- oltLogger.Error("EnablePonIf not implemented")
+func (o OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
+ oltLogger.Errorf("EnablePonIf request received for PON %d", intf.IntfId)
+ ponID := intf.GetIntfId()
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: UP,
+ PonPortID: ponID,
+ },
+ }
+ o.channel <- msg
+
return new(openolt.Empty), nil
}
@@ -995,20 +1010,27 @@
"oltId": o.ID,
}).Info("Received ReenableOlt request from VOLTHA")
- for _, pon := range o.Pons {
- msg := Message{
- Type: PonIndication,
- Data: PonIndicationMessage{
- OperState: UP,
- PonPortID: pon.ID,
- },
- }
- o.channel <- msg
+ // enable OLT
+ oltMsg := Message{
+ Type: OltIndication,
+ Data: OltIndicationMessage{
+ OperState: UP,
+ },
}
+ o.channel <- oltMsg
- // Openolt adapter will start processing indications only after success reponse of ReenableOlt
- // thats why need to send OLT and ONU indications after return of this function
- go o.handleReenableOlt()
+ for _, pon := range o.Pons {
+ if pon.InternalState.Current() == "disabled" {
+ msg := Message{
+ Type: PonIndication,
+ Data: PonIndicationMessage{
+ OperState: UP,
+ PonPortID: pon.ID,
+ },
+ }
+ o.channel <- msg
+ }
+ }
return new(openolt.Empty), nil
}
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index c9c2f17..afa297c 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -82,7 +82,7 @@
func CreateONU(olt *OltDevice, pon PonPort, id uint32, sTag int, cTag int, auth bool, dhcp bool, isMock bool) *Onu {
o := Onu{
- ID: id,
+ ID: 0,
PonPortID: pon.ID,
PonPort: pon,
STag: sTag,
@@ -98,7 +98,7 @@
DhcpFlowReceived: false,
DiscoveryRetryDelay: 60 * time.Second, // this is used to send OnuDiscoveryIndications until an activate call is received
}
- o.SerialNumber = o.NewSN(olt.ID, pon.ID, o.ID)
+ o.SerialNumber = o.NewSN(olt.ID, pon.ID, id)
// NOTE this state machine is used to track the operational
// state as requested by VOLTHA
@@ -119,7 +119,7 @@
{Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
{Name: "add_gem_port", Src: []string{"enabled", "eapol_flow_received"}, Dst: "gem_port_added"},
// NOTE should disabled state be different for oper_disabled (emulating an error) and admin_disabled (received a disabled call via VOLTHA)?
- {Name: "disable", Src: []string{"enabled", "eapol_flow_received", "gem_port_added", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "disabled"},
+ {Name: "disable", Src: []string{"enabled", "eapol_flow_received", "gem_port_added", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed", "pon_disabled"}, Dst: "disabled"},
// ONU state when PON port is disabled but ONU is power ON(more states should be added in src?)
{Name: "pon_disabled", Src: []string{"enabled", "gem_port_added", "eapol_flow_received", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "pon_disabled"},
// EAPOL
@@ -303,7 +303,7 @@
case OnuDiscIndication:
msg, _ := message.Data.(OnuDiscIndicationMessage)
// NOTE we need to slow down and send ONU Discovery Indication in batches to better emulate a real scenario
- time.Sleep(time.Duration(int(o.ID)*o.PonPort.Olt.Delay) * time.Millisecond)
+ time.Sleep(time.Duration(o.PonPort.Olt.Delay) * time.Millisecond)
o.sendOnuDiscIndication(msg, stream)
case OnuIndication:
msg, _ := message.Data.(OnuIndicationMessage)
diff --git a/internal/bbsim/devices/onu_test_helpers.go b/internal/bbsim/devices/onu_test_helpers.go
index cba8db6..a99a007 100644
--- a/internal/bbsim/devices/onu_test_helpers.go
+++ b/internal/bbsim/devices/onu_test_helpers.go
@@ -127,7 +127,8 @@
ID: 0,
}
pon := PonPort{
- ID: 1,
+ ID: 1,
+ Olt: &olt,
}
onu := CreateONU(&olt, pon, 1, 900, 900, false, false, true)
// NOTE we need this in order to create the OnuChannel
diff --git a/internal/bbsim/devices/pon.go b/internal/bbsim/devices/pon.go
index 24b541b..130c74f 100644
--- a/internal/bbsim/devices/pon.go
+++ b/internal/bbsim/devices/pon.go
@@ -31,17 +31,18 @@
ID uint32
NumOnu int
Onus []*Onu
- Olt OltDevice
+ Olt *OltDevice
// PON Attributes
OperState *fsm.FSM
Type string
// NOTE do we need a state machine for the PON Ports?
+ InternalState *fsm.FSM
}
// CreatePonPort creates pon port object
-func CreatePonPort(olt OltDevice, id uint32) *PonPort {
+func CreatePonPort(olt *OltDevice, id uint32) *PonPort {
ponPort := PonPort{
NumOnu: olt.NumOnuPerPon,
@@ -51,6 +52,61 @@
Onus: []*Onu{},
}
+ ponPort.InternalState = fsm.NewFSM(
+ "created",
+ fsm.Events{
+ {Name: "enable", Src: []string{"created", "disabled"}, Dst: "enabled"},
+ {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
+ },
+ fsm.Callbacks{
+ "enter_enabled": func(e *fsm.Event) {
+ oltLogger.WithFields(log.Fields{
+ "ID": ponPort.ID,
+ }).Debugf("Changing PON Port InternalState from %s to %s", e.Src, e.Dst)
+
+ if e.Src == "created" {
+ if olt.ControlledActivation == Default || olt.ControlledActivation == OnlyPON {
+ for _, onu := range ponPort.Onus {
+ if err := onu.InternalState.Event("initialize"); err != nil {
+ log.Errorf("Error initializing ONU: %v", err)
+ continue
+ }
+ if err := onu.InternalState.Event("discover"); err != nil {
+ log.Errorf("Error discover ONU: %v", err)
+ }
+ }
+ }
+ } else if e.Src == "disabled" {
+ for _, onu := range ponPort.Onus {
+ if onu.InternalState.Current() == "pon_disabled" {
+ if err := onu.InternalState.Event("discover"); err != nil {
+ log.Errorf("Error discover ONU: %v", err)
+ }
+ } else if onu.InternalState.Current() == "disabled" {
+ if err := onu.InternalState.Event("initialize"); err != nil {
+ log.Errorf("Error initialize ONU: %v", err)
+ continue
+ }
+ if err := onu.InternalState.Event("discover"); err != nil {
+ log.Errorf("Error discover ONU: %v", err)
+ }
+ }
+ }
+ }
+ },
+ "enter_disabled": func(e *fsm.Event) {
+ for _, onu := range ponPort.Onus {
+ if onu.InternalState.Current() == "initialized" {
+ continue
+ }
+ if err := onu.InternalState.Event("pon_disabled"); err != nil {
+ oltLogger.Errorf("Failed to move ONU in pon_disabled states: %v", err)
+ }
+ }
+ },
+ },
+ )
+
ponPort.OperState = fsm.NewFSM(
"down",
fsm.Events{
@@ -62,17 +118,13 @@
oltLogger.WithFields(log.Fields{
"ID": ponPort.ID,
}).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
+ olt.sendPonIndication(ponPort.ID)
},
"enter_down": func(e *fsm.Event) {
oltLogger.WithFields(log.Fields{
"ID": ponPort.ID,
}).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
-
- for _, onu := range ponPort.Onus {
- if err := onu.InternalState.Event("pon_disabled"); err != nil {
- oltLogger.Errorf("Failed to move ONU in pon_disabled states: %v", err)
- }
- }
+ olt.sendPonIndication(ponPort.ID)
},
},
)
diff --git a/internal/common/options.go b/internal/common/options.go
index 361d9b3..648c5cf 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -70,6 +70,7 @@
LegacyRestApiAddress string `yaml:"legacy_rest_api_address"`
SadisRestAddress string `yaml:"sadis_rest_address"`
SadisServer bool `yaml:"sadis_server"`
+ ControlledActivation string `yaml:"controlled_activation"`
}
type BBRConfig struct {
@@ -103,6 +104,7 @@
LegacyRestApiAddress: ":50073",
SadisRestAddress: ":50074",
SadisServer: true,
+ ControlledActivation: "default",
},
OltConfig{
Vendor: "BBSim",
@@ -165,6 +167,7 @@
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")
flag.Parse()
conf.Olt.ID = int(*olt_id)
@@ -179,6 +182,7 @@
conf.BBSim.EnableAuth = *auth
conf.BBSim.EnableDhcp = *dhcp
conf.BBSim.Delay = *delay
+ conf.BBSim.ControlledActivation = *controlledActivation
// update device id if not set
if conf.Olt.DeviceId == "" {