[VOL-4111] Dinamically generating the MibDB during ONU creation and use
that to drive the MibUploadNextResponse generation
Change-Id: I67dbbe0700a7fbec802516fc6b2a9aff496022de
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index 8f606d0..9fc73e7 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -48,6 +48,7 @@
ImageSoftwareExpectedSections: int32(o.ImageSoftwareExpectedSections),
ActiveImageEntityId: int32(o.ActiveImageEntityId),
CommittedImageEntityId: int32(o.CommittedImageEntityId),
+ Unis: convertBBsimUniPortsToProtoUniPorts(o.UniPorts),
}
onus.Items = append(onus.Items, &onu)
}
@@ -72,6 +73,7 @@
PonPortID: int32(onu.PonPortID),
PortNo: int32(onu.PortNo),
Services: convertBBsimServicesToProtoServices(onu.Services),
+ Unis: convertBBsimUniPortsToProtoUniPorts(onu.UniPorts),
}
return &res, nil
}
diff --git a/internal/bbsim/api/uni_handler.go b/internal/bbsim/api/uni_handler.go
new file mode 100644
index 0000000..48eb260
--- /dev/null
+++ b/internal/bbsim/api/uni_handler.go
@@ -0,0 +1,55 @@
+/*
+ * 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 api
+
+import (
+ "context"
+ "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsim/devices"
+)
+
+func convertBBSimUniPortToProtoUniPort(u *devices.UniPort) *bbsim.UNI {
+ return &bbsim.UNI{
+ ID: int32(u.ID),
+ OnuID: int32(u.Onu.ID),
+ OnuSn: u.Onu.Sn(),
+ MeID: uint32(u.MeId.ToUint16()),
+ OperState: u.OperState.Current(),
+ }
+}
+
+func convertBBsimUniPortsToProtoUniPorts(list []*devices.UniPort) []*bbsim.UNI {
+ unis := []*bbsim.UNI{}
+ for _, uni := range list {
+ unis = append(unis, convertBBSimUniPortToProtoUniPort(uni))
+ }
+ return unis
+}
+
+func (s BBSimServer) GetOnuUnis(ctx context.Context, req *bbsim.ONURequest) (*bbsim.UNIs, error) {
+ onu, err := s.GetONU(ctx, req)
+
+ if err != nil {
+ return nil, err
+ }
+
+ unis := bbsim.UNIs{
+ Items: onu.Unis,
+ }
+
+ return &unis, nil
+}
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index 1afb624..84706fd 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -52,6 +52,7 @@
const (
maxOmciMsgCounter = 10
+ uniPorts = 4 // TODO this will need to be configurable
)
const (
@@ -109,9 +110,11 @@
// PortNo comes with flows and it's used when sending packetIndications,
// There is one PortNo per UNI Port, for now we're only storing the first one
// FIXME add support for multiple UNIs (each UNI has a different PortNo)
- PortNo uint32
- Flows []FlowKey
- FlowIds []uint64 // keep track of the flows we currently have in the ONU
+ // deprecated
+ PortNo uint32
+ UniPorts []*UniPort
+ Flows []FlowKey
+ FlowIds []uint64 // keep track of the flows we currently have in the ONU
OperState *fsm.FSM
SerialNumber *openolt.SerialNumber
@@ -131,6 +134,7 @@
tid uint16
hpTid uint16
seqNumber uint16
+ MibDb *omcilib.MibDb
DoneChannel chan bool // this channel is used to signal once the onu is complete (when the struct is used by BBR)
TrafficSchedulers *tech_profile.TrafficSchedulers
@@ -169,7 +173,9 @@
// state as requested by VOLTHA
o.OperState = getOperStateFSM(func(e *fsm.Event) {
onuLogger.WithFields(log.Fields{
- "ID": o.ID,
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
}).Debugf("Changing ONU OperState from %s to %s", e.Src, e.Dst)
})
o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo)
@@ -308,6 +314,29 @@
},
)
+ for i := 0; i < uniPorts; i++ {
+ uni, err := NewUniPort(uint32(i), &o)
+ if err != nil {
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ "Err": err,
+ }).Fatal("cannot-create-uni-port")
+ }
+ o.UniPorts = append(o.UniPorts, uni)
+ }
+
+ mibDb, err := omcilib.GenerateMibDatabase(len(o.UniPorts))
+ if err != nil {
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ }).Fatal("cannot-generate-mibdb-for-onu")
+ }
+ o.MibDb = mibDb
+
return &o
}
@@ -748,9 +777,9 @@
o.PonPort.removeGemPortBySn(o.SerialNumber)
}
case omci.MibUploadRequestType:
- responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg.TransactionID)
+ responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg.TransactionID, o.MibDb.NumberOfCommands)
case omci.MibUploadNextRequestType:
- responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDataSync)
+ responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDataSync, o.MibDb)
case omci.GetRequestType:
onuDown := o.OperState.Current() == "down"
responsePkt, _ = omcilib.CreateGetResponse(msg.OmciPkt, msg.OmciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId, o.CommittedImageEntityId, onuDown)
diff --git a/internal/bbsim/devices/onu_test_helpers.go b/internal/bbsim/devices/onu_test_helpers.go
index 017cc9c..1d48662 100644
--- a/internal/bbsim/devices/onu_test_helpers.go
+++ b/internal/bbsim/devices/onu_test_helpers.go
@@ -19,6 +19,7 @@
import (
"context"
"errors"
+ omcilib "github.com/opencord/bbsim/internal/common/omci"
"time"
"github.com/opencord/bbsim/internal/bbsim/types"
@@ -151,6 +152,15 @@
}
o.SerialNumber = NewSN(0, ponPortId, o.ID)
o.Channel = make(chan types.Message, 10)
+
+ unis := []*UniPort{
+ {ID: 0, Onu: &o, MeId: omcilib.GenerateUniPortEntityId(1)},
+ {ID: 1, Onu: &o, MeId: omcilib.GenerateUniPortEntityId(2)},
+ {ID: 2, Onu: &o, MeId: omcilib.GenerateUniPortEntityId(3)},
+ {ID: 3, Onu: &o, MeId: omcilib.GenerateUniPortEntityId(4)},
+ }
+
+ o.UniPorts = unis
return &o
}
diff --git a/internal/bbsim/devices/uni_port.go b/internal/bbsim/devices/uni_port.go
new file mode 100644
index 0000000..78640e3
--- /dev/null
+++ b/internal/bbsim/devices/uni_port.go
@@ -0,0 +1,56 @@
+/*
+ * 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 devices
+
+import (
+ "fmt"
+ "github.com/looplab/fsm"
+ omcilib "github.com/opencord/bbsim/internal/common/omci"
+ log "github.com/sirupsen/logrus"
+)
+
+const maxUniPorts = 4
+
+type UniPort struct {
+ ID uint32
+ MeId omcilib.EntityID
+ OperState *fsm.FSM
+ Onu *Onu
+}
+
+func NewUniPort(ID uint32, onu *Onu) (*UniPort, error) {
+
+ // IDs starts from 0, thus the maximum UNI supported is maxUniPorts - 1
+ if ID > (maxUniPorts - 1) {
+ return nil, fmt.Errorf("%d-is-higher-than-the-maximum-supported-unis-%d", ID, maxUniPorts)
+ }
+
+ uni := UniPort{
+ ID: ID,
+ Onu: onu,
+ MeId: omcilib.GenerateUniPortEntityId(ID + 1),
+ }
+
+ uni.OperState = getOperStateFSM(func(e *fsm.Event) {
+ onuLogger.WithFields(log.Fields{
+ "ID": uni.ID,
+ "OnuSn": onu.Sn(),
+ }).Debugf("changing-uni-operstate-from-%s-to-%s", e.Src, e.Dst)
+ })
+
+ return &uni, nil
+}
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index 33bd5ef..a986205 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -34,7 +34,8 @@
const (
DEFAULT_ONU_DEVICE_HEADER_FORMAT = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .PortNo }}\t{{ .SerialNumber }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .ImageSoftwareExpectedSections }}\t{{ .ImageSoftwareReceivedSections }}\t{{ .ActiveImageEntityId }}\t{{ .CommittedImageEntityId }}"
- DEFAULT_ONU_DEVICE_HEADER_FORMAT_WITH_SERVICES = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .PortNo }}\t{{ .SerialNumber }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .ImageSoftwareExpectedSections }}\t{{ .ImageSoftwareReceivedSections }}\t{{ .ActiveImageEntityId }}\t{{ .CommittedImageEntityId }}\t{{ .Services }}"
+ DEFAULT_ONU_DEVICE_HEADER_FORMAT_WITH_SERVICES = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .PortNo }}\t{{ .SerialNumber }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .ImageSoftwareExpectedSections }}\t{{ .ImageSoftwareReceivedSections }}\t{{ .ActiveImageEntityId }}\t{{ .CommittedImageEntityId }}\t{{ .Unis }}\t{{ .Services }}"
+ DEFAULT_UNI_HEADER_FORMAT = "table{{ .OnuSn }}\t{{ .OnuID }}\t{{ .ID }}\t{{ .MeID }}\t{{ .OperState }}"
)
type OnuSnString string
@@ -64,6 +65,12 @@
} `positional-args:"yes" required:"yes"`
}
+type ONUUnis struct {
+ Args struct {
+ OnuSn OnuSnString
+ } `positional-args:"yes" required:"yes"`
+}
+
type ONUShutDown struct {
Args struct {
OnuSn OnuSnString
@@ -112,6 +119,7 @@
List ONUList `command:"list"`
Get ONUGet `command:"get"`
Services ONUServices `command:"services"`
+ Unis ONUUnis `command:"unis"`
ShutDown ONUShutDown `command:"shutdown"`
PowerOn ONUPowerOn `command:"poweron"`
RestartEapol ONUEapolRestart `command:"auth_restart"`
@@ -214,6 +222,31 @@
return nil
}
+func (options *ONUUnis) Execute(args []string) error {
+
+ client, conn := connect()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+ req := pb.ONURequest{
+ SerialNumber: string(options.Args.OnuSn),
+ }
+ res, err := client.GetOnuUnis(ctx, &req)
+
+ if err != nil {
+ log.Fatalf("Cannot not get unis for ONU %s: %v", options.Args.OnuSn, err)
+ return err
+ }
+
+ tableFormat := format.Format(DEFAULT_UNI_HEADER_FORMAT)
+ if err := tableFormat.Execute(os.Stdout, true, res.Items); err != nil {
+ log.Fatalf("Error while formatting Unis table: %s", err)
+ }
+
+ return nil
+}
+
func (options *ONUShutDown) Execute(args []string) error {
client, conn := connect()
diff --git a/internal/common/omci/get.go b/internal/common/omci/get.go
index 384fc0b..73e53ac 100644
--- a/internal/common/omci/get.go
+++ b/internal/common/omci/get.go
@@ -119,7 +119,7 @@
EntityID: entityID,
Attributes: me.AttributeValueMap{
"ManagedEntityId": entityID,
- "EquipmentId": toOctets("12345123451234512345", 20),
+ "EquipmentId": ToOctets("12345123451234512345", 20),
"OpticalNetworkUnitManagementAndControlChannelOmccVersion": 180,
"VendorProductCode": 0,
"SecurityCapability": 1,
@@ -157,8 +157,8 @@
EntityID: entityID,
Attributes: me.AttributeValueMap{
"ManagedEntityId": entityID,
- "VendorId": toOctets("BBSM", 4),
- "Version": toOctets("v0.0.1", 14),
+ "VendorId": ToOctets("BBSM", 4),
+ "Version": ToOctets("v0.0.1", 14),
"SerialNumber": append(onuSn.VendorId, onuSn.VendorSpecific...),
"TrafficManagementOption": 0,
"Deprecated": 0,
@@ -166,8 +166,8 @@
"AdministrativeState": 0,
"OperationalState": 0,
"OnuSurvivalTime": 10,
- "LogicalOnuId": toOctets("BBSM", 24),
- "LogicalPassword": toOctets("BBSM", 12),
+ "LogicalOnuId": ToOctets("BBSM", 24),
+ "LogicalPassword": ToOctets("BBSM", 12),
"CredentialsStatus": 0,
"ExtendedTcLayerOptions": 0,
},
@@ -224,12 +224,12 @@
},
Attributes: me.AttributeValueMap{
"ManagedEntityId": 0,
- "Version": toOctets("00000000000001", 14),
+ "Version": ToOctets("00000000000001", 14),
"IsCommitted": committed,
"IsActive": active,
"IsValid": 1,
- "ProductCode": toOctets("product-code", 25),
- "ImageHash": toOctets("broadband-sim", 16),
+ "ProductCode": ToOctets("product-code", 25),
+ "ImageHash": ToOctets("broadband-sim", 16),
},
Result: me.Success,
AttributeMask: attributeMask,
@@ -253,7 +253,7 @@
},
Attributes: me.AttributeValueMap{
"ManagedEntityId": 0,
- "MacAddress": toOctets("aabbcc", 6),
+ "MacAddress": ToOctets("aabbcc", 6),
},
Result: me.Success,
AttributeMask: attributeMask,
@@ -590,7 +590,7 @@
}
}
-func toOctets(str string, size int) []byte {
+func ToOctets(str string, size int) []byte {
asciiBytes := []byte(str)
if len(asciiBytes) < size {
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
index a4ffbb7..139e3e1 100644
--- a/internal/common/omci/mib_test.go
+++ b/internal/common/omci/mib_test.go
@@ -71,27 +71,99 @@
func TestCreateMibUploadNextResponse(t *testing.T) {
+ const uniPortCount = 4
+
+ var (
+ onuDataEntityId = EntityID{0x00, 0x00}
+ onu2gEntityId = EntityID{0x00, 0x00}
+ anigEntityId = EntityID{tcontSlotId, aniGId}
+ )
+
+ // create a fake mibDb, we only need to test that given a CommandSequenceNumber
+ // we return the corresponding entry
+ // the only exception is for OnuData in which we need to replace the MibDataSync attribute with the current value
+ mibDb := MibDb{
+ NumberOfCommands: 4,
+ items: []MibDbEntry{},
+ }
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.OnuDataClassID,
+ onuDataEntityId,
+ me.AttributeValueMap{"MibDataSync": 0},
+ })
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "Type": ethernetUnitType,
+ "NumberOfPorts": uniPortCount,
+ "SerialNumber": ToOctets("BBSM-Circuit-Pack", 20),
+ "Version": ToOctets("v0.0.1", 20),
+ },
+ })
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.AniGClassID,
+ anigEntityId,
+ me.AttributeValueMap{
+ "Arc": 0,
+ "ArcInterval": 0,
+ "Deprecated": 0,
+ "GemBlockLength": 48,
+ "LowerOpticalThreshold": 255,
+ "LowerTransmitPowerThreshold": 129,
+ "OnuResponseTime": 0,
+ "OpticalSignalLevel": 57428,
+ "PiggybackDbaReporting": 0,
+ "SignalDegradeThreshold": 9,
+ "SignalFailThreshold": 5,
+ "SrIndication": 1,
+ "TotalTcontNumber": 8,
+ "TransmitOpticalLevel": 3171,
+ "UpperOpticalThreshold": 255,
+ "UpperTransmitPowerThreshold": 129,
+ },
+ })
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.Onu2GClassID,
+ onu2gEntityId,
+ me.AttributeValueMap{
+ "ConnectivityCapability": 127,
+ "CurrentConnectivityMode": 0,
+ "Deprecated": 1,
+ "PriorityQueueScaleFactor": 1,
+ "QualityOfServiceQosConfigurationFlexibility": 63,
+ "Sysuptime": 0,
+ "TotalGemPortIdNumber": 8,
+ "TotalPriorityQueueNumber": 64,
+ "TotalTrafficSchedulerNumber": 8,
+ },
+ })
+
tests := []struct {
name string
args mibArgs
want mibExpected
}{
{"mibUploadNext-0", createTestMibUploadNextArgs(t, 1, 0),
-
- mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityID: 0, entityClass: me.OnuDataClassID, attributes: map[string]interface{}{"MibDataSync": MDS}}},
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityID: onuDataEntityId.ToUint16(), entityClass: me.OnuDataClassID, attributes: map[string]interface{}{"MibDataSync": MDS}}},
{"mibUploadNext-1", createTestMibUploadNextArgs(t, 2, 1),
- mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 2, entityID: 257, entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"Type": uint8(47), "NumberOfPorts": uint8(4)}}},
- {"mibUploadNext-4", createTestMibUploadNextArgs(t, 3, 4),
- mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 3, entityID: 257, entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"PowerShedOverride": uint32(0)}}},
- {"mibUploadNext-10", createTestMibUploadNextArgs(t, 4, 10),
- mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 4, entityID: 258, entityClass: me.PhysicalPathTerminationPointEthernetUniClassID, attributes: map[string]interface{}{"SensedType": uint8(47)}}},
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 2, entityID: circuitPackEntityID.ToUint16(), entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"Type": uint8(47), "NumberOfPorts": uint8(4)}}},
+ {"mibUploadNext-2", createTestMibUploadNextArgs(t, 3, 2),
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 3, entityID: anigEntityId.ToUint16(), entityClass: me.AniGClassID, attributes: map[string]interface{}{"GemBlockLength": uint16(48)}}},
+ {"mibUploadNext-3", createTestMibUploadNextArgs(t, 4, 3),
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 4, entityID: onuDataEntityId.ToUint16(), entityClass: me.Onu2GClassID, attributes: map[string]interface{}{"TotalPriorityQueueNumber": uint16(64)}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// create the packet starting from the mibUploadNextRequest
- data, _ := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg, MDS)
+ data, err := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg, MDS, &mibDb)
+ assert.NilError(t, err)
omciMsg, omciPkt := omciBytesToMsg(t, data)
assert.Equal(t, omciMsg.MessageType, tt.want.messageType)
@@ -107,65 +179,15 @@
assert.Equal(t, msgObj.ReportedME.GetEntityID(), tt.want.entityID)
for k, v := range tt.want.attributes {
- attr, _ := msgObj.ReportedME.GetAttribute(k)
+ attr, err := msgObj.ReportedME.GetAttribute(k)
+ assert.NilError(t, err)
assert.Equal(t, attr, v)
}
})
}
-}
-type pqueueExpected struct {
- entityId uint16
- relatedPort uint32
-}
-
-func TestGeneratePriorityQueueMe(t *testing.T) {
-
- tests := []struct {
- name string
- sequence uint16
- want pqueueExpected
- }{
- {"generate-pq-downstream-1", 26,
- pqueueExpected{entityId: 1, relatedPort: 16842752}},
- {"generate-pq-downstream-2", 30,
- pqueueExpected{entityId: 2, relatedPort: 16842753}},
- {"generate-pq-downstream-3", 58,
- pqueueExpected{entityId: 9, relatedPort: 16842760}},
- {"generate-pq-upstream-1", 28,
- pqueueExpected{entityId: 32769, relatedPort: 2147549184}},
- {"generate-pq-upstream-2", 32,
- pqueueExpected{entityId: 32770, relatedPort: 2147549185}},
- {"generate-pq-upstream-3", 60,
- pqueueExpected{entityId: 32777, relatedPort: 2147614720}},
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- reportedMe, meErr := GeneratePriorityQueueMe(tt.sequence)
- if meErr.GetError() != nil {
- t.Fatal(meErr.Error())
- }
-
- assert.Equal(t, reportedMe.GetEntityID(), tt.want.entityId)
-
- relatedPort, _ := reportedMe.GetAttribute("RelatedPort")
- assert.Equal(t, relatedPort, tt.want.relatedPort)
- })
- }
-
- // test that the related ports are unique
- allRelatedPorts := make(map[uint32]struct{})
- for v := 26; v <= 281; v++ {
- reportedMe, meErr := GeneratePriorityQueueMe(uint16(v))
- if meErr.GetError() != nil {
- t.Fatal(meErr.Error())
- }
- relatedPort, _ := reportedMe.GetAttribute("RelatedPort")
- allRelatedPorts[relatedPort.(uint32)] = struct{}{}
- }
-
- // we report 128 queues total, but each of them is comprised of 2 messages
- // that's why the 256 iterations
- assert.Equal(t, len(allRelatedPorts), 128)
+ // now try to get a non existing command from the DB anche expect an error
+ args := createTestMibUploadNextArgs(t, 1, 20)
+ _, err := CreateMibUploadNextResponse(args.omciPkt, args.omciMsg, MDS, &mibDb)
+ assert.Error(t, err, "mibdb-does-not-contain-item")
}
diff --git a/internal/common/omci/mibpackets.go b/internal/common/omci/mibpackets.go
index 6d22200..8db0709 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -23,25 +23,12 @@
"github.com/opencord/omci-lib-go"
me "github.com/opencord/omci-lib-go/generated"
log "github.com/sirupsen/logrus"
- "strconv"
)
var omciLogger = log.WithFields(log.Fields{
"module": "OMCI",
})
-// we have a fixed number of 8 T-CONTS
-var reportedTcontsMeId = []uint16{
- 32769,
- 32770,
- 32771,
- 32772,
- 32773,
- 32774,
- 32775,
- 32776,
-}
-
// NOTE this is basically the same as https://github.com/opencord/voltha-openonu-adapter-go/blob/master/internal/pkg/onuadaptercore/omci_cc.go#L545-L564
// we should probably move it in "omci-lib-go"
func Serialize(msgType omci.MessageType, request gopacket.SerializableLayer, tid uint16) ([]byte, error) {
@@ -112,10 +99,7 @@
return HexEncode(pkt)
}
-func CreateMibUploadResponse(tid uint16) ([]byte, error) {
-
- numberOfCommands := uint16(291) //NOTE should this be configurable? (not until we have moved all the messages away from omci-sim)
-
+func CreateMibUploadResponse(tid uint16, numberOfCommands uint16) ([]byte, error) {
request := &omci.MibUploadResponse{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.OnuDataClassID,
@@ -168,7 +152,7 @@
return msgObj, nil
}
-func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, mds uint8) ([]byte, error) {
+func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, mds uint8, mibDb *MibDb) ([]byte, error) {
msgObj, err := ParseMibUploadNextRequest(omciPkt)
if err != nil {
@@ -183,256 +167,28 @@
"CommandSequenceNumber": msgObj.CommandSequenceNumber,
}).Trace("received-omci-mibUploadNext-request")
- var reportedMe *me.ManagedEntity
- var meErr me.OmciErrors
+ if msgObj.CommandSequenceNumber > mibDb.NumberOfCommands {
+ omciLogger.WithFields(log.Fields{
+ "CommandSequenceNumber": msgObj.CommandSequenceNumber,
+ "MibDbNumberOfCommands": mibDb.NumberOfCommands,
+ }).Error("mibdb-does-not-contain-item")
+ return nil, fmt.Errorf("mibdb-does-not-contain-item")
+ }
+ currentEntry := mibDb.items[int(msgObj.CommandSequenceNumber)]
+ reportedMe, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
+ EntityID: currentEntry.entityId.ToUint16(),
+ Attributes: currentEntry.params,
+ })
- switch msgObj.CommandSequenceNumber {
- case 0:
- reportedMe, meErr = me.NewOnuData(me.ParamData{Attributes: me.AttributeValueMap{
- "MibDataSync": mds,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewOnuData %v", meErr.Error())
- }
+ if meErr.GetError() != nil {
+ omciLogger.Errorf("Error while generating %s: %v", currentEntry.classId.String(), meErr.Error())
+ }
- case 1:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "Type": 47,
- "NumberOfPorts": 4,
- "SerialNumber": toOctets("BBSM-Circuit-Pack", 20),
- "Version": toOctets("v0.0.1", 20),
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+ if reportedMe.GetClassID() == me.OnuDataClassID {
+ // if this is ONU-Data we need to replace the MDS
+ if err := reportedMe.SetAttribute("MibDataSync", mds); err.GetError() != nil {
+ omciLogger.Errorf("Error while setting mds in %s: %v", currentEntry.classId.String(), meErr.Error())
}
- case 2:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "VendorId": "ONF",
- "AdministrativeState": 0,
- "OperationalState": 0,
- "BridgedOrIpInd": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 3:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "EquipmentId": toOctets("BBSM-Circuit-Pack", 20),
- "CardConfiguration": 0,
- "TotalTContBufferNumber": 8,
- "TotalPriorityQueueNumber": 8,
- "TotalTrafficSchedulerNumber": 16,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 4:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "PowerShedOverride": uint32(0),
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 5:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257,
- Attributes: me.AttributeValueMap{
- "Type": 238,
- "NumberOfPorts": 4, //number of UNI for this device
- "SerialNumber": toOctets("BBSM-Circuit-Pack-2", 20),
- "Version": toOctets("v0.0.1", 20),
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 6:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "VendorId": "ONF",
- "AdministrativeState": 0,
- "OperationalState": 0,
- "BridgedOrIpInd": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 7:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "EquipmentId": toOctets("BBSM-Circuit-Pack", 20),
- "CardConfiguration": 0,
- "TotalTContBufferNumber": 0,
- "TotalPriorityQueueNumber": 8,
- "TotalTrafficSchedulerNumber": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 8:
- reportedMe, meErr = me.NewCircuitPack(me.ParamData{
- EntityID: 257, // first UNI
- Attributes: me.AttributeValueMap{
- "PowerShedOverride": uint32(0),
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
- }
- case 9, 10, 11, 12:
- // NOTE we're reporting for different UNIs, the IDs are 257, 258, 259, 260
- meInstance := 248 + msgObj.CommandSequenceNumber
- reportedMe, meErr = me.NewPhysicalPathTerminationPointEthernetUni(me.ParamData{
- EntityID: meInstance,
- Attributes: me.AttributeValueMap{
- "ExpectedType": 0,
- "SensedType": 47,
- "AutoDetectionConfiguration": 0,
- "EthernetLoopbackConfiguration": 0,
- "AdministrativeState": 0,
- "OperationalState": 0,
- "ConfigurationInd": 3,
- "MaxFrameSize": 1518,
- "DteOrDceInd": 0,
- "PauseTime": 0,
- "BridgedOrIpInd": 2,
- "Arc": 0,
- "ArcInterval": 0,
- "PppoeFilter": 0,
- "PowerControl": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewPhysicalPathTerminationPointEthernetUni %v", meErr.Error())
- }
- case 13, 14, 15, 16, 17, 18, 19, 20:
- reportedMe, meErr = me.NewTCont(me.ParamData{
- // NOTE fetch the correct T-CONT MeID based on the sequence number
- EntityID: reportedTcontsMeId[msgObj.CommandSequenceNumber-13],
- Attributes: me.AttributeValueMap{
- "AllocId": 65535,
- },
- })
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewTCont %v", meErr.Error())
- }
- case 21:
- reportedMe, meErr = me.NewAniG(me.ParamData{
- EntityID: 32769, // same as the first T-CONT
- Attributes: me.AttributeValueMap{
- "Arc": 0,
- "ArcInterval": 0,
- "Deprecated": 0,
- "GemBlockLength": 48,
- "LowerOpticalThreshold": 255,
- "LowerTransmitPowerThreshold": 129,
- "OnuResponseTime": 0,
- "OpticalSignalLevel": 57428,
- "PiggybackDbaReporting": 0,
- "SignalDegradeThreshold": 9,
- "SignalFailThreshold": 5,
- "SrIndication": 1,
- "TotalTcontNumber": 8,
- "TransmitOpticalLevel": 3171,
- "UpperOpticalThreshold": 255,
- "UpperTransmitPowerThreshold": 129,
- },
- })
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewAniG %v", meErr.Error())
- }
- case 22, 23, 24, 25:
- // NOTE we're reporting for different UNIs, the IDs are 257, 258, 259, 260
- meInstance := 235 + msgObj.CommandSequenceNumber
- reportedMe, meErr = me.NewUniG(me.ParamData{
- EntityID: meInstance,
- Attributes: me.AttributeValueMap{
- "AdministrativeState": 0,
- "Deprecated": 0,
- "ManagementCapability": 0,
- "NonOmciManagementIdentifier": 0,
- "RelayAgentOptions": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewUniG %v", meErr.Error())
- }
- // Prior-Q with mask downstream
- case 26, 30, 34, 38, 42, 46, 50, 54,
- 58, 62, 66, 70, 74, 78, 82, 86,
- 90, 94, 98, 102, 106, 110, 114, 118,
- 122, 126, 130, 134, 138, 142, 146, 150,
- 154, 158, 162, 166, 170, 174, 178, 182,
- 186, 190, 194, 198, 202, 206, 210, 214,
- 218, 222, 226, 230, 234, 238, 242, 246,
- 250, 254, 258, 262, 266, 270, 274, 278,
- // Prior-Q with attribute list downstream
- 27, 31, 35, 39, 43, 47, 51, 55,
- 59, 63, 67, 71, 75, 79, 83, 87,
- 91, 95, 99, 103, 107, 111, 115, 119,
- 123, 127, 131, 135, 139, 143, 147, 151,
- 155, 159, 163, 167, 171, 175, 179, 183,
- 187, 191, 195, 199, 203, 207, 211, 215,
- 219, 223, 227, 231, 235, 239, 243, 247,
- 251, 255, 259, 263, 267, 271, 275, 279,
- // Prior-Q with mask upstream
- 28, 32, 36, 40, 44, 48, 52, 56,
- 60, 64, 68, 72, 76, 80, 84, 88,
- 92, 96, 100, 104, 108, 112, 116, 120,
- 124, 128, 132, 136, 140, 144, 148, 152,
- 156, 160, 164, 168, 172, 176, 180, 184,
- 188, 192, 196, 200, 204, 208, 212, 216,
- 220, 224, 228, 232, 236, 240, 244, 248,
- 252, 256, 260, 264, 268, 272, 276, 280,
- // Prior-Q with attribute list upstream
- 29, 33, 37, 41, 45, 49, 53, 57,
- 61, 65, 69, 73, 77, 81, 85, 89,
- 93, 97, 101, 105, 109, 113, 117, 121,
- 125, 129, 133, 137, 141, 145, 149, 153,
- 157, 161, 165, 169, 173, 177, 181, 185,
- 189, 193, 197, 201, 205, 209, 213, 217,
- 221, 225, 229, 233, 237, 241, 245, 249,
- 253, 257, 261, 265, 269, 273, 277, 281:
-
- reportedMe, meErr = GeneratePriorityQueueMe(msgObj.CommandSequenceNumber)
-
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewPriorityQueue %v", meErr.Error())
- }
- case 282, 283, 284, 285, 286, 287, 288, 289:
- reportedMe, meErr = me.NewTrafficScheduler(me.ParamData{Attributes: me.AttributeValueMap{
- "TContPointer": 32768, // NOTE does this need to change?
- "TrafficSchedulerPointer": 0,
- "Policy": 02,
- "PriorityWeight": 0,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewTrafficScheduler %v", meErr.Error())
- }
- case 290:
- reportedMe, meErr = me.NewOnu2G(me.ParamData{Attributes: me.AttributeValueMap{
- "ConnectivityCapability": 127,
- "CurrentConnectivityMode": 0,
- "Deprecated": 1,
- "PriorityQueueScaleFactor": 1,
- "QualityOfServiceQosConfigurationFlexibility": 63,
- "Sysuptime": 0,
- "TotalGemPortIdNumber": 8,
- "TotalPriorityQueueNumber": 64,
- "TotalTrafficSchedulerNumber": 8,
- }})
- if meErr.GetError() != nil {
- omciLogger.Errorf("NewOnu2G %v", meErr.Error())
- }
- default:
- omciLogger.Warn("unsupported-CommandSequenceNumber-in-mib-upload-next", msgObj.CommandSequenceNumber)
- return nil, nil
}
response := &omci.MibUploadNextResponse{
@@ -457,83 +213,3 @@
return pkt, nil
}
-
-func GeneratePriorityQueueMe(sequence uint16) (*me.ManagedEntity, me.OmciErrors) {
-
- iteration := sequence - 26
-
- // we report 256 messages for priority queues,
- // 128 downstream and 128 upstream
- // we repeat 64 times the quartet:
- // - downstream with mask
- // - downstream with attributes (same MeID as the previous)
- // - upstream with mask
- // - upstream with attributes (same MeID as the previous)
-
- // very ugly way to define whether the priority queue is upstream or downstream
- // (first 2 blocks are downstream, second two are upstream)
- // for example sequence 26, 27 are downstream
- // sequence 28, 29 are upstream
- isDownstream := ((sequence-26)%4 == 0) || ((sequence-27)%4 == 0)
- // entityIds are:
- // - 1 to 64 for downstream (hex 0001 to 0040)
- // - 32769 to 32832 for upstream (hex 8001 to 8040)
- var entityId uint16
- if isDownstream {
- entityId = (iteration)/4 + 1
- } else {
- entityId = (iteration)/4 + 32769
- }
-
- var relatedPort uint32
- if isDownstream {
- // downstream the related port is:
- // - Circuit Pack/ UNI port of UNI Port (01 01/04)
- // - priority 0 to 15 -> iteration%16
-
- // every 16 iteration (of 4 commands) we move to the next the TCONT MeID
- uniPort := int(iteration/64) + 1
- priority := (iteration / 4) % 16
-
- // concat the uniPort and priority in an hex string
- // we have a single circuit pack, so we hardcode it
- v := fmt.Sprintf("010%x000%x", uniPort, priority)
-
- // convert back to int
- k, _ := strconv.ParseInt(v, 16, 64)
- relatedPort = uint32(k)
- } else {
- // upstream the related port is:
- // - Tcont MeID -> reportedTcontsMeId[ceil(iteration/4/8)]
- // - priority 0 to 7 -> iteration%8
-
- // every 8 iteration (of 4 commands) we move to the next the TCONT MeID
- tcontMe := reportedTcontsMeId[int(iteration/32)]
- priority := (iteration / 4) % 8
-
- // concat the tcontMe and priority in an hex string
- v := fmt.Sprintf("%x000%x", tcontMe, priority)
-
- // convert back to int
- k, _ := strconv.ParseInt(v, 16, 64)
- relatedPort = uint32(k)
- }
-
- return me.NewPriorityQueue(me.ParamData{
- EntityID: entityId,
- Attributes: me.AttributeValueMap{
- "QueueConfigurationOption": 0,
- "MaximumQueueSize": 100,
- "AllocatedQueueSize": 100,
- "DiscardBlockCounterResetInterval": 0,
- "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
- "RelatedPort": relatedPort,
- "TrafficSchedulerPointer": 264,
- "Weight": 1,
- "BackPressureOperation": 1,
- "BackPressureTime": 0,
- "BackPressureOccurQueueThreshold": 0,
- "BackPressureClearQueueThreshold": 0,
- },
- })
-}
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
new file mode 100644
index 0000000..c8696a7
--- /dev/null
+++ b/internal/common/omci/onu_mib_db.go
@@ -0,0 +1,362 @@
+/*
+ * 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 omci
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ me "github.com/opencord/omci-lib-go/generated"
+)
+
+type MibDbEntry struct {
+ classId me.ClassID
+ entityId EntityID
+ params me.AttributeValueMap
+}
+
+type MibDb struct {
+ NumberOfCommands uint16
+ items []MibDbEntry
+}
+
+type EntityID []byte
+
+func (e EntityID) ToString() string {
+ return hex.EncodeToString(e)
+}
+
+func (e EntityID) ToUint16() uint16 {
+ return binary.BigEndian.Uint16(e)
+}
+
+func (e EntityID) ToUint32() uint32 {
+ return binary.BigEndian.Uint32(e)
+}
+
+const (
+ cardHolderOnuType byte = 0x01 // ONU is a single piece of integrated equipment
+ ethernetUnitType byte = 0x2f // Ethernet BASE-T
+ xgsPonUnitType byte = 0xee // XG-PON10G10
+ cardHolderSlotID byte = 0x01
+ tcontSlotId byte = 0x80 // why is this not the same as the cardHolderSlotID, it does not point to anything
+ aniGId byte = 0x01
+
+ upstreamPriorityQueues = 8 // Number of queues for each T-CONT
+ downstreamPriorityQueues = 16 // Number of queues for each PPTP
+ tconts = 8 // NOTE will we ever need to configure this?
+ // trafficSchedulers = 8 // NOTE will we ever need to configure this?
+)
+
+var (
+ cardHolderEntityID = EntityID{cardHolderOnuType, cardHolderSlotID}
+ circuitPackEntityID = cardHolderEntityID // is the same as that of the cardholder ME containing this circuit pack instance
+)
+
+func GenerateUniPortEntityId(id uint32) EntityID {
+ return EntityID{cardHolderSlotID, byte(id)}
+}
+
+// creates a MIB database for a ONU
+// CircuitPack and CardHolder are static, everything else can be configured
+func GenerateMibDatabase(uniPortCount int) (*MibDb, error) {
+
+ mibDb := MibDb{
+ items: []MibDbEntry{},
+ }
+
+ // the first element to return is the ONU-Data
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.OnuDataClassID,
+ EntityID{0x00, 0x00},
+ me.AttributeValueMap{"MibDataSync": 0}, // FIXME this needs to be parametrized before sending the response
+ })
+
+ // then we report the CardHolder
+ // NOTE we have not report it till now, so leave it commented out
+ //mibDb.items = append(mibDb.items, MibDbEntry{
+ // me.CardholderClassID,
+ // cardHolderEntityID,
+ // me.AttributeValueMap{
+ // "ActualPlugInUnitType": cardHolderOnuType,
+ // "ExpectedPlugInUnitType": ethernetUnitType,
+ // },
+ //})
+
+ // circuitPack XG-PON10G10
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "Type": xgsPonUnitType,
+ "NumberOfPorts": 1, // NOTE is this the ANI port? must be
+ "SerialNumber": ToOctets("BBSM-Circuit-Pack-ani", 20),
+ "Version": ToOctets("v0.0.1", 20),
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "VendorId": "ONF",
+ "AdministrativeState": 0,
+ "OperationalState": 0,
+ "BridgedOrIpInd": 0,
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "EquipmentId": ToOctets("BBSM-Circuit-Pack", 20),
+ "CardConfiguration": 0,
+ "TotalTContBufferNumber": 8,
+ "TotalPriorityQueueNumber": 8,
+ "TotalTrafficSchedulerNumber": 0,
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "PowerShedOverride": uint32(0),
+ },
+ })
+
+ // ANI-G
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.AniGClassID,
+ EntityID{tcontSlotId, aniGId},
+ me.AttributeValueMap{
+ "Arc": 0,
+ "ArcInterval": 0,
+ "Deprecated": 0,
+ "GemBlockLength": 48,
+ "LowerOpticalThreshold": 255,
+ "LowerTransmitPowerThreshold": 129,
+ "OnuResponseTime": 0,
+ "OpticalSignalLevel": 57428,
+ "PiggybackDbaReporting": 0,
+ "SignalDegradeThreshold": 9,
+ "SignalFailThreshold": 5,
+ "SrIndication": 1,
+ "TotalTcontNumber": 8,
+ "TransmitOpticalLevel": 3171,
+ "UpperOpticalThreshold": 255,
+ "UpperTransmitPowerThreshold": 129,
+ },
+ })
+
+ // circuitPack Ethernet
+ // NOTE the circuit pack is divided in multiple messages as too big to fit in a single one
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "Type": ethernetUnitType,
+ "NumberOfPorts": uniPortCount,
+ "SerialNumber": ToOctets("BBSM-Circuit-Pack", 20),
+ "Version": ToOctets("v0.0.1", 20),
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "VendorId": "ONF",
+ "AdministrativeState": 0,
+ "OperationalState": 0,
+ "BridgedOrIpInd": 0,
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "EquipmentId": ToOctets("BBSM-Circuit-Pack", 20),
+ "CardConfiguration": 0,
+ "TotalTContBufferNumber": 8,
+ "TotalPriorityQueueNumber": 8,
+ "TotalTrafficSchedulerNumber": 16,
+ },
+ })
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.CircuitPackClassID,
+ circuitPackEntityID,
+ me.AttributeValueMap{
+ "PowerShedOverride": uint32(0),
+ },
+ })
+
+ // PPTP and UNI-Gs
+ // NOTE this are dependent on the number of UNI this ONU supports
+ // Through an identical ID, the UNI-G ME is implicitly linked to an instance of a PPTP
+ for i := 1; i <= uniPortCount; i++ {
+ uniEntityId := GenerateUniPortEntityId(uint32(i))
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.PhysicalPathTerminationPointEthernetUniClassID,
+ uniEntityId,
+ me.AttributeValueMap{
+ "ExpectedType": 0,
+ "SensedType": ethernetUnitType,
+ "AutoDetectionConfiguration": 0,
+ "EthernetLoopbackConfiguration": 0,
+ "AdministrativeState": 0,
+ "OperationalState": 0,
+ "ConfigurationInd": 3,
+ "MaxFrameSize": 1518,
+ "DteOrDceInd": 0,
+ "PauseTime": 0,
+ "BridgedOrIpInd": 2,
+ "Arc": 0,
+ "ArcInterval": 0,
+ "PppoeFilter": 0,
+ "PowerControl": 0,
+ },
+ })
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.UniGClassID,
+ uniEntityId,
+ me.AttributeValueMap{
+ "AdministrativeState": 0,
+ "Deprecated": 0,
+ "ManagementCapability": 0,
+ "NonOmciManagementIdentifier": 0,
+ "RelayAgentOptions": 0,
+ },
+ })
+
+ // Downstream Queues (related to PPTP)
+ // 16 priorities queues for each UNI Ports
+ // EntityID = cardHolderSlotID + Uni EntityID (0101)
+ for j := 1; j <= downstreamPriorityQueues; j++ {
+ queueEntityId := EntityID{cardHolderSlotID, byte(j)}
+
+ // we first report the PriorityQueue without any attribute
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.PriorityQueueClassID,
+ queueEntityId, //was not reported in the original implementation
+ me.AttributeValueMap{},
+ })
+
+ // then we report it with the required attributes
+ // In the downstream direction, the first byte is the slot number and the second byte is the port number of the queue's destination port.
+ relatedPort := append(uniEntityId, 0x00, byte(j))
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.PriorityQueueClassID,
+ queueEntityId, //was not reported in the original implementation
+ me.AttributeValueMap{
+ "QueueConfigurationOption": 0,
+ "MaximumQueueSize": 100,
+ "AllocatedQueueSize": 100,
+ "DiscardBlockCounterResetInterval": 0,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "RelatedPort": relatedPort.ToUint32(),
+ "TrafficSchedulerPointer": 0, //it was hardcoded to 0x0108 in the current implementation
+ "Weight": 1,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureClearQueueThreshold": 0,
+ },
+ })
+ }
+ }
+
+ // T-CONTS and Traffic Schedulers
+ for i := 1; i <= tconts; i++ {
+ tcontEntityId := EntityID{tcontSlotId, byte(i)}
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.TContClassID,
+ tcontEntityId,
+ me.AttributeValueMap{
+ "AllocId": 65535,
+ },
+ })
+
+ tsEntityId := EntityID{cardHolderSlotID, byte(i)}
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.TrafficSchedulerClassID,
+ tsEntityId, //was not reported in the original implementation
+ me.AttributeValueMap{
+ "TContPointer": tcontEntityId.ToUint16(), // was hardcoded to a non-existing t-cont
+ "TrafficSchedulerPointer": 0,
+ "Policy": 02,
+ "PriorityWeight": 0,
+ },
+ })
+
+ for j := 1; j <= upstreamPriorityQueues; j++ {
+ queueEntityId := EntityID{tcontSlotId, byte(j)}
+ // Upstream Queues (related to traffic schedulers)
+ // 8 priorities queues per TCONT
+ // EntityID = tcontSlotId + Uni EntityID (8001)
+
+ // we first report the PriorityQueue without any attribute
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.PriorityQueueClassID,
+ queueEntityId, //was not reported in the original implementation
+ me.AttributeValueMap{},
+ })
+
+ // then we report it with the required attributes
+ // In the upstream direction, the first 2 bytes are the ME ID of the associated T- CONT, the first byte of which is a slot number, the second byte a T-CONT number.
+ relatedPort := append(tcontEntityId, 0x00, byte(j))
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.PriorityQueueClassID,
+ queueEntityId, //was not reported in the original implementation
+ me.AttributeValueMap{
+ "QueueConfigurationOption": 0,
+ "MaximumQueueSize": 100,
+ "AllocatedQueueSize": 100,
+ "DiscardBlockCounterResetInterval": 0,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "RelatedPort": relatedPort.ToUint32(),
+ "TrafficSchedulerPointer": tsEntityId.ToUint16(), //it was hardcoded to 0x0108 in the current implementation
+ "Weight": 1,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureClearQueueThreshold": 0,
+ },
+ })
+ }
+ }
+
+ // ONU-2g
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.Onu2GClassID,
+ EntityID{0x00, 0x00},
+ me.AttributeValueMap{
+ "ConnectivityCapability": 127,
+ "CurrentConnectivityMode": 0,
+ "Deprecated": 1,
+ "PriorityQueueScaleFactor": 1,
+ "QualityOfServiceQosConfigurationFlexibility": 63,
+ "Sysuptime": 0,
+ "TotalGemPortIdNumber": 8,
+ "TotalPriorityQueueNumber": 64,
+ "TotalTrafficSchedulerNumber": 8,
+ },
+ })
+
+ mibDb.NumberOfCommands = uint16(len(mibDb.items))
+
+ return &mibDb, nil
+}
diff --git a/internal/common/omci/onu_mib_db_test.go b/internal/common/omci/onu_mib_db_test.go
new file mode 100644
index 0000000..cea0daf
--- /dev/null
+++ b/internal/common/omci/onu_mib_db_test.go
@@ -0,0 +1,74 @@
+/*
+ * 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 omci
+
+import (
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestEntityID_ToUint16(t *testing.T) {
+ var id EntityID
+ var res uint16
+
+ id = EntityID{0x01, 0x01}
+ res = id.ToUint16()
+ assert.Equal(t, uint16(257), res)
+
+ id = EntityID{0x00, 0x00}
+ res = id.ToUint16()
+ assert.Equal(t, uint16(0), res)
+}
+
+func Test_GenerateMibDatabase(t *testing.T) {
+ const uniPortCount = 4
+ mibDb, err := GenerateMibDatabase(uniPortCount)
+
+ expectedItems := 9 //ONU-G + 2 Circuit Packs (4 messages each)
+ expectedItems += 2 * uniPortCount // 1 PPTP and 1 UniG per UNI
+ expectedItems += 1 // ANI-G
+ expectedItems += 2 * tconts // T-CONT and traffic schedulers
+ expectedItems += 1 // ONU-2g
+ expectedItems += 2 * 8 * tconts // 8 upstream queues for each T-CONT, and we report each queue twice
+ expectedItems += 2 * 16 * uniPortCount // 16 downstream queues for each T-CONT, and we report each queue twice
+
+ assert.NoError(t, err)
+ assert.NotNil(t, mibDb)
+ assert.Equal(t, expectedItems, int(mibDb.NumberOfCommands))
+
+ // now try to serialize all messages to check on the attributes
+ for _, entry := range mibDb.items {
+ reportedMe, meErr := me.LoadManagedEntityDefinition(entry.classId, me.ParamData{
+ EntityID: entry.entityId.ToUint16(),
+ Attributes: entry.params,
+ })
+ assert.NoError(t, meErr.GetError())
+
+ response := &omci.MibUploadNextResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.OnuDataClassID,
+ },
+ ReportedME: *reportedMe,
+ }
+
+ _, err := Serialize(omci.MibUploadNextResponseType, response, uint16(10))
+ assert.NoError(t, err)
+ }
+
+}