[VOL-4679] BBSIM: OMCI extended message set - support MIB upload
Change-Id: I291524f9d33194fb54c508e2344e53dd47370a8f
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
index 2214f2e..376e583 100644
--- a/internal/common/omci/mib_test.go
+++ b/internal/common/omci/mib_test.go
@@ -27,10 +27,6 @@
"gotest.tools/assert"
)
-// used to verify that the first message in the MIB Sync (OnuData)
-// reports the correct MDS
-const MDS = uint8(128)
-
func TestCreateMibResetResponse(t *testing.T) {
data, _ := CreateMibResetResponse(1)
@@ -96,18 +92,18 @@
// 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{},
+ NumberOfBaselineCommands: 4,
+ baselineItems: []MibDbEntry{},
}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.OnuDataClassID,
onuDataEntityId,
me.AttributeValueMap{me.OnuData_MibDataSync: 0},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -119,7 +115,7 @@
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.AniGClassID,
anigEntityId,
me.AttributeValueMap{
@@ -143,7 +139,7 @@
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.Onu2GClassID,
onu2gEntityId,
me.AttributeValueMap{
@@ -163,7 +159,7 @@
// create an entry with UnkownAttributes set
var customPktTxId uint16 = 5
customPkt := []byte{0, byte(customPktTxId), 46, 10, 0, 2, 0, 0, 0, 37, 0, 1, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, 0, 40, 40, 206, 0, 226}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.ClassID(37),
nil,
me.AttributeValueMap{},
@@ -176,7 +172,7 @@
want mibExpected
}{
{"mibUploadNext-0", createTestMibUploadNextArgs(t, 1, 0),
- mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityID: onuDataEntityId.ToUint16(), entityClass: me.OnuDataClassID, attributes: map[string]interface{}{me.OnuData_MibDataSync: MDS}}},
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityID: onuDataEntityId.ToUint16(), entityClass: me.OnuDataClassID, attributes: map[string]interface{}{me.OnuData_MibDataSync: uint8(0)}}},
{"mibUploadNext-1", createTestMibUploadNextArgs(t, 2, 1),
mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 2, entityID: circuitPackEntityID.ToUint16(), entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{me.CircuitPack_Type: uint8(47), me.CircuitPack_NumberOfPorts: uint8(4)}}},
{"mibUploadNext-2", createTestMibUploadNextArgs(t, 3, 2),
@@ -191,7 +187,7 @@
t.Run(tt.name, func(t *testing.T) {
// create the packet starting from the mibUploadNextRequest
- data, err := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg, MDS, &mibDb)
+ data, err := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg, &mibDb)
assert.NilError(t, err)
omciMsg, omciPkt := omciBytesToMsg(t, data)
@@ -225,7 +221,7 @@
// 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)
+ _, err := CreateMibUploadNextResponse(args.omciPkt, args.omciMsg, &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 d22908d..a374371 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -18,8 +18,11 @@
import (
"encoding/binary"
+ "encoding/hex"
"errors"
"fmt"
+ "strconv"
+
"github.com/google/gopacket"
"github.com/opencord/omci-lib-go/v2"
me "github.com/opencord/omci-lib-go/v2/generated"
@@ -109,23 +112,48 @@
return HexEncode(pkt)
}
-func CreateMibUploadResponse(tid uint16, numberOfCommands uint16) ([]byte, error) {
- request := &omci.MibUploadResponse{
+func CreateMibUploadResponse(omciMsg *omci.OMCI, mibDb *MibDb) ([]byte, error) {
+
+ isExtended := false
+ numberOfCommands := mibDb.NumberOfBaselineCommands
+ if omciMsg.DeviceIdentifier == omci.ExtendedIdent {
+ isExtended = true
+ numberOfCommands = mibDb.NumberOfExtendedCommands
+ }
+ response := &omci.MibUploadResponse{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.OnuDataClassID,
+ Extended: isExtended,
},
NumberOfCommands: numberOfCommands,
}
+ omciLogger.WithFields(log.Fields{
+ "NumberOfCommands": numberOfCommands, "isExtended": isExtended}).Debug("mib-upload-response")
- omciLogger.WithFields(log.Fields{"NumberOfCommands": numberOfCommands}).Debug("mib-upload-response")
+ omciLayer := &omci.OMCI{
+ TransactionID: omciMsg.TransactionID,
+ MessageType: omci.MibUploadResponseType,
+ DeviceIdentifier: omciMsg.DeviceIdentifier,
+ }
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
- pkt, err := Serialize(omci.MibUploadResponseType, request, tid)
+ buffer := gopacket.NewSerializeBuffer()
+ err := gopacket.SerializeLayers(buffer, options, omciLayer, response)
if err != nil {
omciLogger.WithFields(log.Fields{
- "Err": err,
- }).Error("Cannot Serialize MibUploadResponse")
+ "Err": err,
+ "TxID": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+ }).Error("cannot-Serialize-MibUploadResponse")
return nil, err
}
+ pkt := buffer.Bytes()
+
+ log.WithFields(log.Fields{
+ "TxID": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+ "pkt": hex.EncodeToString(pkt),
+ }).Trace("omci-mib-upload-response")
+
return pkt, nil
}
@@ -165,7 +193,7 @@
return msgObj, nil
}
-func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, mds uint8, mibDb *MibDb) ([]byte, error) {
+func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, mibDb *MibDb) ([]byte, error) {
msgObj, err := ParseMibUploadNextRequest(omciPkt)
if err != nil {
@@ -180,65 +208,67 @@
"CommandSequenceNumber": msgObj.CommandSequenceNumber,
}).Trace("received-omci-mibUploadNext-request")
- if msgObj.CommandSequenceNumber > mibDb.NumberOfCommands {
+ isExtended := false
+ numberOfCommands := mibDb.NumberOfBaselineCommands
+ if omciMsg.DeviceIdentifier == omci.ExtendedIdent {
+ isExtended = true
+ numberOfCommands = mibDb.NumberOfExtendedCommands
+ }
+ if msgObj.CommandSequenceNumber > numberOfCommands {
omciLogger.WithFields(log.Fields{
"CommandSequenceNumber": msgObj.CommandSequenceNumber,
- "MibDbNumberOfCommands": mibDb.NumberOfCommands,
+ "MibDbNumberOfCommands": numberOfCommands,
}).Error("mibdb-does-not-contain-item")
return nil, fmt.Errorf("mibdb-does-not-contain-item")
}
- currentEntry := mibDb.items[int(msgObj.CommandSequenceNumber)]
+ if isExtended {
+ pkt := SetTxIdInEncodedPacket(mibDb.extendedResponses[int(msgObj.CommandSequenceNumber)], omciMsg.TransactionID)
+ return pkt, nil
+ } else {
+ currentEntry := mibDb.baselineItems[int(msgObj.CommandSequenceNumber)]
- // if packet is set then we don't need to serialize the packet, it's already done
- if currentEntry.packet != nil {
+ // if packet is set then we don't need to serialize the packet, it's already done
+ if currentEntry.packet != nil {
+ omciLogger.WithFields(log.Fields{
+ "CommandSequenceNumber": msgObj.CommandSequenceNumber,
+ "MibDbNumberOfCommands": numberOfCommands,
+ "packet": currentEntry.packet,
+ "request-txid": omciMsg.TransactionID,
+ }).Info("sending-custom-packet")
+
+ // NOTE we need to replace the first two bytes of the packet with the correct transactionId
+ pkt := SetTxIdInEncodedPacket(currentEntry.packet, omciMsg.TransactionID)
+
+ return pkt, nil
+ }
+ reportedMe, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
+ EntityID: currentEntry.entityId.ToUint16(),
+ Attributes: currentEntry.params,
+ })
+
+ if meErr.GetError() != nil {
+ omciLogger.Errorf("Error while generating %s: %v", currentEntry.classId.String(), meErr.Error())
+ }
+ response := &omci.MibUploadNextResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.OnuDataClassID,
+ },
+ ReportedME: *reportedMe,
+ }
+
omciLogger.WithFields(log.Fields{
- "CommandSequenceNumber": msgObj.CommandSequenceNumber,
- "MibDbNumberOfCommands": mibDb.NumberOfCommands,
- "packet": currentEntry.packet,
- "request-txid": omciMsg.TransactionID,
- }).Info("sending-custom-packet")
+ "reportedMe": reportedMe,
+ }).Trace("created-omci-mibUploadNext-response")
- // NOTE we need to replace the first two bytes of the packet with the correct transactionId
- pkt := SetTxIdInEncodedPacket(currentEntry.packet, omciMsg.TransactionID)
+ pkt, err := Serialize(omci.MibUploadNextResponseType, response, omciMsg.TransactionID)
+
+ if err != nil {
+ omciLogger.WithFields(log.Fields{
+ "Err": err,
+ }).Fatalf("Cannot Serialize MibUploadNextRequest")
+ return nil, err
+ }
return pkt, nil
}
-
- reportedMe, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
- EntityID: currentEntry.entityId.ToUint16(),
- Attributes: currentEntry.params,
- })
-
- if meErr.GetError() != nil {
- omciLogger.Errorf("Error while generating %s: %v", currentEntry.classId.String(), 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())
- }
- }
-
- response := &omci.MibUploadNextResponse{
- MeBasePacket: omci.MeBasePacket{
- EntityClass: me.OnuDataClassID,
- },
- ReportedME: *reportedMe,
- }
-
- omciLogger.WithFields(log.Fields{
- "reportedMe": reportedMe,
- }).Trace("created-omci-mibUploadNext-response")
-
- pkt, err := Serialize(omci.MibUploadNextResponseType, response, omciMsg.TransactionID)
-
- if err != nil {
- omciLogger.WithFields(log.Fields{
- "Err": err,
- }).Fatalf("Cannot Serialize MibUploadNextRequest")
- return nil, err
- }
-
- return pkt, nil
}
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
index 08322ca..57ca215 100644
--- a/internal/common/omci/onu_mib_db.go
+++ b/internal/common/omci/onu_mib_db.go
@@ -20,6 +20,9 @@
"bytes"
"encoding/binary"
"encoding/hex"
+ "fmt"
+ "strings"
+
"github.com/google/gopacket"
"github.com/opencord/bbsim/internal/common"
"github.com/opencord/omci-lib-go/v2"
@@ -37,12 +40,23 @@
}
type MibDb struct {
- NumberOfCommands uint16
- items []MibDbEntry
+ NumberOfBaselineCommands uint16
+ NumberOfExtendedCommands uint16
+ baselineItems []MibDbEntry
+ extendedResponses [][]byte
}
type EntityID []byte
+const (
+ unknownMePktReportedMeHdr string = "002500018000"
+ unknownMePktAttributes string = "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+ unknownAttribPktReportedMeHdr string = "0101000007FD"
+ unknownAttribPktAttributes string = "00400801000800000006007F07003F00010001000100"
+ extRespMsgContentsLenStart = 8
+ extRespMsgContentsLenEnd = 10
+)
+
func (e EntityID) ToString() string {
return hex.EncodeToString(e)
}
@@ -102,11 +116,11 @@
func GenerateMibDatabase(ethUniPortCount int, potsUniPortCount int, technology common.PonTechnology) (*MibDb, error) {
mibDb := MibDb{
- items: []MibDbEntry{},
+ baselineItems: []MibDbEntry{},
}
// the first element to return is the ONU-Data
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.OnuDataClassID,
EntityID{0x00, 0x00},
me.AttributeValueMap{me.OnuData_MibDataSync: 0}, // FIXME this needs to be parametrized before sending the response
@@ -134,7 +148,7 @@
aniCPType = gPonUnitType
}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -145,7 +159,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -156,7 +170,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -168,7 +182,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -178,7 +192,7 @@
})
// ANI-G
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.AniGClassID,
EntityID{tcontSlotId, aniGId},
me.AttributeValueMap{
@@ -204,7 +218,7 @@
// 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{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -215,7 +229,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -226,7 +240,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -238,7 +252,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -250,7 +264,7 @@
if potsUniPortCount > 0 {
// circuitPack POTS
// NOTE the circuit pack is divided in multiple messages as too big to fit in a single one
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -261,7 +275,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -272,7 +286,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -284,7 +298,7 @@
},
nil,
})
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.CircuitPackClassID,
circuitPackEntityID,
me.AttributeValueMap{
@@ -303,7 +317,7 @@
if i <= ethUniPortCount {
// first, create the correct amount of ethernet UNIs, the same is done in onu.go
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PhysicalPathTerminationPointEthernetUniClassID,
uniEntityId,
me.AttributeValueMap{
@@ -327,7 +341,7 @@
})
} else {
// the remaining ones are pots UNIs, the same is done in onu.go
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PhysicalPathTerminationPointPotsUniClassID,
uniEntityId,
me.AttributeValueMap{
@@ -349,7 +363,7 @@
})
}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.UniGClassID,
uniEntityId,
me.AttributeValueMap{
@@ -369,7 +383,7 @@
queueEntityId := EntityID{cardHolderSlotID, byte(j)}
// we first report the PriorityQueue without any attribute
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{},
@@ -379,7 +393,7 @@
// 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{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{
@@ -405,7 +419,7 @@
for i := 1; i <= tconts; i++ {
tcontEntityId := EntityID{tcontSlotId, byte(i)}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.TContClassID,
tcontEntityId,
me.AttributeValueMap{
@@ -415,7 +429,7 @@
})
tsEntityId := EntityID{cardHolderSlotID, byte(i)}
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.TrafficSchedulerClassID,
tsEntityId, //was not reported in the original implementation
me.AttributeValueMap{
@@ -434,7 +448,7 @@
// EntityID = tcontSlotId + Uni EntityID (8001)
// we first report the PriorityQueue without any attribute
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{},
@@ -444,7 +458,7 @@
// 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{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{
@@ -500,7 +514,7 @@
}
}
- mibDb.items = append(mibDb.items, onu2g)
+ mibDb.baselineItems = append(mibDb.baselineItems, onu2g)
if common.Config.BBSim.InjectOmciUnknownMe {
// NOTE the TxID is actually replaced
@@ -515,10 +529,8 @@
//omciHdr := "00032e0a"
msgHdr := "00020000"
- reportedMeHdr := "002500018000"
- attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
trailer := "0000002828ce00e2"
- msg := omciHdr + msgHdr + reportedMeHdr + attr + trailer
+ msg := omciHdr + msgHdr + unknownMePktReportedMeHdr + unknownMePktAttributes + trailer
data, err := hex.DecodeString(msg)
if err != nil {
omciLogger.Fatal("cannot-create-custom-packet")
@@ -526,7 +538,7 @@
packet := gopacket.NewPacket(data, omci.LayerTypeOMCI, gopacket.Lazy)
- mibDb.items = append(mibDb.items, MibDbEntry{
+ mibDb.baselineItems = append(mibDb.baselineItems, MibDbEntry{
me.ClassID(37), // G.988 "Intentionally left blank"
nil,
me.AttributeValueMap{},
@@ -534,7 +546,126 @@
})
}
- mibDb.NumberOfCommands = uint16(len(mibDb.items))
+ mibDb.NumberOfBaselineCommands = uint16(len(mibDb.baselineItems))
+ // Create extended MIB upload responses
+ omciLayer := &omci.OMCI{
+ TransactionID: 0xFFFF, //to be replaced later on
+ MessageType: omci.MibUploadNextResponseType,
+ DeviceIdentifier: omci.ExtendedIdent,
+ }
+ var i uint16 = 0
+ for i < mibDb.NumberOfBaselineCommands {
+ currentEntry := mibDb.baselineItems[i]
+ for mibDb.baselineItems[i].packet != nil {
+ // Skip any entry with a predefined packet currently used for MEs with unknown ClassID or unknown attributes.
+ // This information will be added later to the last extended response packet
+ i++
+ currentEntry = mibDb.baselineItems[i]
+ }
+ reportedME, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
+ EntityID: currentEntry.entityId.ToUint16(),
+ Attributes: currentEntry.params,
+ })
+ if meErr.GetError() != nil {
+ omciLogger.Errorf("Error while generating reportedME %s: %v", currentEntry.classId.String(), meErr.Error())
+ }
+ request := &omci.MibUploadNextResponse{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.OnuDataClassID,
+ EntityInstance: uint16(0),
+ Extended: true,
+ },
+ ReportedME: *reportedME,
+ AdditionalMEs: make([]me.ManagedEntity, 0),
+ }
+ i++
+ var outgoingPacket []byte
+ var outgoingPacketLen = 0
+ addMeLoop:
+ for outgoingPacketLen <= omci.MaxExtendedLength-omci.MaxBaselineLength && i < mibDb.NumberOfBaselineCommands {
+ currentEntry := mibDb.baselineItems[i]
+ for mibDb.baselineItems[i].packet != nil {
+ // Skip any entry with a predefined packet currently used for MEs with unknown ClassID or unknown attributes.
+ // This information will be added later to the last extended response packet
+ i++
+ if i < mibDb.NumberOfBaselineCommands {
+ currentEntry = mibDb.baselineItems[i]
+ } else {
+ break addMeLoop
+ }
+ }
+ additionalME, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
+ EntityID: currentEntry.entityId.ToUint16(),
+ Attributes: currentEntry.params,
+ })
+ if meErr.GetError() != nil {
+ omciLogger.Errorf("Error while generating additionalME %s: %v", currentEntry.classId.String(), meErr.Error())
+ }
+ request.AdditionalMEs = append(request.AdditionalMEs, *additionalME)
+
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
+
+ buffer := gopacket.NewSerializeBuffer()
+ omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+ if omciErr != nil {
+ omciLogger.Errorf("Error while serializing generating additionalME %s: %v", currentEntry.classId.String(), omciErr)
+ }
+ outgoingPacket = buffer.Bytes()
+ outgoingPacketLen = len(outgoingPacket)
+ i++
+ }
+ mibDb.extendedResponses = append(mibDb.extendedResponses, outgoingPacket)
+ mibDb.NumberOfExtendedCommands = uint16(len(mibDb.extendedResponses))
+
+ outgoingPacketString := strings.ToLower(hex.EncodeToString(mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1]))
+ omciLogger.Debugf("Extended MIB upload response respNo: %d length: %d string: %s", mibDb.NumberOfExtendedCommands, outgoingPacketLen, outgoingPacketString)
+ }
+ // Currently, there is enough space in the last extended response to add potential MEs with unknown ClassID or unknown attributes, if requested.
+ if common.Config.BBSim.InjectOmciUnknownMe {
+ var err error
+ mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1], err = AppendAdditionalMEs(mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1], unknownMePktReportedMeHdr, unknownMePktAttributes)
+ if err != nil {
+ omciLogger.Fatal(err)
+ } else {
+ outgoingPacketString := strings.ToLower(hex.EncodeToString(mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1]))
+ omciLogger.Debugf("Reponse with unknown ME added: %s", outgoingPacketString)
+ }
+ }
+ if common.Config.BBSim.InjectOmciUnknownAttributes {
+ var err error
+ mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1], err = AppendAdditionalMEs(mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1], unknownAttribPktReportedMeHdr, unknownAttribPktAttributes)
+ if err != nil {
+ omciLogger.Fatal(err)
+ } else {
+ outgoingPacketString := strings.ToLower(hex.EncodeToString(mibDb.extendedResponses[mibDb.NumberOfExtendedCommands-1]))
+ omciLogger.Debugf("Reponse with unknown attributes added: %s", outgoingPacketString)
+ }
+ }
return &mibDb, nil
}
+
+func AppendAdditionalMEs(srcSlice []byte, reportedMeHdr string, attributes string) ([]byte, error) {
+ attribBytes, err := hex.DecodeString(attributes)
+ if err != nil {
+ return nil, fmt.Errorf("cannot-decode-attributes-string")
+ }
+ attribBytesLen := len(attribBytes)
+ attribBytesLenStr := fmt.Sprintf("%04X", attribBytesLen)
+ msg := attribBytesLenStr + reportedMeHdr + attributes
+ data, err := hex.DecodeString(msg)
+ if err != nil {
+ return nil, fmt.Errorf("cannot-decode-attributes")
+ }
+ dstSlice := make([]byte, len(srcSlice))
+ copy(dstSlice, srcSlice)
+ dstSlice = append(dstSlice[:], data[:]...)
+ messageContentsLen := binary.BigEndian.Uint16(dstSlice[extRespMsgContentsLenStart:extRespMsgContentsLenEnd])
+ dataLen := len(data)
+ newMessageContentsLen := messageContentsLen + uint16(dataLen)
+ newLenSlice := make([]byte, 2)
+ binary.BigEndian.PutUint16(newLenSlice, newMessageContentsLen)
+ copy(dstSlice[extRespMsgContentsLenStart:extRespMsgContentsLenEnd], newLenSlice[0:2])
+ return dstSlice, nil
+}
diff --git a/internal/common/omci/onu_mib_db_test.go b/internal/common/omci/onu_mib_db_test.go
index e1c1213..75bcf7d 100644
--- a/internal/common/omci/onu_mib_db_test.go
+++ b/internal/common/omci/onu_mib_db_test.go
@@ -18,9 +18,10 @@
import (
"fmt"
+ "testing"
+
"github.com/google/gopacket"
"github.com/opencord/bbsim/internal/common"
- "testing"
"github.com/opencord/omci-lib-go/v2"
me "github.com/opencord/omci-lib-go/v2/generated"
@@ -76,10 +77,10 @@
assert.NoError(t, err)
assert.NotNil(t, mibDb)
- assert.Equal(t, expectedItems, int(mibDb.NumberOfCommands))
+ assert.Equal(t, expectedItems, int(mibDb.NumberOfBaselineCommands))
// now try to serialize all messages to check on the attributes
- for _, entry := range mibDb.items {
+ for _, entry := range mibDb.baselineItems {
reportedMe, meErr := me.LoadManagedEntityDefinition(entry.classId, me.ParamData{
EntityID: entry.entityId.ToUint16(),
Attributes: entry.params,
@@ -119,10 +120,10 @@
assert.NoError(t, err)
assert.NotNil(t, mibDb)
- assert.Equal(t, expectedItems, int(mibDb.NumberOfCommands))
+ assert.Equal(t, expectedItems, int(mibDb.NumberOfBaselineCommands))
// now try to serialize all messages to check on the attributes
- for _, entry := range mibDb.items {
+ for _, entry := range mibDb.baselineItems {
reportedMe, meErr := me.LoadManagedEntityDefinition(entry.classId, me.ParamData{
EntityID: entry.entityId.ToUint16(),
Attributes: entry.params,
@@ -157,9 +158,9 @@
assert.NoError(t, err)
assert.NotNil(t, mibDb)
- assert.Equal(t, expectedMibEntries, int(mibDb.NumberOfCommands))
+ assert.Equal(t, expectedMibEntries, int(mibDb.NumberOfBaselineCommands))
- entry := mibDb.items[expectedMibEntries-1] // select the last entry, it's the hardcoded packet
+ entry := mibDb.baselineItems[expectedMibEntries-1] // select the last entry, it's the hardcoded packet
fmt.Println(entry.packet)
assert.NotNil(t, entry)
assert.Equal(t, me.ClassID(37), entry.classId)