VOL-3983: Support for GET request/response extended message set
Change-Id: I9eab817f5c1bc918e18dd45de6bb3109db1e5cce
diff --git a/VERSION b/VERSION
index c5523bd..3eefcb9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.17.0
+1.0.0
diff --git a/generated/medef.go b/generated/medef.go
index 767e27b..4e91db6 100644
--- a/generated/medef.go
+++ b/generated/medef.go
@@ -141,7 +141,7 @@
data = data[len(valueBuffer):]
case byte(Set) | AR: // Set Request
- fmt.Println("TODO")
+ // TODO: No support at this time
case byte(SetTable) | AR: // Set Table Request
// TODO: Only baseline supported at this time
diff --git a/generated/omcidefs.go b/generated/omcidefs.go
index 8924e7d..5e845ff 100644
--- a/generated/omcidefs.go
+++ b/generated/omcidefs.go
@@ -105,6 +105,7 @@
TestResult MsgType = 27
GetCurrentData MsgType = 28
SetTable MsgType = 29 // Defined in Extended Message Set Only
+ ExtendedOffset MsgType = 0x80
)
func (mt MsgType) String() string {
diff --git a/layers.go b/layers.go
index 1bac6b3..aa49e8c 100644
--- a/layers.go
+++ b/layers.go
@@ -26,6 +26,7 @@
var nextLayerMapping map[MessageType]gopacket.LayerType
var (
+ // Baseline Message Types
LayerTypeCreateRequest gopacket.LayerType
LayerTypeDeleteRequest gopacket.LayerType
LayerTypeSetRequest gopacket.LayerType
@@ -47,8 +48,12 @@
LayerTypeGetNextRequest gopacket.LayerType
LayerTypeGetCurrentDataRequest gopacket.LayerType
LayerTypeSetTableRequest gopacket.LayerType
+
+ // Extended Message Types
+ LayerTypeGetRequestExtended gopacket.LayerType
)
var (
+ // Baseline Message Types
LayerTypeCreateResponse gopacket.LayerType
LayerTypeDeleteResponse gopacket.LayerType
LayerTypeSetResponse gopacket.LayerType
@@ -72,6 +77,9 @@
LayerTypeTestResult gopacket.LayerType
LayerTypeGetCurrentDataResponse gopacket.LayerType
LayerTypeSetTableResponse gopacket.LayerType
+
+ // Extended Message Types
+ LayerTypeGetResponseExtended gopacket.LayerType
)
func mkReqLayer(mt me.MsgType, mts string, decode gopacket.DecodeFunc) gopacket.LayerType {
@@ -139,6 +147,11 @@
LayerTypeGetCurrentDataResponse = mkRespLayer(me.GetCurrentData, "GetCurrentDataResponse", gopacket.DecodeFunc(decodeGetCurrentDataResponse))
LayerTypeSetTableResponse = mkRespLayer(me.SetTable, "SetTableResponse", gopacket.DecodeFunc(decodeSetTableResponse))
+ // Extended message set support
+
+ LayerTypeGetRequestExtended = mkReqLayer(me.Get|me.ExtendedOffset, "GetRequest-Ext", gopacket.DecodeFunc(decodeGetRequestExtended))
+ LayerTypeGetResponseExtended = mkRespLayer(me.Get|me.ExtendedOffset, "GetResponse-Ext", gopacket.DecodeFunc(decodeGetResponseExtended))
+
// Map message_type and action to layer
nextLayerMapping = make(map[MessageType]gopacket.LayerType)
@@ -188,12 +201,19 @@
nextLayerMapping[AttributeValueChangeType] = LayerTypeAttributeValueChange
nextLayerMapping[AlarmNotificationType] = LayerTypeAlarmNotification
nextLayerMapping[TestResultType] = LayerTypeTestResult
+
+ // Extended message support
+ nextLayerMapping[GetRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetRequestExtended
+ nextLayerMapping[GetResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetResponseExtended
}
-func MsgTypeToNextLayer(mt MessageType) (gopacket.LayerType, error) {
+func MsgTypeToNextLayer(mt MessageType, isExtended bool) (gopacket.LayerType, error) {
+ if isExtended {
+ mt |= ExtendedTypeDecodeOffset
+ }
nextLayer, ok := nextLayerMapping[mt]
if ok {
return nextLayer, nil
}
- return gopacket.LayerTypeZero, errors.New("unknown message type")
+ return gopacket.LayerTypeZero, errors.New("unknown/unsupported message type")
}
diff --git a/layers_test.go b/layers_test.go
index 2b99278..4b72a76 100644
--- a/layers_test.go
+++ b/layers_test.go
@@ -25,9 +25,9 @@
)
// Note: The majority of this file is tested by other unit tests
-func TestKnownMessageTytpe(t *testing.T) {
+func TestKnownMessageType(t *testing.T) {
for _, msg := range allMessageTypes {
- layer, err := omci.MsgTypeToNextLayer(msg)
+ layer, err := omci.MsgTypeToNextLayer(msg, false)
assert.NotEqual(t, layer, gopacket.LayerTypeZero)
assert.Nil(t, err)
}
@@ -36,9 +36,9 @@
assert.NotEqual(t, len(strMsg), 0)
}
-func TestUnknownMessageTytpe(t *testing.T) {
+func TestUnknownMessageType(t *testing.T) {
unknown := omci.MessageType(0xFF)
- layer, err := omci.MsgTypeToNextLayer(unknown)
+ layer, err := omci.MsgTypeToNextLayer(unknown, false)
assert.Equal(t, layer, gopacket.LayerTypeZero)
assert.NotNil(t, err)
}
diff --git a/mebase.go b/mebase.go
index 955e610..41f7a1f 100644
--- a/mebase.go
+++ b/mebase.go
@@ -32,6 +32,7 @@
gopacket.Layer
layers.BaseLayer
MsgLayerType gopacket.LayerType
+ Extended bool
}
func (msg *MeBasePacket) String() string {
diff --git a/meframe.go b/meframe.go
index 3c5ab53..37f04a5 100644
--- a/meframe.go
+++ b/meframe.go
@@ -414,6 +414,9 @@
}
func CreateRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// NOTE: The OMCI parser does not extract the default values of set-by-create attributes
// and are the zero 'default' (or nil) at this time. For this reason, make sure
// you specify all non-zero default values and pass them in appropriate
@@ -421,6 +424,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Attributes: m.GetAttributeValueMap(),
}
@@ -443,10 +447,14 @@
}
func CreateResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
meLayer := &CreateResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
}
@@ -457,20 +465,28 @@
}
func DeleteRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
meLayer := &DeleteRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
return meLayer, nil
}
func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
meLayer := &DeleteResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
}
@@ -493,11 +509,15 @@
// Get payload space available
maxPayload := maxPacketAvailable(m, opt)
payloadAvailable := int(maxPayload) - 2 // Less attribute mask
-
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ // payloadAvailable -= 2 // Less length
+ }
meLayer := &SetRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AttributeMask: 0,
Attributes: make(me.AttributeValueMap),
@@ -546,10 +566,14 @@
}
func SetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
meLayer := &SetResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
}
@@ -582,6 +606,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AttributeMask: mask,
}
@@ -601,6 +626,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
AttributeMask: 0,
@@ -666,11 +692,15 @@
}
func GetAllAlarmsRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &GetAllAlarmsRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AlarmRetrievalMode: opt.mode,
}
@@ -678,11 +708,15 @@
}
func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &GetAllAlarmsResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
NumberOfCommands: opt.sequenceNumberCountOrSize,
}
@@ -690,11 +724,15 @@
}
func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &GetAllAlarmsNextRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
CommandSequenceNumber: opt.sequenceNumberCountOrSize,
}
@@ -702,11 +740,15 @@
}
func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &GetAllAlarmsNextResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AlarmEntityClass: opt.alarm.AlarmClassID,
AlarmEntityInstance: opt.alarm.AlarmInstance,
@@ -724,22 +766,30 @@
}
func MibUploadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibUploadRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: 0,
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
return meLayer, nil
}
func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibUploadResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: 0,
+ Extended: opt.frameFormat == ExtendedIdent,
},
NumberOfCommands: opt.sequenceNumberCountOrSize,
}
@@ -747,11 +797,15 @@
}
func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibUploadNextRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: 0,
+ Extended: opt.frameFormat == ExtendedIdent,
},
CommandSequenceNumber: opt.sequenceNumberCountOrSize,
}
@@ -759,11 +813,15 @@
}
func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibUploadNextResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
if opt.payload == nil {
@@ -792,22 +850,30 @@
}
func MibResetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibResetRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
return meLayer, nil
}
func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &MibResetResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
}
@@ -815,6 +881,9 @@
}
func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -824,6 +893,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -837,6 +907,9 @@
}
func AttributeValueChangeFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -846,6 +919,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AttributeMask: 0,
Attributes: make(me.AttributeValueMap),
@@ -861,6 +935,9 @@
}
func TestRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -870,6 +947,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -882,6 +960,9 @@
}
func TestResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -891,6 +972,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -903,11 +985,15 @@
}
func StartSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &StartSoftwareDownloadRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
WindowSize: opt.software.WindowSize,
ImageSize: opt.software.ImageSize,
@@ -927,11 +1013,15 @@
}
func StartSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &StartSoftwareDownloadResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
WindowSize: opt.software.WindowSize,
NumberOfInstances: byte(len(opt.software.CircuitPacks)),
@@ -950,6 +1040,9 @@
}
func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -959,6 +1052,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -971,6 +1065,9 @@
}
func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -980,6 +1077,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -992,6 +1090,9 @@
}
func EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1001,6 +1102,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1013,6 +1115,9 @@
}
func EndSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1022,6 +1127,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1034,6 +1140,9 @@
}
func ActivateSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1043,6 +1152,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1055,6 +1165,9 @@
}
func ActivateSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1064,6 +1177,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1076,6 +1190,9 @@
}
func CommitSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1085,6 +1202,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1097,6 +1215,9 @@
}
func CommitSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1106,6 +1227,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1118,11 +1240,15 @@
}
func SynchronizeTimeRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &SynchronizeTimeRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Decode payload option. If nil, no timestamp provided
@@ -1139,11 +1265,15 @@
}
func SynchronizeTimeResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &SynchronizeTimeResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
SuccessResults: opt.mode,
@@ -1152,11 +1282,15 @@
}
func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &RebootRequest{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
RebootCondition: opt.mode,
}
@@ -1164,11 +1298,15 @@
}
func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Common for all MEs
meLayer := &RebootResponse{
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
}
@@ -1176,6 +1314,9 @@
}
func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Validate attribute mask
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
@@ -1195,6 +1336,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
AttributeMask: mask,
SequenceNumber: opt.sequenceNumberCountOrSize,
@@ -1203,6 +1345,9 @@
}
func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
// Validate attribute mask
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
@@ -1218,6 +1363,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
Result: opt.result,
AttributeMask: 0,
@@ -1274,6 +1420,9 @@
}
func TestResultFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1283,6 +1432,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1295,6 +1445,9 @@
}
func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1304,6 +1457,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1316,6 +1470,9 @@
}
func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1325,6 +1482,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1340,6 +1498,9 @@
if opt.frameFormat != ExtendedIdent {
return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
}
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
+ }
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
@@ -1349,6 +1510,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: opt.frameFormat == ExtendedIdent,
},
}
// Get payload space available
@@ -1362,7 +1524,10 @@
func SetTableResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
if opt.frameFormat != ExtendedIdent {
- return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
+ return nil, errors.New("SetTable message type only supported with Extended OMCI Message Set")
+ }
+ if opt.frameFormat == ExtendedIdent {
+ return nil, errors.New("Extended message set for this message type is not supported")
}
mask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
@@ -1373,6 +1538,7 @@
MeBasePacket: MeBasePacket{
EntityClass: m.GetClassID(),
EntityInstance: m.GetEntityID(),
+ Extended: true,
},
}
// Get payload space available
diff --git a/meframe_test.go b/meframe_test.go
index bd4c424..cf42492 100644
--- a/meframe_test.go
+++ b/meframe_test.go
@@ -27,10 +27,10 @@
"time"
)
-var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity)
+var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent)
func init() {
- messageTypeTestFuncs = make(map[MessageType]func(*testing.T, *me.ManagedEntity), 0)
+ messageTypeTestFuncs = make(map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent), 0)
messageTypeTestFuncs[CreateRequestType] = testCreateRequestTypeMeFrame
messageTypeTestFuncs[CreateResponseType] = testCreateResponseTypeMeFrame
@@ -75,6 +75,10 @@
messageTypeTestFuncs[AlarmNotificationType] = testAlarmNotificationTypeMeFrame
messageTypeTestFuncs[AttributeValueChangeType] = testAttributeValueChangeTypeMeFrame
messageTypeTestFuncs[TestResultType] = testTestResultTypeMeFrame
+
+ // Supported Extended message set types here
+ messageTypeTestFuncs[GetRequestType+ExtendedTypeDecodeOffset] = testGetRequestTypeMeFrame
+ messageTypeTestFuncs[GetResponseType+ExtendedTypeDecodeOffset] = testGetResponseTypeMeFrame
}
func getMEsThatSupportAMessageType(messageType MessageType) []*me.ManagedEntity {
@@ -93,8 +97,9 @@
}
func TestFrameFormatNotYetSupported(t *testing.T) {
- // We do not yet support extended frame formats. Once we do, add a bunch of tests
- // to cover it
+ // We do not yet support a few message types for the extended frame formats.
+ // As we do, add appropriate tests and change this to one that is not supported
+ // Until all are supported
params := me.ParamData{
Attributes: me.AttributeValueMap{"MibDataSync": 0},
@@ -103,7 +108,7 @@
assert.NotNil(t, omciErr)
assert.Equal(t, omciErr.StatusCode(), me.Success)
- buffer, err := GenFrame(managedEntity, GetRequestType, FrameFormat(ExtendedIdent), TransactionID(1))
+ buffer, err := GenFrame(managedEntity, SetRequestType, FrameFormat(ExtendedIdent), TransactionID(1))
assert.Nil(t, buffer)
assert.NotNil(t, err)
}
@@ -243,7 +248,22 @@
// Loop over all Managed Entities that support that type
for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
// Call the test routine
- testRoutine(t, managedEntity)
+ testRoutine(t, managedEntity, BaselineIdent)
+ //typeTested = true
+ }
+ }
+ // Verify at least one test ran for this message type
+ // TODO: Enable once all tests are working -> assert.True(t, typeTested)
+ }
+ // Now for the extended message set message types we support
+ for _, messageType := range allExtendedMessageTypes {
+ trueMessageType := messageType - ExtendedTypeDecodeOffset
+
+ if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
+ // Loop over all Managed Entities that support that type
+ for _, managedEntity := range getMEsThatSupportAMessageType(trueMessageType) {
+ // Call the test routine
+ testRoutine(t, managedEntity, ExtendedIdent)
//typeTested = true
}
}
@@ -355,7 +375,7 @@
}
}
-func testCreateRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testCreateRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// Generate the frame. Use a default Entity ID of zero, but for the
// OMCI library, we need to specify all supported Set-By-Create
params := me.ParamData{
@@ -376,7 +396,7 @@
assert.NotNil(t, err)
assert.Equal(t, err.StatusCode(), me.Success)
- frame, omciErr := GenFrame(meInstance, CreateRequestType, TransactionID(tid))
+ frame, omciErr := GenFrame(meInstance, CreateRequestType, TransactionID(tid), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -394,7 +414,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, CreateRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeCreateRequest)
assert.NotNil(t, msgLayer)
@@ -408,7 +428,7 @@
assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
}
-func testCreateResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testCreateResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -434,7 +454,7 @@
}
}
frame, omciErr := GenFrame(meInstance, CreateResponseType,
- TransactionID(tid), Result(result), AttributeExecutionMask(mask))
+ TransactionID(tid), Result(result), AttributeExecutionMask(mask), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -452,7 +472,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, CreateResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeCreateResponse)
assert.NotNil(t, msgLayer)
@@ -472,7 +492,7 @@
}
}
-func testDeleteRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testDeleteRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// Generate the frame. Use a default Entity ID of zero, but for the
// OMCI library, we need to specify all supported Set-By-Create
params := me.ParamData{
@@ -485,7 +505,7 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, DeleteRequestType, TransactionID(tid))
+ frame, omciErr := GenFrame(meInstance, DeleteRequestType, TransactionID(tid), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -503,7 +523,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, DeleteRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeDeleteRequest)
assert.NotNil(t, msgLayer)
@@ -516,7 +536,7 @@
assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
}
-func testDeleteResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testDeleteResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -528,7 +548,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
result := me.Results(rand.Int31n(7)) // [0, 6] Not all types will be tested
- frame, omciErr := GenFrame(meInstance, DeleteResponseType, TransactionID(tid), Result(result))
+ frame, omciErr := GenFrame(meInstance, DeleteResponseType, TransactionID(tid), Result(result),
+ FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -546,7 +567,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, DeleteResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeDeleteResponse)
assert.NotNil(t, msgLayer)
@@ -560,7 +581,7 @@
assert.Equal(t, result, msgObj.Result)
}
-func testSetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
Attributes: make(me.AttributeValueMap, 0),
@@ -592,7 +613,8 @@
assert.Equal(t, err.StatusCode(), me.Success)
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, SetRequestType, TransactionID(tid), AttributeMask(bitmask))
+ frame, omciErr := GenFrame(meInstance, SetRequestType, TransactionID(tid),
+ AttributeMask(bitmask), FrameFormat(messageSet))
// some frames cannot fit all the attributes
if omciErr != nil {
if _, ok := omciErr.(*me.MessageTruncatedError); ok {
@@ -615,7 +637,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, SetRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeSetRequest)
assert.NotNil(t, msgLayer)
@@ -629,7 +651,7 @@
assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
}
-func testSetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -665,7 +687,7 @@
frame, omciErr := GenFrame(meInstance, SetResponseType,
TransactionID(tid), Result(result),
- AttributeMask(bitmask),
+ AttributeMask(bitmask), FrameFormat(messageSet),
AttributeExecutionMask(failedMask),
UnsupportedAttributeMask(unsupportedMask))
assert.NotNil(t, frame)
@@ -685,7 +707,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, SetResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeSetResponse)
assert.NotNil(t, msgLayer)
@@ -707,7 +729,7 @@
}
}
-func testGetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
Attributes: make(me.AttributeValueMap, 0),
@@ -732,7 +754,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, GetRequestType, TransactionID(tid), AttributeMask(bitmask))
+ frame, omciErr := GenFrame(meInstance, GetRequestType, TransactionID(tid),
+ AttributeMask(bitmask), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -750,7 +773,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetRequest)
assert.NotNil(t, msgLayer)
@@ -764,137 +787,152 @@
assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
}
-func testGetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
Attributes: make(me.AttributeValueMap),
}
- tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- result := me.Results(rand.Int31n(10)) // [0, 9]
-
- // If success Results selected, set FailIfTruncated 50% of time to test
- // overflow detection and failures periodically.
- failIfTruncated := false
- if result == me.Success && rand.Int31n(2) == 1 {
- failIfTruncated = true
+ // Add loop to test all valid result codes for this message type
+ validResultCodes := []me.Results{
+ me.Success,
+ me.ProcessingError,
+ me.NotSupported,
+ me.ParameterError,
+ me.UnknownEntity,
+ me.UnknownInstance,
+ me.DeviceBusy,
+ me.AttributeFailure,
}
- // Always pass a failure mask, but should only get encoded if result == ParameterError
- var unsupportedMask uint16
- var failedMask uint16
- attrDefs := managedEntity.GetAttributeDefinitions()
- for _, attrDef := range attrDefs {
- if attrDef.Index == 0 {
- continue // Skip entity ID, already specified
+ for _, result := range validResultCodes {
+ tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- } else if attrDef.GetAccess().Contains(me.Read) {
- // Random 10% chance this parameter unsupported and
- // 10% it failed
- switch rand.Int31n(5) {
- default:
- // TODO: Table attributes not yet supported. For Table Attributes, figure out a
- // good way to unit test this and see if that can be extended to a more
- // general operation that provides the 'get-next' frames to the caller who
- // wishes to serialize a table attribute.
- if !attrDef.IsTableAttribute() {
- params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+ // If success Results selected, set FailIfTruncated 50% of time to test
+ // overflow detection and failures periodically. This is primarily for
+ // baseline message set for those MEs that may have lots of attribute space
+ // needed. If extended message set, always fail if truncated since we should
+ // be able to stuff as much as we want (at least for now in these unit tests)
+ failIfTruncated := false
+ if result == me.Success && (rand.Int31n(2) == 1 || messageSet == ExtendedIdent) {
+ failIfTruncated = true
+ }
+ // Always pass a failure mask, but should only get encoded if result == ParameterError
+ var unsupportedMask uint16
+ var failedMask uint16
+ attrDefs := managedEntity.GetAttributeDefinitions()
+ for _, attrDef := range attrDefs {
+ if attrDef.Index == 0 {
+ continue // Skip entity ID, already specified
+
+ } else if attrDef.GetAccess().Contains(me.Read) {
+ // Random 5% chance this parameter unsupported and
+ // 5% it failed
+ switch rand.Int31n(20) {
+ default:
+ // TODO: Table attributes not yet supported. For Table Attributes, figure out a
+ // good way to unit test this and see if that can be extended to a more
+ // general operation that provides the 'get-next' frames to the caller who
+ // wishes to serialize a table attribute.
+ if !attrDef.IsTableAttribute() {
+ params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+ }
+ case 0:
+ unsupportedMask |= attrDef.Mask
+ case 1:
+ failedMask |= attrDef.Mask
}
- case 0:
- unsupportedMask |= attrDef.Mask
- case 1:
- failedMask |= attrDef.Mask
}
}
- }
- bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
- assert.Nil(t, attrErr)
+ bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+ assert.Nil(t, attrErr)
- // Create the managed instance
- meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+ // Create the managed instance
+ meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
- frame, omciErr := GenFrame(meInstance, GetResponseType,
- TransactionID(tid), Result(result),
- AttributeMask(bitmask),
- AttributeExecutionMask(failedMask),
- UnsupportedAttributeMask(unsupportedMask),
- FailIfTruncated(failIfTruncated))
+ frame, omciErr := GenFrame(meInstance, GetResponseType,
+ TransactionID(tid), Result(result),
+ AttributeMask(bitmask), FrameFormat(messageSet),
+ AttributeExecutionMask(failedMask),
+ UnsupportedAttributeMask(unsupportedMask),
+ FailIfTruncated(failIfTruncated))
- // TODO: Need to test if err is MessageTruncatedError. Sometimes reported as
- // a proessing error
- if omciErr != nil {
- if _, ok := omciErr.(*me.MessageTruncatedError); ok {
- return
+ // TODO: Need to test if err is MessageTruncatedError. Sometimes reported as
+ // a proessing error
+ if omciErr != nil {
+ if _, ok := omciErr.(*me.MessageTruncatedError); ok {
+ return
+ }
}
- }
- assert.NotNil(t, frame)
- assert.NotZero(t, len(frame))
- assert.NotNil(t, err)
- assert.Equal(t, err.StatusCode(), me.Success)
+ assert.NotNil(t, frame)
+ assert.NotZero(t, len(frame))
+ assert.NotNil(t, err)
+ assert.Equal(t, err.StatusCode(), me.Success)
- ///////////////////////////////////////////////////////////////////
- // Now decode and compare
- packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
- assert.NotNil(t, packet)
+ ///////////////////////////////////////////////////////////////////
+ // Now decode and compare
+ packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+ assert.NotNil(t, packet)
- omciLayer := packet.Layer(LayerTypeOMCI)
- assert.NotNil(t, omciLayer)
+ omciLayer := packet.Layer(LayerTypeOMCI)
+ assert.NotNil(t, omciLayer)
- omciObj, omciOk := omciLayer.(*OMCI)
- assert.NotNil(t, omciObj)
- assert.True(t, omciOk)
- assert.Equal(t, tid, omciObj.TransactionID)
- assert.Equal(t, GetResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ omciObj, omciOk := omciLayer.(*OMCI)
+ assert.NotNil(t, omciObj)
+ assert.True(t, omciOk)
+ assert.Equal(t, tid, omciObj.TransactionID)
+ assert.Equal(t, GetResponseType, omciObj.MessageType)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
- msgLayer := packet.Layer(LayerTypeGetResponse)
- // If requested Result was Success and FailIfTruncated is true, then we may
- // fail (get nil layer) if too many attributes to fit in a frame
- if result == me.Success && msgLayer == nil {
- return // was expected
- }
- assert.NotNil(t, msgLayer)
-
- msgObj, msgOk := msgLayer.(*GetResponse)
- assert.NotNil(t, msgObj)
- assert.True(t, msgOk)
-
- assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
- assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-
- switch msgObj.Result {
- default:
- assert.Equal(t, result, msgObj.Result)
- assert.Zero(t, msgObj.FailedAttributeMask)
- assert.Zero(t, msgObj.UnsupportedAttributeMask)
-
- case me.Success:
- assert.Equal(t, result, msgObj.Result)
- assert.Zero(t, msgObj.FailedAttributeMask)
- assert.Zero(t, msgObj.UnsupportedAttributeMask)
- assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
-
- case me.AttributeFailure:
- // Should have been Success or AttributeFailure to start with
- assert.True(t, result == me.Success || result == me.AttributeFailure)
- if result == me.AttributeFailure {
- assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
+ msgLayer := packet.Layer(LayerTypeGetResponse)
+ // If requested Result was Success and FailIfTruncated is true, then we may
+ // fail (get nil layer) if too many attributes to fit in a frame
+ if result == me.Success && msgLayer == nil {
+ return // was expected
}
- // Returned may have more bits set in failed mask and less attributes
- // since failIfTruncated is false and we may add more fail attributes
- // since they do not fit. May also set only lower value (lower bits)
- // if it turns out that the upper bits are already pre-assigned to the
- // failure bits.
- //
- // Make sure any successful attributes were requested
- meMap := meInstance.GetAttributeValueMap()
- for name := range msgObj.Attributes {
- getValue, ok := meMap[name]
- assert.True(t, ok)
- assert.NotNil(t, getValue)
+ assert.NotNil(t, msgLayer)
+
+ msgObj, msgOk := msgLayer.(*GetResponse)
+ assert.NotNil(t, msgObj)
+ assert.True(t, msgOk)
+
+ assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+ assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+
+ switch msgObj.Result {
+ default:
+ assert.Equal(t, result, msgObj.Result)
+ assert.Zero(t, msgObj.FailedAttributeMask)
+ assert.Zero(t, msgObj.UnsupportedAttributeMask)
+
+ case me.Success:
+ assert.Equal(t, result, msgObj.Result)
+ assert.Zero(t, msgObj.FailedAttributeMask)
+ assert.Zero(t, msgObj.UnsupportedAttributeMask)
+ assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
+
+ case me.AttributeFailure:
+ // Should have been Success or AttributeFailure to start with
+ assert.True(t, result == me.Success || result == me.AttributeFailure)
+ if result == me.AttributeFailure {
+ assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
+ }
+ // Returned may have more bits set in failed mask and less attributes
+ // since failIfTruncated is false and we may add more fail attributes
+ // since they do not fit. May also set only lower value (lower bits)
+ // if it turns out that the upper bits are already pre-assigned to the
+ // failure bits.
+ //
+ // Make sure any successful attributes were requested
+ meMap := meInstance.GetAttributeValueMap()
+ for name := range msgObj.Attributes {
+ getValue, ok := meMap[name]
+ assert.True(t, ok)
+ assert.NotNil(t, getValue)
+ }
}
}
}
-func testGetAllAlarmsRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetAllAlarmsRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -906,7 +944,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
mode := uint8(rand.Int31n(2)) // [0, 1]
- frame, omciErr := GenFrame(meInstance, GetAllAlarmsRequestType, TransactionID(tid), RetrievalMode(mode))
+ frame, omciErr := GenFrame(meInstance, GetAllAlarmsRequestType, TransactionID(tid),
+ RetrievalMode(mode), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -924,7 +963,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetAllAlarmsRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
assert.NotNil(t, msgLayer)
@@ -938,7 +977,7 @@
assert.Equal(t, mode, msgObj.AlarmRetrievalMode)
}
-func testGetAllAlarmsResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetAllAlarmsResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -951,7 +990,7 @@
numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
frame, omciErr := GenFrame(meInstance, GetAllAlarmsResponseType, TransactionID(tid),
- SequenceNumberCountOrSize(numOfCommands))
+ SequenceNumberCountOrSize(numOfCommands), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -969,7 +1008,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetAllAlarmsResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
assert.NotNil(t, msgLayer)
@@ -983,7 +1022,7 @@
assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
}
-func testGetAllAlarmsNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetAllAlarmsNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -996,7 +1035,7 @@
sequenceNumber := uint16(rand.Int31n(5)) // [0, 5)
frame, omciErr := GenFrame(meInstance, GetAllAlarmsNextRequestType, TransactionID(tid),
- SequenceNumberCountOrSize(sequenceNumber))
+ SequenceNumberCountOrSize(sequenceNumber), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1014,7 +1053,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetAllAlarmsNextRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
assert.NotNil(t, msgLayer)
@@ -1028,7 +1067,7 @@
assert.Equal(t, sequenceNumber, msgObj.CommandSequenceNumber)
}
-func testGetAllAlarmsNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetAllAlarmsNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1049,7 +1088,7 @@
alarmInfo.AlarmBitmap[octet] = uint8(rand.Intn(256))
}
frame, omciErr := GenFrame(meInstance, GetAllAlarmsNextResponseType, TransactionID(tid),
- Alarm(alarmInfo))
+ Alarm(alarmInfo), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1067,7 +1106,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetAllAlarmsNextResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
assert.NotNil(t, msgLayer)
@@ -1085,7 +1124,7 @@
}
}
-func testMibUploadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibUploadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1096,7 +1135,7 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, MibUploadRequestType, TransactionID(tid))
+ frame, omciErr := GenFrame(meInstance, MibUploadRequestType, TransactionID(tid), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1114,7 +1153,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibUploadRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibUploadRequest)
assert.NotNil(t, msgLayer)
@@ -1127,7 +1166,7 @@
assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
}
-func testMibUploadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibUploadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1140,7 +1179,7 @@
numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
frame, omciErr := GenFrame(meInstance, MibUploadResponseType, TransactionID(tid),
- SequenceNumberCountOrSize(numOfCommands))
+ SequenceNumberCountOrSize(numOfCommands), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1158,7 +1197,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibUploadResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibUploadResponse)
assert.NotNil(t, msgLayer)
@@ -1172,7 +1211,7 @@
assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
}
-func testMibUploadNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibUploadNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1186,7 +1225,7 @@
var frame []byte
frame, omciErr := GenFrame(meInstance, MibUploadNextRequestType, TransactionID(tid),
- SequenceNumberCountOrSize(seqNumber))
+ SequenceNumberCountOrSize(seqNumber), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1204,7 +1243,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibUploadNextRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
assert.NotNil(t, msgLayer)
@@ -1218,7 +1257,7 @@
assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
}
-func testMibUploadNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibUploadNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1232,7 +1271,8 @@
// TODO: Since only baseline messages supported, send only one ME
uploadMe := meInstance
- frame, omciErr := GenFrame(meInstance, MibUploadNextResponseType, TransactionID(tid), Payload(uploadMe))
+ frame, omciErr := GenFrame(meInstance, MibUploadNextResponseType, TransactionID(tid),
+ Payload(uploadMe), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1250,7 +1290,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibUploadNextResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
assert.NotNil(t, msgLayer)
@@ -1265,7 +1305,7 @@
assert.Equal(t, uploadMe.GetEntityID(), msgObj.ReportedME.GetEntityID())
}
-func testMibResetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibResetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1276,7 +1316,7 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, MibResetRequestType, TransactionID(tid))
+ frame, omciErr := GenFrame(meInstance, MibResetRequestType, TransactionID(tid), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1294,7 +1334,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibResetRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibResetRequest)
assert.NotNil(t, msgLayer)
@@ -1307,7 +1347,7 @@
assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
}
-func testMibResetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testMibResetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1319,7 +1359,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
result := me.Results(rand.Int31n(7)) // [0, 6] Not all types will be tested
- frame, omciErr := GenFrame(meInstance, MibResetResponseType, TransactionID(tid), Result(result))
+ frame, omciErr := GenFrame(meInstance, MibResetResponseType, TransactionID(tid),
+ Result(result), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1337,7 +1378,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, MibResetResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeMibResetResponse)
assert.NotNil(t, msgLayer)
@@ -1351,15 +1392,15 @@
assert.Equal(t, result, msgObj.Result)
}
-func testTestRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testTestRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testTestResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testTestResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testStartSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testStartSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
instance := uint16(0) // ONU-G
image := uint16(1)
params := me.ParamData{
@@ -1376,7 +1417,8 @@
ImageSize: uint32(rand.Int31n(0x100000) + 0x100000), // [1 Meg, 2M-1]
CircuitPacks: []uint16{0}, // [1 Meg, 2M-1]
}
- frame, omciErr := GenFrame(meInstance, StartSoftwareDownloadRequestType, TransactionID(tid), Software(options))
+ frame, omciErr := GenFrame(meInstance, StartSoftwareDownloadRequestType,
+ TransactionID(tid), Software(options), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1394,7 +1436,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, StartSoftwareDownloadRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
assert.NotNil(t, msgLayer)
@@ -1413,43 +1455,43 @@
}
}
-func testStartSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testStartSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testDownloadSectionRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testDownloadSectionRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testDownloadSectionResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testDownloadSectionResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testEndSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testEndSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testEndSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testEndSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testActivateSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testActivateSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testActivateSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testActivateSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testCommitSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testCommitSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testCommitSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testCommitSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testSynchronizeTimeRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSynchronizeTimeRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1462,7 +1504,8 @@
tm := time.Now().UTC()
tmUnix := tm.Unix()
- frame, omciErr := GenFrame(meInstance, SynchronizeTimeRequestType, TransactionID(tid), Payload(tmUnix))
+ frame, omciErr := GenFrame(meInstance, SynchronizeTimeRequestType, TransactionID(tid),
+ Payload(tmUnix), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1480,7 +1523,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, SynchronizeTimeRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
assert.NotNil(t, msgLayer)
@@ -1500,7 +1543,7 @@
assert.Equal(t, uint8(tm.Second()), msgObj.Second)
}
-func testSynchronizeTimeResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSynchronizeTimeResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1515,7 +1558,7 @@
var frame []byte
frame, omciErr := GenFrame(meInstance, SynchronizeTimeResponseType, TransactionID(tid),
- Result(result), SuccessResult(successResult))
+ Result(result), SuccessResult(successResult), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1533,7 +1576,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, SynchronizeTimeResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
assert.NotNil(t, msgLayer)
@@ -1552,7 +1595,7 @@
}
}
-func testRebootRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testRebootRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1564,7 +1607,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
condition := uint8(rand.Int31n(3)) // [0, 3]
- frame, omciErr := GenFrame(meInstance, RebootRequestType, TransactionID(tid), RebootCondition(condition))
+ frame, omciErr := GenFrame(meInstance, RebootRequestType, TransactionID(tid),
+ RebootCondition(condition), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1582,7 +1626,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, RebootRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeRebootRequest)
assert.NotNil(t, msgLayer)
@@ -1596,7 +1640,7 @@
assert.Equal(t, condition, msgObj.RebootCondition)
}
-func testRebootResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testRebootResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
}
@@ -1608,7 +1652,8 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
result := me.Results(rand.Int31n(7)) // [0, 6] Not all types will be tested
- frame, omciErr := GenFrame(meInstance, RebootResponseType, TransactionID(tid), Result(result))
+ frame, omciErr := GenFrame(meInstance, RebootResponseType, TransactionID(tid),
+ Result(result), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1626,7 +1671,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, RebootResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeRebootResponse)
assert.NotNil(t, msgLayer)
@@ -1640,7 +1685,7 @@
assert.Equal(t, result, msgObj.Result)
}
-func testGetNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
Attributes: make(me.AttributeValueMap, 0),
@@ -1678,8 +1723,8 @@
seqNumber := uint16(rand.Int31n(0xFFFF)) // [0, 0xFFFE]
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
- frame, omciErr := GenFrame(meInstance, GetNextRequestType, TransactionID(tid), SequenceNumberCountOrSize(seqNumber),
- AttributeMask(bitmask))
+ frame, omciErr := GenFrame(meInstance, GetNextRequestType, TransactionID(tid),
+ SequenceNumberCountOrSize(seqNumber), AttributeMask(bitmask), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1697,7 +1742,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetNextRequestType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetNextRequest)
assert.NotNil(t, msgLayer)
@@ -1712,7 +1757,7 @@
assert.Equal(t, seqNumber, msgObj.SequenceNumber)
}
-func testGetNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
params := me.ParamData{
EntityID: uint16(0),
Attributes: make(me.AttributeValueMap, 0),
@@ -1756,7 +1801,7 @@
tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
frame, omciErr := GenFrame(meInstance, GetNextResponseType, TransactionID(tid), Result(result),
- AttributeMask(bitmask))
+ AttributeMask(bitmask), FrameFormat(messageSet))
assert.NotNil(t, frame)
assert.NotZero(t, len(frame))
assert.Nil(t, omciErr)
@@ -1776,7 +1821,7 @@
assert.True(t, omciOk)
assert.Equal(t, tid, omciObj.TransactionID)
assert.Equal(t, GetNextResponseType, omciObj.MessageType)
- assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+ assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
msgLayer := packet.Layer(LayerTypeGetNextResponse)
assert.NotNil(t, msgLayer)
@@ -1814,30 +1859,30 @@
}
}
-func testGetCurrentDataRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetCurrentDataRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testGetCurrentDataResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testGetCurrentDataResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testSetTableRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSetTableRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testSetTableResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testSetTableResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testAlarmNotificationTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testAlarmNotificationTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testAttributeValueChangeTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testAttributeValueChangeTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
-func testTestResultTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity) {
+func testTestResultTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
// TODO: Implement
}
diff --git a/messagetypes.go b/messagetypes.go
index f0ff447..0d48458 100644
--- a/messagetypes.go
+++ b/messagetypes.go
@@ -74,6 +74,9 @@
AlarmNotificationType = MessageType(byte(me.AlarmNotification))
AttributeValueChangeType = MessageType(byte(me.AttributeValueChange))
TestResultType = MessageType(byte(me.TestResult))
+
+ // Support mapping of extended format types (use MSB reserved bit)
+ ExtendedTypeDecodeOffset = MessageType(byte(0x80))
)
func (mt MessageType) String() string {
@@ -125,7 +128,7 @@
return "Start Software Download Request"
case StartSoftwareDownloadResponseType:
return "Start Software Download Response"
- case DownloadSectionRequestType:
+ case DownloadSectionRequestType, DownloadSectionRequestWithResponseType:
return "Download Section Request"
case DownloadSectionResponseType:
return "Download Section Response"
@@ -649,7 +652,15 @@
if !me.SupportsMsgType(meDefinition, me.Get) {
return me.NewProcessingError("managed entity does not support Get Message-Type")
}
- omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+ if omci.Extended {
+ if len(data) < 8 {
+ p.SetTruncated()
+ return errors.New("frame too small")
+ }
+ omci.AttributeMask = binary.BigEndian.Uint16(data[6:])
+ } else {
+ omci.AttributeMask = binary.BigEndian.Uint16(data[4:])
+ }
return nil
}
@@ -659,6 +670,13 @@
return decodingLayerDecoder(omci, data, p)
}
+func decodeGetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+ omci := &GetRequest{}
+ omci.MsgLayerType = LayerTypeGetRequest
+ omci.Extended = true
+ return decodingLayerDecoder(omci, data, p)
+}
+
// SerializeTo provides serialization of an Get Request message
func (omci *GetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
// Basic (common) OMCI Header is 8 octets, 10
@@ -675,11 +693,22 @@
if !me.SupportsMsgType(meDefinition, me.Get) {
return me.NewProcessingError("managed entity does not support Get Message-Type")
}
- bytes, err := b.AppendBytes(2)
+ maskOffset := 0
+ if omci.Extended {
+ maskOffset = 2
+ }
+ bytes, err := b.AppendBytes(2 + maskOffset)
if err != nil {
return err
}
- binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+ if omci.Extended {
+ binary.BigEndian.PutUint16(bytes, uint16(2))
+ }
+ binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+ return nil
+}
+
+func (omci *GetRequest) SerializeToExtended(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
return nil
}
@@ -716,33 +745,56 @@
if !me.SupportsMsgType(meDefinition, me.Get) {
return me.NewProcessingError("managed entity does not support Get Message-Type")
}
- omci.Result = me.Results(data[4])
- omci.AttributeMask = binary.BigEndian.Uint16(data[5:7])
+ if omci.Extended {
+ if len(data) < 13 {
+ p.SetTruncated()
+ return errors.New("frame too small")
+ }
+ omci.Result = me.Results(data[6])
+ omci.AttributeMask = binary.BigEndian.Uint16(data[7:])
+ // If Attribute failed or Unknown, decode optional attribute mask
+ if omci.Result == me.AttributeFailure {
+ omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[9:])
+ omci.FailedAttributeMask = binary.BigEndian.Uint16(data[11:])
+ }
+ } else {
+ omci.Result = me.Results(data[4])
+ omci.AttributeMask = binary.BigEndian.Uint16(data[5:])
+
+ // If Attribute failed or Unknown, decode optional attribute mask
+ if omci.Result == me.AttributeFailure {
+ omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:34])
+ omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:36])
+ }
+ }
// Attribute decode. Note that the ITU-T G.988 specification states that the
// Unsupported and Failed attribute masks are always present
// but only valid if the status code== 9. However some XGS
// ONUs (T&W and Alpha, perhaps more) will use these last 4
// octets for data if the status code == 0. So accommodate
// this behaviour in favor of greater interoperability.
+ firstOctet := 7
lastOctet := 36
+ if omci.Extended {
+ firstOctet = 13
+ lastOctet = len(data)
+ }
switch omci.Result {
case me.ProcessingError, me.NotSupported, me.UnknownEntity, me.UnknownInstance, me.DeviceBusy:
return nil // Done (do not try and decode attributes)
case me.AttributeFailure:
- lastOctet = 32
+ if !omci.Extended {
+ lastOctet = 32
+ }
}
- omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[7:lastOctet], p, byte(GetResponseType))
+ omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask,
+ data[firstOctet:lastOctet], p, byte(GetResponseType))
if err != nil {
return err
}
- // If Attribute failed or Unknown, decode optional attribute mask
- if omci.Result == me.AttributeFailure {
- omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:34])
- omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:36])
- }
// Validate all attributes support read
for attrName := range omci.Attributes {
attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
@@ -767,6 +819,13 @@
return decodingLayerDecoder(omci, data, p)
}
+func decodeGetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+ omci := &GetResponse{}
+ omci.MsgLayerType = LayerTypeGetResponse
+ omci.Extended = true
+ return decodingLayerDecoder(omci, data, p)
+}
+
// SerializeTo provides serialization of an Get Response message
func (omci *GetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
// Basic (common) OMCI Header is 8 octets, 10
@@ -783,16 +842,27 @@
if !me.SupportsMsgType(meDefinition, me.Get) {
return me.NewProcessingError("managed entity does not support the Get Message-Type")
}
- bytes, err := b.AppendBytes(3)
+ resultOffset := 0
+ attributeErrExtra := 0
+
+ if omci.Extended {
+ resultOffset = 2
+ attributeErrExtra = 4 // Attribute mask + attribute error masks
+ }
+ // Space for result + mask (both types) + (len & error masks if extended)
+ buffer, err := b.AppendBytes(3 + resultOffset + attributeErrExtra)
if err != nil {
return err
}
- bytes[0] = byte(omci.Result)
- binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
+ // Save result and initial mask. Other header fields updated after
+ // attribute copy
+ buffer[resultOffset] = byte(omci.Result)
+ binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
// Validate all attributes support read
for attrName := range omci.Attributes {
- attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+ var attr *me.AttributeDefinition
+ attr, err = me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
if err != nil {
return err
}
@@ -804,52 +874,77 @@
// Attribute serialization
switch omci.Result {
default:
+ if omci.Extended {
+ // Minimum length is 7 for extended an need to write error masks
+ binary.BigEndian.PutUint16(buffer, uint16(7))
+ binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
+ }
break
case me.Success, me.AttributeFailure:
// TODO: Baseline only supported at this time)
- available := MaxBaselineLength - 11 - 4 - 8
-
+ var available int
+ if omci.Extended {
+ available = MaxExtendedLength - 18 - 4 // Less: header, mic
+ } else {
+ available = MaxBaselineLength - 11 - 4 - 8 // Less: header, failed attributes, length, mic
+ }
// Serialize to temporary buffer if we may need to reset values due to
// recoverable truncation errors
- origBuffer := b
- b := gopacket.NewSerializeBuffer()
+ attributeBuffer := gopacket.NewSerializeBuffer()
+ var failedMask uint16
+ err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
+ attributeBuffer, byte(GetResponseType), available, opts.FixLengths)
- err, failedMask := meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b, byte(GetResponseType),
- available, opts.FixLengths)
-
- if err == nil && failedMask != 0 && opts.FixLengths {
+ if err != nil {
+ return err
+ }
+ if failedMask != 0 {
// Not all attributes would fit
omci.FailedAttributeMask |= failedMask
omci.AttributeMask &= ^failedMask
omci.Result = me.AttributeFailure
// Adjust already recorded values
- bytes[0] = byte(omci.Result)
- binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
- } else if err != nil {
- return err
+ buffer[resultOffset] = byte(omci.Result)
+ binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
+ }
+ if omci.Extended {
+ // Set length and any failure masks
+ binary.BigEndian.PutUint16(buffer, uint16(len(attributeBuffer.Bytes())+7))
+
+ if omci.Result == me.AttributeFailure {
+ binary.BigEndian.PutUint16(buffer[resultOffset+3:], omci.UnsupportedAttributeMask)
+ binary.BigEndian.PutUint16(buffer[resultOffset+5:], omci.FailedAttributeMask)
+ } else {
+ binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
+ }
}
// Copy over attributes to the original serialization buffer
- newSpace, err := origBuffer.AppendBytes(len(b.Bytes()))
+ var newSpace []byte
+
+ newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
if err != nil {
return err
}
- copy(newSpace, b.Bytes())
- b = origBuffer
+ copy(newSpace, attributeBuffer.Bytes())
- // Calculate space left. Max - msgType header - OMCI trailer - spacedUsedSoFar
- bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
+ if !omci.Extended {
+ // Calculate space left. Max - msgType header - OMCI trailer - spacedUsedSoFar
+ bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
- remainingBytes, err := b.AppendBytes(bytesLeft + 4)
- if err != nil {
- return me.NewMessageTruncatedError(err.Error())
- }
- copy(remainingBytes, lotsOfZeros[:])
+ var remainingBytes []byte
+ remainingBytes, err = b.AppendBytes(bytesLeft + 4)
- if omci.Result == me.AttributeFailure {
- binary.BigEndian.PutUint16(remainingBytes[bytesLeft-4:bytesLeft-2], omci.UnsupportedAttributeMask)
- binary.BigEndian.PutUint16(remainingBytes[bytesLeft-2:bytesLeft], omci.FailedAttributeMask)
+ if err != nil {
+ return me.NewMessageTruncatedError(err.Error())
+ }
+ copy(remainingBytes, lotsOfZeros[:])
+
+ if omci.Result == me.AttributeFailure {
+ binary.BigEndian.PutUint16(remainingBytes[bytesLeft-4:bytesLeft-2], omci.UnsupportedAttributeMask)
+ binary.BigEndian.PutUint16(remainingBytes[bytesLeft-2:bytesLeft], omci.FailedAttributeMask)
+ }
}
}
return nil
diff --git a/messagetypes_test.go b/messagetypes_test.go
index 64b3be3..514bc79 100644
--- a/messagetypes_test.go
+++ b/messagetypes_test.go
@@ -18,6 +18,7 @@
import (
"encoding/base64"
+ "encoding/binary"
"fmt"
"github.com/google/gopacket"
. "github.com/opencord/omci-lib-go"
@@ -99,6 +100,11 @@
TestResultType,
}
+var allExtendedMessageTypes = [...]MessageType{
+ GetRequestType,
+ GetResponseType,
+}
+
var allResults = [...]me.Results{
me.Success,
me.ProcessingError,
@@ -3024,3 +3030,232 @@
packetString := packet.String()
assert.NotZero(t, len(packetString))
}
+
+func TestExtendedGetRequestDecode(t *testing.T) {
+ //ONU-2G: 257
+ goodMessage := "035e490b010100000002fffc"
+ data, err := stringToPacket(goodMessage)
+ assert.NoError(t, err)
+
+ packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+ assert.NotNil(t, packet)
+
+ omciLayer := packet.Layer(LayerTypeOMCI)
+ assert.NotNil(t, packet)
+
+ omciMsg, ok := omciLayer.(*OMCI)
+ assert.True(t, ok)
+ assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
+ assert.Equal(t, omciMsg.MessageType, GetRequestType)
+ assert.Equal(t, omciMsg.DeviceIdentifier, ExtendedIdent)
+ assert.Equal(t, omciMsg.Length, uint16(2))
+
+ msgLayer := packet.Layer(LayerTypeGetRequest)
+ assert.NotNil(t, msgLayer)
+
+ request, ok2 := msgLayer.(*GetRequest)
+ assert.True(t, ok2)
+ assert.NotNil(t, request)
+
+ //ONU-2G: 257
+ assert.Equal(t, me.Onu2GClassID, request.EntityClass)
+ assert.Equal(t, uint16(0), request.EntityInstance)
+ assert.Equal(t, uint16(0xfffc), request.AttributeMask)
+
+ // Verify string output for message
+ packetString := packet.String()
+ assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetRequestSerialize(t *testing.T) {
+ goodMessage := "035e490b010100000002fffc"
+
+ omciLayer := &OMCI{
+ TransactionID: 0x035e,
+ MessageType: GetRequestType,
+ DeviceIdentifier: ExtendedIdent,
+ // Length parameter is optional for Extended message format serialization
+ // and if present it will be overwritten during the serialization with the
+ // actual value.
+ }
+ request := &GetRequest{
+ MeBasePacket: MeBasePacket{
+ EntityClass: me.Onu2GClassID,
+ EntityInstance: uint16(0),
+ Extended: true,
+ },
+ AttributeMask: uint16(0xfffc),
+ }
+ // Test serialization back to former string
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
+
+ buffer := gopacket.NewSerializeBuffer()
+ err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+ assert.NoError(t, err)
+
+ outgoingPacket := buffer.Bytes()
+ reconstituted := packetToString(outgoingPacket)
+ assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedGetResponseDecode(t *testing.T) {
+ attrDef, omciErr := me.GetAttributesDefinitions(me.Onu2GClassID)
+ assert.NotNil(t, attrDef)
+ assert.NotNil(t, omciErr)
+ assert.Equal(t, omciErr.StatusCode(), me.Success)
+
+ attributes := []interface{}{
+ toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), // 1: MultiByteField - "EquipmentId" (20 zeros)
+ byte(0xb4), // 2: ByteField - "OpticalNetworkUnitManagementAndControlChannelOmccVersion"
+ uint16(0x1234), // 3: Uint16Field - "VendorProductCode"
+ byte(1), // 4: ByteField - "SecurityCapability"
+ byte(1), // 5: ByteField - "SecurityMode"
+ uint16(0x5678), // 6: Uint16Field - "TotalPriorityQueueNumber"
+ byte(0x44), // 7: ByteField - "TotalTrafficSchedulerNumber"
+ byte(1), // 8: ByteField - "Deprecated"
+ uint16(0x55aa), // 9: Uint16Field - "TotalGemPortIdNumber"
+ uint32(0xC4108011), // 10: Uint32Field - "Sysuptime"
+ uint16(0x6), // 11: Uint16Field - "ConnectivityCapability"
+ byte(6), // 12: ByteField - "CurrentConnectivityMode"
+ uint16(2), // 13: Uint16Field - "QualityOfServiceQosConfigurationFlexibility"
+ uint16(0x1234), // 14: Uint16Field - "PriorityQueueScaleFactor"
+ }
+ attributeData := make([]byte, 0)
+
+ // Walk through all attributes and encode them
+ for _, value := range attributes {
+ //attrDef, err := meDef.GetAttributeByIndex(index)
+ var buf []byte
+ u8, ok := value.(byte)
+ if ok {
+ buf = []byte{u8}
+ } else {
+ u16, ok := value.(uint16)
+ if ok {
+ buf = make([]byte, 2)
+ binary.BigEndian.PutUint16(buf, u16)
+ } else {
+ u32, ok := value.(uint32)
+ if ok {
+ buf = make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, u32)
+ } else {
+ bytes, ok := value.([]byte)
+ if ok {
+ buf = bytes
+ } else {
+ assert.True(t, false) // Unknown attribute type
+ }
+ }
+ }
+ }
+ attributeData = append(attributeData, buf...)
+ }
+ attributeMask := 0xfffc
+ msgLength := len(attributeData) + 7
+ // Results is 0 ("00"), and the two optional attribute masks are 0 ("00000000") as well
+ goodMessage := "035e290b01010000" + fmt.Sprintf("%04x", msgLength) +
+ "00" + fmt.Sprintf("%04x", attributeMask) + "00000000" + packetToString(attributeData)
+
+ data, err := stringToPacket(goodMessage)
+ assert.NotNil(t, data)
+ assert.Nil(t, err)
+
+ packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+ assert.NotNil(t, packet)
+
+ omciLayer := packet.Layer(LayerTypeOMCI)
+ assert.NotNil(t, omciLayer)
+
+ omciMsg, ok := omciLayer.(*OMCI)
+ assert.True(t, ok)
+ assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
+ assert.Equal(t, omciMsg.MessageType, GetResponseType)
+ assert.Equal(t, omciMsg.DeviceIdentifier, ExtendedIdent)
+ assert.Equal(t, omciMsg.Length, uint16(msgLength))
+
+ msgLayer := packet.Layer(LayerTypeGetResponse)
+ assert.NotNil(t, msgLayer)
+
+ response, ok2 := msgLayer.(*GetResponse)
+ assert.True(t, ok2)
+ assert.NotNil(t, response)
+ assert.Equal(t, response.Result, me.Success)
+ assert.Equal(t, response.AttributeMask, uint16(attributeMask))
+ assert.Equal(t, response.FailedAttributeMask, uint16(0))
+ assert.Equal(t, response.UnsupportedAttributeMask, uint16(0))
+
+ assert.Equal(t, response.Attributes["EquipmentId"], toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="))
+ assert.Equal(t, response.Attributes["OpticalNetworkUnitManagementAndControlChannelOmccVersion"], byte(0xb4)) // )
+ assert.Equal(t, response.Attributes["VendorProductCode"], uint16(0x1234))
+ assert.Equal(t, response.Attributes["SecurityCapability"], byte(1))
+ assert.Equal(t, response.Attributes["SecurityMode"], byte(1))
+ assert.Equal(t, response.Attributes["TotalPriorityQueueNumber"], uint16(0x5678))
+ assert.Equal(t, response.Attributes["TotalTrafficSchedulerNumber"], byte(0x44))
+ assert.Equal(t, response.Attributes["Deprecated"], byte(1))
+ assert.Equal(t, response.Attributes["TotalGemPortIdNumber"], uint16(0x55aa))
+ assert.Equal(t, response.Attributes["Sysuptime"], uint32(0xC4108011))
+ assert.Equal(t, response.Attributes["ConnectivityCapability"], uint16(0x6))
+ assert.Equal(t, response.Attributes["CurrentConnectivityMode"], byte(6))
+ assert.Equal(t, response.Attributes["QualityOfServiceQosConfigurationFlexibility"], uint16(2))
+ assert.Equal(t, response.Attributes["PriorityQueueScaleFactor"], uint16(0x1234))
+
+ // Verify string output for message
+ packetString := packet.String()
+ assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetResponseSerialize(t *testing.T) {
+ goodMessage := "035e290b01010000003100fffc" +
+ "000000000000000000000000000000000000000000000000" +
+ "b4123401015678440155aac410801100060600021234"
+
+ omciLayer := &OMCI{
+ TransactionID: 0x035e,
+ MessageType: GetResponseType,
+ DeviceIdentifier: ExtendedIdent,
+ // Length parameter is optional for Extended message format serialization
+ // and if present it will be overwritten during the serialization with the
+ // actual value.
+ }
+ request := &GetResponse{
+ MeBasePacket: MeBasePacket{
+ EntityClass: me.Onu2GClassID,
+ EntityInstance: uint16(0),
+ Extended: true,
+ },
+ Result: 0,
+ AttributeMask: uint16(0xfffc),
+ Attributes: me.AttributeValueMap{
+ "EquipmentId": toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
+ "OpticalNetworkUnitManagementAndControlChannelOmccVersion": byte(0xb4),
+ "VendorProductCode": uint16(0x1234),
+ "SecurityCapability": byte(1),
+ "SecurityMode": byte(1),
+ "TotalPriorityQueueNumber": uint16(0x5678),
+ "TotalTrafficSchedulerNumber": byte(0x44),
+ "Deprecated": byte(1),
+ "TotalGemPortIdNumber": uint16(0x55aa),
+ "Sysuptime": uint32(0xC4108011),
+ "ConnectivityCapability": uint16(0x6),
+ "CurrentConnectivityMode": byte(6),
+ "QualityOfServiceQosConfigurationFlexibility": uint16(2),
+ "PriorityQueueScaleFactor": uint16(0x1234),
+ },
+ }
+ // Test serialization back to former string
+ var options gopacket.SerializeOptions
+ options.FixLengths = true
+
+ buffer := gopacket.NewSerializeBuffer()
+ err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+ assert.NoError(t, err)
+
+ outgoingPacket := buffer.Bytes()
+ reconstituted := packetToString(outgoingPacket)
+ assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+// TODO: Also remember to add extended message tests to the meframe_test.go
+// unit tests as more message types are supported
diff --git a/omci.go b/omci.go
index 9b7f881..a303a65 100644
--- a/omci.go
+++ b/omci.go
@@ -157,7 +157,7 @@
func decodeOMCI(data []byte, p gopacket.PacketBuilder) error {
// Allow baseline messages without Length & MIC, but no less
- if len(data) < MaxBaselineLength-8 {
+ if len(data) < 4 {
return errors.New("frame header too small")
}
switch DeviceIdent(data[3]) {
@@ -165,12 +165,16 @@
return errors.New("unsupported message type")
case BaselineIdent:
- //omci := &BaselineMessage{}
+ if len(data) < MaxBaselineLength-8 {
+ return errors.New("frame too small")
+ }
omci := &OMCI{}
return omci.DecodeFromBytes(data, p)
case ExtendedIdent:
- //omci := &ExtendedMessage{}
+ if len(data) < 10 {
+ return errors.New("extended frame header too small")
+ }
omci := &OMCI{}
return omci.DecodeFromBytes(data, p)
}
@@ -217,10 +221,12 @@
// Decode length
var payloadOffset int
var micOffset int
+ var eomOffset int
if omci.DeviceIdentifier == BaselineIdent {
omci.Length = MaxBaselineLength - 8
payloadOffset = 8
micOffset = MaxBaselineLength - 4
+ eomOffset = MaxBaselineLength - 8
if len(data) >= micOffset {
length := binary.BigEndian.Uint32(data[micOffset-4:])
@@ -232,14 +238,13 @@
payloadOffset = 10
omci.Length = binary.BigEndian.Uint16(data[8:10])
micOffset = int(omci.Length) + payloadOffset
+ eomOffset = micOffset
- if omci.Length > MaxExtendedLength {
+ if omci.Length > uint16(MaxExtendedLength-payloadOffset) {
return me.NewProcessingError("extended frame exceeds maximum allowed")
}
- if int(omci.Length) != micOffset {
- if int(omci.Length) < micOffset {
- p.SetTruncated()
- }
+ if len(data) < micOffset {
+ p.SetTruncated()
return me.NewProcessingError("extended frame too small")
}
}
@@ -253,9 +258,9 @@
//return errors.New(msg)
}
}
- omci.BaseLayer = layers.BaseLayer{Contents: data[:4], Payload: data[4:omci.Length]}
+ omci.BaseLayer = layers.BaseLayer{data[:4], data[4:eomOffset]}
p.AddLayer(omci)
- nextLayer, err := MsgTypeToNextLayer(omci.MessageType)
+ nextLayer, err := MsgTypeToNextLayer(omci.MessageType, omci.DeviceIdentifier == ExtendedIdent)
if err != nil {
return err
}
@@ -266,8 +271,6 @@
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (omci *OMCI) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- // TODO: Hardcoded for baseline message format for now. Will eventually need to support
- // the extended message format.
bytes, err := b.PrependBytes(4)
if err != nil {
return err
@@ -288,11 +291,11 @@
return errors.New(msg)
}
} else if omci.DeviceIdentifier == ExtendedIdent {
- if omci.Length == 0 {
- omci.Length = uint16(len(bytes) - 10) // Allow uninitialized length
- }
- if omci.Length > MaxExtendedLength {
- msg := fmt.Sprintf("invalid Baseline message length: %v", omci.Length)
+ omci.Length = uint16(len(b.Bytes()) - 10)
+
+ // Is length larger than maximum packet (less header and trailing MIC)
+ if omci.Length > MaxExtendedLength-10-4 {
+ msg := fmt.Sprintf("invalid Extended message length: %v", omci.Length)
return errors.New(msg)
}
} else {
@@ -311,17 +314,20 @@
bytes[3] = byte(omci.DeviceIdentifier)
b.PushLayer(LayerTypeOMCI)
- bufLen := len(b.Bytes())
- padSize := int(omci.Length) - bufLen + 4
- if padSize < 0 {
- msg := fmt.Sprintf("invalid OMCI Message Type length, exceeded allowed frame size by %d bytes",
- -padSize)
- return errors.New(msg)
- }
- padding, err := b.AppendBytes(padSize)
- copy(padding, lotsOfZeros[:])
-
if omci.DeviceIdentifier == BaselineIdent {
+ bufLen := len(b.Bytes())
+ padSize := int(omci.Length) - bufLen + 4
+ if padSize < 0 {
+ msg := fmt.Sprintf("invalid OMCI Message Type length, exceeded allowed frame size by %d bytes",
+ -padSize)
+ return errors.New(msg)
+ }
+ padding, err := b.AppendBytes(padSize)
+ if err != nil {
+ return err
+ }
+ copy(padding, lotsOfZeros[:])
+
// For baseline, always provide the length
binary.BigEndian.PutUint32(b.Bytes()[MaxBaselineLength-8:], 40)
}