[VOL-4437] Adding support for unkown attributes
Change-Id: I54b1fbefdb75ca3ec4abfc83b57b232d07c76873
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
index 9578416..2214f2e 100644
--- a/internal/common/omci/mib_test.go
+++ b/internal/common/omci/mib_test.go
@@ -17,6 +17,8 @@
package omci
import (
+ "encoding/binary"
+ "reflect"
"testing"
"github.com/google/gopacket"
@@ -45,6 +47,16 @@
assert.Equal(t, msgObj.Result, me.Success)
}
+func TestSetTxIdInEncodedPacket(t *testing.T) {
+ basePkt := []byte{129, 42, 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}
+ res := SetTxIdInEncodedPacket(basePkt, uint16(292))
+ assert.Equal(t, len(basePkt), len(res))
+
+ b := res[0:2]
+ txId := binary.BigEndian.Uint16(b)
+ assert.Equal(t, uint16(292), txId)
+}
+
// types for TestCreateMibUploadNextResponse test
type mibArgs struct {
omciPkt gopacket.Packet
@@ -92,6 +104,7 @@
me.OnuDataClassID,
onuDataEntityId,
me.AttributeValueMap{me.OnuData_MibDataSync: 0},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
@@ -103,6 +116,7 @@
me.CircuitPack_SerialNumber: ToOctets("BBSM-Circuit-Pack", 20),
me.CircuitPack_Version: ToOctets("v0.0.1", 20),
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
@@ -126,6 +140,7 @@
me.AniG_UpperOpticalThreshold: 255,
me.AniG_UpperTransmitPowerThreshold: 129,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
@@ -142,6 +157,17 @@
me.Onu2G_TotalPriorityQueueNumber: 64,
me.Onu2G_TotalTrafficSchedulerNumber: 8,
},
+ nil,
+ })
+
+ // 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{
+ me.ClassID(37),
+ nil,
+ me.AttributeValueMap{},
+ customPkt,
})
tests := []struct {
@@ -157,6 +183,8 @@
mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 3, entityID: anigEntityId.ToUint16(), entityClass: me.AniGClassID, attributes: map[string]interface{}{me.AniG_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{}{me.Onu2G_TotalPriorityQueueNumber: uint16(64)}}},
+ {"mibUploadNext-unknown-attrs", createTestMibUploadNextArgs(t, 5, 4),
+ mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: customPktTxId, entityID: 1, entityClass: me.ClassID(37), attributes: map[string]interface{}{"UnknownAttr_1": []uint8{1}}}},
}
for _, tt := range tests {
@@ -182,7 +210,15 @@
for k, v := range tt.want.attributes {
attr, err := msgObj.ReportedME.GetAttribute(k)
assert.NilError(t, err)
- assert.Equal(t, attr, v)
+ if isSlice(attr) {
+ expected := v.([]uint8)
+ data := attr.([]uint8)
+ for i, val := range data {
+ assert.Equal(t, expected[i], val)
+ }
+ } else {
+ assert.Equal(t, attr, v)
+ }
}
})
}
@@ -192,3 +228,7 @@
_, err := CreateMibUploadNextResponse(args.omciPkt, args.omciMsg, MDS, &mibDb)
assert.Error(t, err, "mibdb-does-not-contain-item")
}
+
+func isSlice(v interface{}) bool {
+ return reflect.TypeOf(v).Kind() == reflect.Slice
+}
diff --git a/internal/common/omci/mibpackets.go b/internal/common/omci/mibpackets.go
index 8b7afcb..d22908d 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -17,6 +17,7 @@
package omci
import (
+ "encoding/binary"
"errors"
"fmt"
"github.com/google/gopacket"
@@ -47,6 +48,15 @@
return buffer.Bytes(), nil
}
+func SetTxIdInEncodedPacket(packet []byte, txId uint16) []byte {
+ valid := packet[2:]
+
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, txId)
+
+ return append(b, valid...)
+}
+
func CreateMibResetRequest(tid uint16) ([]byte, error) {
request := &omci.MibResetRequest{
@@ -106,6 +116,9 @@
},
NumberOfCommands: numberOfCommands,
}
+
+ omciLogger.WithFields(log.Fields{"NumberOfCommands": numberOfCommands}).Debug("mib-upload-response")
+
pkt, err := Serialize(omci.MibUploadResponseType, request, tid)
if err != nil {
omciLogger.WithFields(log.Fields{
@@ -175,6 +188,22 @@
return nil, fmt.Errorf("mibdb-does-not-contain-item")
}
currentEntry := mibDb.items[int(msgObj.CommandSequenceNumber)]
+
+ // 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": mibDb.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,
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
index 2902fd2..23d2e99 100644
--- a/internal/common/omci/onu_mib_db.go
+++ b/internal/common/omci/onu_mib_db.go
@@ -20,15 +20,20 @@
"bytes"
"encoding/binary"
"encoding/hex"
-
+ "github.com/google/gopacket"
"github.com/opencord/bbsim/internal/common"
+ "github.com/opencord/omci-lib-go/v2"
me "github.com/opencord/omci-lib-go/v2/generated"
)
+// MibDbEntry contains all the information needed to build a
+// MibUploadNextResponse packet.
+// if Packet has a value all the other fields are ignored and the packet is sent as is.
type MibDbEntry struct {
classId me.ClassID
entityId EntityID
params me.AttributeValueMap
+ packet []byte
}
type MibDb struct {
@@ -105,6 +110,7 @@
me.OnuDataClassID,
EntityID{0x00, 0x00},
me.AttributeValueMap{me.OnuData_MibDataSync: 0}, // FIXME this needs to be parametrized before sending the response
+ nil,
})
// then we report the CardHolder
@@ -137,6 +143,7 @@
me.CircuitPack_SerialNumber: ToOctets("BBSM-Circuit-Pack-ani", 20),
me.CircuitPack_Version: ToOctets("v0.0.1", 20),
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -147,6 +154,7 @@
me.CircuitPack_OperationalState: 0,
me.CircuitPack_BridgedOrIpInd: 0,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -158,6 +166,7 @@
me.CircuitPack_TotalPriorityQueueNumber: 8,
me.CircuitPack_TotalTrafficSchedulerNumber: 0,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -165,6 +174,7 @@
me.AttributeValueMap{
me.CircuitPack_PowerShedOverride: uint32(0),
},
+ nil,
})
// ANI-G
@@ -189,6 +199,7 @@
me.AniG_UpperOpticalThreshold: 255,
me.AniG_UpperTransmitPowerThreshold: 129,
},
+ nil,
})
// circuitPack Ethernet
@@ -202,6 +213,7 @@
me.CircuitPack_SerialNumber: ToOctets("BBSM-Circuit-Pack", 20),
me.CircuitPack_Version: ToOctets("v0.0.1", 20),
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -212,6 +224,7 @@
me.CircuitPack_OperationalState: 0,
me.CircuitPack_BridgedOrIpInd: 0,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -223,6 +236,7 @@
me.CircuitPack_TotalPriorityQueueNumber: 8,
me.CircuitPack_TotalTrafficSchedulerNumber: 16,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -230,6 +244,7 @@
me.AttributeValueMap{
me.CircuitPack_PowerShedOverride: uint32(0),
},
+ nil,
})
if potsUniPortCount > 0 {
@@ -244,6 +259,7 @@
me.CircuitPack_SerialNumber: ToOctets("BBSM-Circuit-Pack", 20),
me.CircuitPack_Version: ToOctets("v0.0.1", 20),
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -254,6 +270,7 @@
me.CircuitPack_OperationalState: 0,
me.CircuitPack_BridgedOrIpInd: 0,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -265,6 +282,7 @@
me.CircuitPack_TotalPriorityQueueNumber: 8,
me.CircuitPack_TotalTrafficSchedulerNumber: 16,
},
+ nil,
})
mibDb.items = append(mibDb.items, MibDbEntry{
me.CircuitPackClassID,
@@ -272,6 +290,7 @@
me.AttributeValueMap{
me.CircuitPack_PowerShedOverride: uint32(0),
},
+ nil,
})
}
@@ -304,6 +323,7 @@
me.PhysicalPathTerminationPointEthernetUni_PppoeFilter: 0,
me.PhysicalPathTerminationPointEthernetUni_PowerControl: 0,
},
+ nil,
})
} else {
// the remaining ones are pots UNIs, the same is done in onu.go
@@ -325,6 +345,7 @@
me.PhysicalPathTerminationPointPotsUni_NominalFeedVoltage: 0,
me.PhysicalPathTerminationPointPotsUni_LossOfSoftswitch: 0,
},
+ nil,
})
}
@@ -338,6 +359,7 @@
me.UniG_NonOmciManagementIdentifier: 0,
me.UniG_RelayAgentOptions: 0,
},
+ nil,
})
// Downstream Queues (related to PPTP)
@@ -351,6 +373,7 @@
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{},
+ nil,
})
// then we report it with the required attributes
@@ -373,6 +396,7 @@
me.PriorityQueue_BackPressureOccurQueueThreshold: 0,
me.PriorityQueue_BackPressureClearQueueThreshold: 0,
},
+ nil,
})
}
}
@@ -387,6 +411,7 @@
me.AttributeValueMap{
me.TCont_AllocId: 65535,
},
+ nil,
})
tsEntityId := EntityID{cardHolderSlotID, byte(i)}
@@ -399,6 +424,7 @@
me.TrafficScheduler_Policy: 02,
me.TrafficScheduler_PriorityWeight: 0,
},
+ nil,
})
for j := 1; j <= upstreamPriorityQueues; j++ {
@@ -412,6 +438,7 @@
me.PriorityQueueClassID,
queueEntityId, //was not reported in the original implementation
me.AttributeValueMap{},
+ nil,
})
// then we report it with the required attributes
@@ -434,6 +461,7 @@
me.PriorityQueue_BackPressureOccurQueueThreshold: 0,
me.PriorityQueue_BackPressureClearQueueThreshold: 0,
},
+ nil,
})
}
}
@@ -453,8 +481,41 @@
me.Onu2G_TotalPriorityQueueNumber: 64,
me.Onu2G_TotalTrafficSchedulerNumber: 8,
},
+ nil,
})
+ if common.Config.BBSim.InjectOmciUnknownAttributes {
+ // NOTE the TxID is actually replaced
+ // by SetTxIdInEncodedPacket in CreateMibUploadNextResponse
+ txId := uint16(33066)
+
+ b := make([]byte, 4)
+ binary.BigEndian.PutUint16(b, txId)
+ b[2] = byte(omci.MibUploadNextResponseType)
+ b[3] = byte(omci.BaselineIdent)
+ omciHdr := hex.EncodeToString(b)
+
+ //omciHdr := "00032e0a"
+ msgHdr := "00020000"
+ reportedMeHdr := "002500018000"
+ attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+ trailer := "0000002828ce00e2"
+ msg := omciHdr + msgHdr + reportedMeHdr + attr + trailer
+ data, err := hex.DecodeString(msg)
+ if err != nil {
+ omciLogger.Fatal("cannot-create-custom-packet")
+ }
+
+ packet := gopacket.NewPacket(data, omci.LayerTypeOMCI, gopacket.Lazy)
+
+ mibDb.items = append(mibDb.items, MibDbEntry{
+ me.ClassID(37), // G.988 "Intentionally left blank"
+ nil,
+ me.AttributeValueMap{},
+ packet.Data(),
+ })
+ }
+
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
index 2794aa4..7a589ad 100644
--- a/internal/common/omci/onu_mib_db_test.go
+++ b/internal/common/omci/onu_mib_db_test.go
@@ -17,9 +17,11 @@
package omci
import (
+ "fmt"
+ "github.com/google/gopacket"
+ "github.com/opencord/bbsim/internal/common"
"testing"
- "github.com/opencord/bbsim/internal/common"
"github.com/opencord/omci-lib-go/v2"
me "github.com/opencord/omci-lib-go/v2/generated"
"github.com/stretchr/testify/assert"
@@ -56,6 +58,11 @@
}
func Test_GenerateMibDatabase(t *testing.T) {
+ common.Config = &common.GlobalConfig{
+ BBSim: common.BBSimConfig{
+ InjectOmciUnknownAttributes: false,
+ },
+ }
const uniPortCount = 4
mibDb, err := GenerateMibDatabase(uniPortCount, 0, common.XGSPON)
@@ -93,6 +100,11 @@
}
func Test_GenerateMibDatabase_withPots(t *testing.T) {
+ common.Config = &common.GlobalConfig{
+ BBSim: common.BBSimConfig{
+ InjectOmciUnknownAttributes: false,
+ },
+ }
const uniPortCount = 4
const potsPortCount = 1
mibDb, err := GenerateMibDatabase(uniPortCount, potsPortCount, common.XGSPON)
@@ -129,3 +141,38 @@
}
}
+
+func Test_GenerateMibDatabase_withUnkownAttrs(t *testing.T) {
+
+ common.Config = &common.GlobalConfig{
+ BBSim: common.BBSimConfig{
+ InjectOmciUnknownAttributes: true,
+ },
+ }
+
+ const uniPortCount = 4
+ const baseMibEntries = 291 // see Test_GenerateMibDatabase for breakdown
+ const expectedMibEntries = baseMibEntries + 1 // expecting one hardcoded packet
+ mibDb, err := GenerateMibDatabase(uniPortCount, 0, common.XGSPON)
+
+ assert.NoError(t, err)
+ assert.NotNil(t, mibDb)
+ assert.Equal(t, expectedMibEntries, int(mibDb.NumberOfCommands))
+
+ entry := mibDb.items[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)
+ assert.Nil(t, entry.entityId)
+ assert.Equal(t, 0, len(entry.params))
+ assert.NotNil(t, entry.packet)
+
+ // check that we're generating a valid OMCI payload
+ packet := gopacket.NewPacket(entry.packet, omci.LayerTypeOMCI, gopacket.Lazy)
+ omciLayer := packet.Layer(omci.LayerTypeOMCI)
+ assert.NotNil(t, omciLayer)
+ omciMsg, ok := omciLayer.(*omci.OMCI)
+ assert.True(t, ok)
+ assert.Equal(t, omci.MibUploadNextResponseType, omciMsg.MessageType)
+ assert.Equal(t, uint16(33066), omciMsg.TransactionID)
+}