SEBA-958 send periodic port stats
Change-Id: I981e6c70b214845d87e8ae96b370fcdf58ccfef3
diff --git a/cmd/bbr/bbr.go b/cmd/bbr/bbr.go
index 52ae622..441ddb0 100644
--- a/cmd/bbr/bbr.go
+++ b/cmd/bbr/bbr.go
@@ -70,18 +70,7 @@
// create the OLT device
olt := devices.CreateOLT(
- options.Olt.ID,
- int(options.Olt.NniPorts),
- int(options.Olt.PonPorts),
- int(options.Olt.OnusPonPort),
- options.BBSim.STag,
- options.BBSim.CTagInit,
- 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,
- false, // this parameter is not important in the BBR Case
- false,
+ *options.BBSimYamlConfig,
true,
)
diff --git a/cmd/bbsim/bbsim.go b/cmd/bbsim/bbsim.go
index 2de8906..8a1b088 100644
--- a/cmd/bbsim/bbsim.go
+++ b/cmd/bbsim/bbsim.go
@@ -163,18 +163,7 @@
apiDoneChannel := make(chan bool)
olt := devices.CreateOLT(
- options.Olt.ID,
- int(options.Olt.NniPorts),
- int(options.Olt.PonPorts),
- int(options.Olt.OnusPonPort),
- options.BBSim.STag,
- options.BBSim.CTagInit,
- options.BBSim.EnableAuth,
- options.BBSim.EnableDhcp,
- options.BBSim.Delay,
- options.BBSim.ControlledActivation,
- options.BBSim.EnablePerf,
- options.BBSim.Events,
+ *options,
false,
)
diff --git a/configs/bbsim.yaml b/configs/bbsim.yaml
index dcba903..23a6cc9 100644
--- a/configs/bbsim.yaml
+++ b/configs/bbsim.yaml
@@ -37,6 +37,7 @@
reboot_delay: 10 # reboot delay in seconds
# firmware_version: ""
# device_id: 0a:0a:0a:0a:0a:<id>
+ port_stats_interval: 20 # in seconds
# BBR settings
bbr:
diff --git a/internal/bbsim/alarmsim/alarmsim.go b/internal/bbsim/alarmsim/alarmsim.go
index 266282a..aa80212 100644
--- a/internal/bbsim/alarmsim/alarmsim.go
+++ b/internal/bbsim/alarmsim/alarmsim.go
@@ -263,22 +263,6 @@
return nil
}
-// InterfaceIDToPortNo converts InterfaceID to voltha PortID
-// Refer openolt adapter code(master) voltha-openolt-adapter/adaptercore/olt_platform.go: IntfIDToPortNo()
-func InterfaceIDToPortNo(req *bbsim.OLTAlarmRequest) uint32 {
- // Converts interface-id to port-numbers that can be understood by the VOLTHA
- if req.InterfaceType == "nni" || req.InterfaceType == "PonLossOfSignal" {
- // nni at voltha starts with 1,048,576
- // nni = 1,048,576 + InterfaceID
- return 0x1<<20 + req.InterfaceID
- } else if req.InterfaceType == "pon" || req.InterfaceType == "NniLossOfSignal" {
- // pon = 536,870,912 + InterfaceID
- return (0x2 << 28) + req.InterfaceID
- // In bbsim, pon starts from 1
- }
- return 0
-}
-
// IsPonPortPresentInOlt verifies if given Pon port is present in olt
func IsPonPortPresentInOlt(PonPort uint32) bool {
o := devices.GetOLT()
@@ -321,7 +305,7 @@
alarmIndication = &openolt.AlarmIndication{
Data: &openolt.AlarmIndication_LosInd{&openolt.LosIndication{
Status: req.Status,
- IntfId: InterfaceIDToPortNo(req),
+ IntfId: devices.InterfaceIDToPortNo(req.InterfaceID, req.InterfaceType),
}},
}
diff --git a/internal/bbsim/devices/helpers.go b/internal/bbsim/devices/helpers.go
index c4bab28..e72093b 100644
--- a/internal/bbsim/devices/helpers.go
+++ b/internal/bbsim/devices/helpers.go
@@ -17,6 +17,7 @@
package devices
import (
+ "math/rand"
"strconv"
"time"
@@ -85,3 +86,46 @@
olt.EventChannel <- event
}
}
+
+func getPortStats(packetCount uint64, incrementStat bool) (*openolt.PortStatistics, uint64) {
+ // increment current packet count by random number
+ if incrementStat {
+ packetCount = packetCount + uint64(rand.Intn(50)+1*10)
+ }
+
+ // fill all other stats based on packet count
+ portStats := &openolt.PortStatistics{
+ RxBytes: packetCount * 64,
+ RxPackets: packetCount,
+ RxUcastPackets: packetCount * 40 / 100,
+ RxMcastPackets: packetCount * 30 / 100,
+ RxBcastPackets: packetCount * 30 / 100,
+ RxErrorPackets: 0,
+ TxBytes: packetCount * 64,
+ TxPackets: packetCount,
+ TxUcastPackets: packetCount * 40 / 100,
+ TxMcastPackets: packetCount * 30 / 100,
+ TxBcastPackets: packetCount * 30 / 100,
+ TxErrorPackets: 0,
+ RxCrcErrors: 0,
+ BipErrors: 0,
+ Timestamp: uint32(time.Now().Unix()),
+ }
+
+ return portStats, packetCount
+}
+
+// InterfaceIDToPortNo converts InterfaceID to voltha PortID
+// Refer openolt adapter code(master) voltha-openolt-adapter/adaptercore/olt_platform.go: IntfIDToPortNo()
+func InterfaceIDToPortNo(intfID uint32, intfType string) uint32 {
+ // Converts interface-id to port-numbers that can be understood by the VOLTHA
+ if intfType == "nni" {
+ // nni at voltha starts with 1,048,576
+ // nni = 1,048,576 + InterfaceID
+ return 0x1<<20 + intfID
+ } else if intfType == "pon" {
+ // pon = 536,870,912 + InterfaceID
+ return (0x2 << 28) + intfID
+ }
+ return 0
+}
diff --git a/internal/bbsim/devices/nni.go b/internal/bbsim/devices/nni.go
index 0d658e9..fabe69c 100644
--- a/internal/bbsim/devices/nni.go
+++ b/internal/bbsim/devices/nni.go
@@ -54,6 +54,7 @@
ID uint32
nniVeth string
upstreamVeth string
+ PacketCount uint64
// PON Attributes
OperState *fsm.FSM
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index 4aafaba..0209b88 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -63,6 +63,7 @@
ControlledActivation mode
EventChannel chan common.Event
PublishEvents bool
+ PortStatsInterval int
Pons []*PonPort
Nnis []*NniPort
@@ -84,32 +85,33 @@
return &olt
}
-func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, ca string, enablePerf bool, event bool, isMock bool) *OltDevice {
+func CreateOLT(options common.BBSimYamlConfig, isMock bool) *OltDevice {
oltLogger.WithFields(log.Fields{
- "ID": oltId,
- "NumNni": nni,
- "NumPon": pon,
- "NumOnuPerPon": onuPerPon,
+ "ID": options.Olt.ID,
+ "NumNni": options.Olt.NniPorts,
+ "NumPon": options.Olt.PonPorts,
+ "NumOnuPerPon": options.Olt.OnusPonPort,
}).Debug("CreateOLT")
olt = OltDevice{
- ID: oltId,
- SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
+ ID: options.Olt.ID,
+ SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
OperState: getOperStateFSM(func(e *fsm.Event) {
oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
}),
- NumNni: nni,
- NumPon: pon,
- NumOnuPerPon: onuPerPon,
- Pons: []*PonPort{},
- Nnis: []*NniPort{},
- Delay: delay,
- Flows: make(map[FlowKey]openolt.Flow),
- enablePerf: enablePerf,
- PublishEvents: event,
+ NumNni: int(options.Olt.NniPorts),
+ NumPon: int(options.Olt.PonPorts),
+ NumOnuPerPon: int(options.Olt.OnusPonPort),
+ Pons: []*PonPort{},
+ Nnis: []*NniPort{},
+ Delay: options.BBSim.Delay,
+ Flows: make(map[FlowKey]openolt.Flow),
+ enablePerf: options.BBSim.EnablePerf,
+ PublishEvents: options.BBSim.Events,
+ PortStatsInterval: options.Olt.PortStatsInterval,
}
- if val, ok := ControlledActivationModes[ca]; ok {
+ if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
olt.ControlledActivation = val
} else {
oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
@@ -146,14 +148,14 @@
}
// create PON ports
- availableCTag := cTagInit
- for i := 0; i < pon; i++ {
+ availableCTag := options.BBSim.CTagInit
+ for i := 0; i < olt.NumPon; i++ {
p := CreatePonPort(&olt, uint32(i))
// create ONU devices
- for j := 0; j < onuPerPon; j++ {
+ for j := 0; j < olt.NumOnuPerPon; j++ {
delay := time.Duration(olt.Delay*j) * time.Millisecond
- o := CreateONU(&olt, *p, uint32(j+1), sTag, availableCTag, auth, dhcp, delay, isMock)
+ o := CreateONU(&olt, *p, uint32(j+1), options.BBSim.STag, availableCTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
p.Onus = append(p.Onus, o)
availableCTag = availableCTag + 1
}
@@ -391,6 +393,12 @@
}
oltLogger.Debug("Enable OLT Done")
+
+ if !o.enablePerf {
+ // Start a go routine to send periodic port stats to openolt adapter
+ go o.periodicPortStats(o.enableContext)
+ }
+
wg.Wait()
return nil
}
@@ -432,6 +440,39 @@
wg.Done()
}
+func (o *OltDevice) periodicPortStats(ctx context.Context) {
+ var portStats *openolt.PortStatistics
+ for {
+ select {
+ case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
+ // send NNI port stats
+ for _, port := range o.Nnis {
+ incrementStat := true
+ if port.OperState.Current() == "down" {
+ incrementStat = false
+ }
+ portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
+ o.sendPortStatsIndication(portStats, port.ID, port.Type)
+ }
+
+ // send PON port stats
+ for _, port := range o.Pons {
+ incrementStat := true
+ // do not increment port stats if PON port is down or no ONU is activated on PON port
+ if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
+ incrementStat = false
+ }
+ portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
+ o.sendPortStatsIndication(portStats, port.ID, port.Type)
+ }
+ case <-ctx.Done():
+ log.Debug("Stop sending port stats")
+ return
+ }
+
+ }
+}
+
// Helpers method
func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
@@ -553,6 +594,22 @@
}).Debug("Sent Indication_IntfOperInd for PON")
}
+func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
+ oltLogger.WithFields(log.Fields{
+ "Type": portType,
+ "IntfId": portID,
+ }).Trace("Sending port stats")
+ stats.IntfId = InterfaceIDToPortNo(portID, portType)
+ data := &openolt.Indication_PortStats{
+ PortStats: stats,
+ }
+ stream := *o.OpenoltStream
+ if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
+ oltLogger.Errorf("Failed to send PortStats: %v", err)
+ return
+ }
+}
+
// processOltMessages handles messages received over the OpenOLT interface
func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
oltLogger.Debug("Starting OLT Indication Channel")
diff --git a/internal/bbsim/devices/pon.go b/internal/bbsim/devices/pon.go
index 130c74f..c2847b1 100644
--- a/internal/bbsim/devices/pon.go
+++ b/internal/bbsim/devices/pon.go
@@ -28,17 +28,16 @@
type PonPort struct {
// BBSIM Internals
- ID uint32
- NumOnu int
- Onus []*Onu
- Olt *OltDevice
+ ID uint32
+ NumOnu int
+ Onus []*Onu
+ Olt *OltDevice
+ PacketCount uint64
+ InternalState *fsm.FSM
// 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
@@ -148,3 +147,15 @@
}
return nil, errors.New(fmt.Sprintf("Cannot find Onu with id %d in PonPort %d", id, p.ID))
}
+
+// GetNumOfActiveOnus returns number of active ONUs for PON port
+func (p PonPort) GetNumOfActiveOnus() uint32 {
+ var count uint32 = 0
+ for _, onu := range p.Onus {
+ if onu.InternalState.Current() == "initialized" || onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
+ continue
+ }
+ count++
+ }
+ return count
+}
diff --git a/internal/bbsimctl/commands/oltalarms.go b/internal/bbsimctl/commands/oltalarms.go
index 645aade..f251b83 100755
--- a/internal/bbsimctl/commands/oltalarms.go
+++ b/internal/bbsimctl/commands/oltalarms.go
@@ -75,10 +75,18 @@
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
defer cancel()
- req := pb.OLTAlarmRequest{InterfaceType: string(o.Args.Name),
+ req := pb.OLTAlarmRequest{
InterfaceID: uint32(o.Args.IntfID),
Status: "on"}
+ if string(o.Args.Name) == "PonLossOfSignal" {
+ req.InterfaceType = "pon"
+ } else if string(o.Args.Name) == "NniLossOfSignal" {
+ req.InterfaceType = "nni"
+ } else {
+ return fmt.Errorf("Unknown alarm type")
+ }
+
res, err := client.SetOltAlarmIndication(ctx, &req)
if err != nil {
log.Fatalf("Cannot raise OLT alarm: %v", err)
@@ -97,10 +105,18 @@
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
defer cancel()
- req := pb.OLTAlarmRequest{InterfaceType: string(o.Args.Name),
+ req := pb.OLTAlarmRequest{
InterfaceID: uint32(o.Args.IntfID),
Status: "off"}
+ if string(o.Args.Name) == "PonLossOfSignal" {
+ req.InterfaceType = "pon"
+ } else if string(o.Args.Name) == "NniLossOfSignal" {
+ req.InterfaceType = "nni"
+ } else {
+ return fmt.Errorf("Unknown alarm type")
+ }
+
res, err := client.SetOltAlarmIndication(ctx, &req)
if err != nil {
diff --git a/internal/common/options.go b/internal/common/options.go
index 6724d1f..d7bc9eb 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -52,6 +52,7 @@
Technology string `yaml:"technology"`
ID int `yaml:"id"`
OltRebootDelay int `yaml:"reboot_delay"`
+ PortStatsInterval int `yaml: "port_stats_interval"`
}
type BBSimConfig struct {
@@ -124,6 +125,7 @@
Technology: "XGS-PON",
ID: 0,
OltRebootDelay: 10,
+ PortStatsInterval: 20,
},
BBRConfig{
LogLevel: "debug",