| /* |
| * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net) |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * NOTE: This file was generated, manual edits will be overwritten! |
| * |
| * Generated by 'goCodeGenerator.py': |
| * https://github.com/opencord/omci-lib-go/OMCI-parser/README.md |
| */ |
| |
| package omci |
| |
| import ( |
| "errors" |
| "fmt" |
| "github.com/deckarep/golang-set" |
| "github.com/google/gopacket" |
| me "github.com/opencord/omci-lib-go/generated" |
| "time" |
| ) |
| |
| var encoderMap map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error) |
| |
| func init() { |
| encoderMap = make(map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error)) |
| |
| encoderMap[CreateRequestType] = CreateRequestFrame |
| encoderMap[DeleteRequestType] = DeleteRequestFrame |
| encoderMap[SetRequestType] = SetRequestFrame |
| encoderMap[GetRequestType] = GetRequestFrame |
| encoderMap[GetAllAlarmsRequestType] = GetAllAlarmsRequestFrame |
| encoderMap[GetAllAlarmsNextRequestType] = GetAllAlarmsNextRequestFrame |
| encoderMap[MibUploadRequestType] = MibUploadRequestFrame |
| encoderMap[MibUploadNextRequestType] = MibUploadNextRequestFrame |
| encoderMap[MibResetRequestType] = MibResetRequestFrame |
| //encoderMap[TestRequestType] = TestRequestFrame |
| encoderMap[StartSoftwareDownloadRequestType] = StartSoftwareDownloadRequestFrame |
| encoderMap[DownloadSectionRequestType] = DownloadSectionRequestFrame |
| encoderMap[EndSoftwareDownloadRequestType] = EndSoftwareDownloadRequestFrame |
| encoderMap[ActivateSoftwareRequestType] = ActivateSoftwareRequestFrame |
| encoderMap[CommitSoftwareRequestType] = CommitSoftwareRequestFrame |
| encoderMap[SynchronizeTimeRequestType] = SynchronizeTimeRequestFrame |
| encoderMap[RebootRequestType] = RebootRequestFrame |
| encoderMap[GetNextRequestType] = GetNextRequestFrame |
| encoderMap[GetCurrentDataRequestType] = GetCurrentDataRequestFrame |
| encoderMap[SetTableRequestType] = SetTableRequestFrame |
| encoderMap[CreateResponseType] = CreateResponseFrame |
| encoderMap[DeleteResponseType] = DeleteResponseFrame |
| encoderMap[SetResponseType] = SetResponseFrame |
| encoderMap[GetResponseType] = GetResponseFrame |
| encoderMap[GetAllAlarmsResponseType] = GetAllAlarmsResponseFrame |
| encoderMap[GetAllAlarmsNextResponseType] = GetAllAlarmsNextResponseFrame |
| encoderMap[MibUploadResponseType] = MibUploadResponseFrame |
| encoderMap[MibUploadNextResponseType] = MibUploadNextResponseFrame |
| encoderMap[MibResetResponseType] = MibResetResponseFrame |
| //encoderMap[TestResponseType] = TestResponseFrame |
| encoderMap[StartSoftwareDownloadResponseType] = StartSoftwareDownloadResponseFrame |
| encoderMap[DownloadSectionResponseType] = DownloadSectionResponseFrame |
| encoderMap[EndSoftwareDownloadResponseType] = EndSoftwareDownloadResponseFrame |
| encoderMap[ActivateSoftwareResponseType] = ActivateSoftwareResponseFrame |
| encoderMap[CommitSoftwareResponseType] = CommitSoftwareResponseFrame |
| encoderMap[SynchronizeTimeResponseType] = SynchronizeTimeResponseFrame |
| encoderMap[RebootResponseType] = RebootResponseFrame |
| encoderMap[GetNextResponseType] = GetNextResponseFrame |
| encoderMap[GetCurrentDataResponseType] = GetCurrentDataResponseFrame |
| encoderMap[SetTableResponseType] = SetTableResponseFrame |
| encoderMap[AlarmNotificationType] = AlarmNotificationFrame |
| encoderMap[AttributeValueChangeType] = AttributeValueChangeFrame |
| //encoderMap[TestResultType] = TestResultFrame |
| } |
| |
| type options struct { |
| frameFormat DeviceIdent |
| failIfTruncated bool |
| attributeMask uint16 |
| result me.Results // Common for many responses |
| attrExecutionMask uint16 // Create Response Only if results == 3 or Set Response only if results == 0 |
| unsupportedMask uint16 // Set Response only if results == 9 |
| sequenceNumberCountOrSize uint16 // For get-next request frames and for frames that return number of commands or length |
| transactionID uint16 // OMCI TID |
| mode uint8 // Get All Alarms retrieval mode |
| alarm AlarmOptions // Alarm related frames |
| software SoftwareOptions // Software image related frames |
| payload interface{} // ME or list of MEs, alarm bitmap, timestamp, ... |
| addDefaults bool // Add missing SetByCreate attributes for Create Requests |
| } |
| |
| var defaultFrameOptions = options{ |
| frameFormat: BaselineIdent, |
| failIfTruncated: false, |
| attributeMask: 0xFFFF, |
| result: me.Success, |
| attrExecutionMask: 0, |
| unsupportedMask: 0, |
| sequenceNumberCountOrSize: 0, |
| transactionID: 0, |
| mode: 0, |
| software: defaultSoftwareOptions, |
| alarm: defaultAlarmOptions, |
| payload: nil, |
| addDefaults: false, |
| } |
| |
| // FrameOption sets options such as frame format, etc. |
| type FrameOption func(*options) |
| |
| // FrameFormat determines determines the OMCI message format used on the fiber. |
| // The default value is BaselineIdent |
| func FrameFormat(ff DeviceIdent) FrameOption { |
| return func(o *options) { |
| o.frameFormat = ff |
| } |
| } |
| |
| // FailIfTruncated determines whether a request to encode a frame that does |
| // not have enough room for all requested options should fail and return an |
| // error. |
| // |
| // If set to 'false', the behaviour depends on the message type/operation |
| // requested. The table below provides more information: |
| // |
| // Request Type Behavour |
| // ------------------------------------------------------------------------ |
| // CreateRequest A single CreateRequest struct is always returned as the |
| // CreateRequest message does not have an attributes Mask |
| // field and a Baseline OMCI message is large enough to |
| // support all Set-By-Create attributes. |
| // |
| // GetResponse If multiple OMCI response frames are needed to return |
| // all requested attributes, only the attributes that can |
| // fit will be returned and the FailedAttributeMask field |
| // set to the attributes that could not be returned |
| // |
| // If this is an ME with an attribute that is a table, the |
| // first GetResponse struct will return the size of the |
| // attribute and the following GetNextResponse structs will |
| // contain the attribute data. The ONU application is |
| // responsible for stashing these extra struct(s) away in |
| // anticipation of possible GetNext Requests occurring for |
| // the attribute. See the discussion on Table attributes |
| // in the GetResponse section of ITU G.988 for more |
| // information. |
| // |
| // If set to 'true', no struct(s) are returned and an error is provided. |
| // |
| // The default value is 'false' |
| func FailIfTruncated(f bool) FrameOption { |
| return func(o *options) { |
| o.failIfTruncated = f |
| } |
| } |
| |
| // attributeMask determines the attributes to encode into the frame. |
| // The default value is 0xFFFF which specifies all available attributes |
| // in the frame |
| func AttributeMask(m uint16) FrameOption { |
| return func(o *options) { |
| o.attributeMask = m |
| } |
| } |
| |
| // AttributeExecutionMask is used by the Create and Set Response frames to indicate |
| // attributes that failed to be created/set. |
| func AttributeExecutionMask(m uint16) FrameOption { |
| return func(o *options) { |
| o.attrExecutionMask = m |
| } |
| } |
| |
| // UnsupportedAttributeMask is used by the Set Response frames to indicate |
| // attributes are not supported on this ONU |
| func UnsupportedAttributeMask(m uint16) FrameOption { |
| return func(o *options) { |
| o.unsupportedMask = m |
| } |
| } |
| |
| // Result is used to set returned results in responses |
| // that have that field |
| func Result(r me.Results) FrameOption { |
| return func(o *options) { |
| o.result = r |
| } |
| } |
| |
| // SequenceNumberCountOrSize is used by the GetNext and MibUploadGetNext request frames and for |
| // frames that return number of commands or length such as Get (table attribute) or |
| // MibUpload/GetAllAlarms/... |
| func SequenceNumberCountOrSize(m uint16) FrameOption { |
| return func(o *options) { |
| o.sequenceNumberCountOrSize = m |
| } |
| } |
| |
| // TransactionID is to specify the TID in the OMCI header. The default is |
| // zero which requires the caller to set it to the appropriate value if this |
| // is not an autonomous ONU notification frame |
| func TransactionID(tid uint16) FrameOption { |
| return func(o *options) { |
| o.transactionID = tid |
| } |
| } |
| |
| // RetrievalMode is to specify the the Alarm Retrieval Mode in a GetAllAlarms Request |
| func RetrievalMode(m uint8) FrameOption { |
| return func(o *options) { |
| o.mode = m |
| } |
| } |
| |
| // SuccessResult is to specify the the SuccessResult for a SynchronizeTime Response |
| func SuccessResult(m uint8) FrameOption { |
| return func(o *options) { |
| o.mode = m |
| } |
| } |
| |
| // RebootCondition is to specify the the Reboot Condition for a ONU Reboot request |
| func RebootCondition(m uint8) FrameOption { |
| return func(o *options) { |
| o.mode = m |
| } |
| } |
| |
| // Alarm is used to specify a collection of options related to Alarm notifications |
| func Alarm(ao AlarmOptions) FrameOption { |
| return func(o *options) { |
| o.alarm = ao |
| } |
| } |
| |
| // Software is used to specify a collection of options related to Software image |
| // manipulation |
| func Software(so SoftwareOptions) FrameOption { |
| return func(o *options) { |
| o.software = so |
| } |
| } |
| |
| // Payload is used to specify ME payload options that are not simple types. This |
| // include the ME (list of MEs) to encode into a GetNextMibUpload response, the |
| // alarm bitmap for alarm relates responses/notifications, alarm bitmaps, and |
| // for specifying the download section data when performing Software Download. |
| func Payload(p interface{}) FrameOption { |
| return func(o *options) { |
| o.payload = p |
| } |
| } |
| |
| // AddDefaults is used to specify that if a SetByCreate attribute is not |
| // specified in the list of attributes for a Create Request, use the attribute |
| // defined default |
| func AddDefaults(add bool) FrameOption { |
| return func(o *options) { |
| o.addDefaults = add |
| } |
| } |
| |
| // Alarm related frames have a wide variety of settable values. Placing them |
| // in a separate struct is mainly to keep the base options simple |
| type AlarmOptions struct { |
| AlarmClassID me.ClassID |
| AlarmInstance uint16 |
| AlarmBitmap []byte // Should be up to 58 octets |
| } |
| |
| var defaultAlarmOptions = AlarmOptions{ |
| AlarmClassID: 0, |
| AlarmInstance: 0, |
| AlarmBitmap: nil, |
| } |
| |
| // Software related frames have a wide variety of settable values. Placing them |
| // in a separate struct is mainly to keep the base options simple |
| type SoftwareOptions struct { |
| WindowSize uint8 // Window size - 1 |
| SectionNumber uint8 // [0..Window size - 1] |
| ImageSize uint32 |
| CircuitPacks []uint16 // slot (upper 8 bits) and instance (lower 8 bits) |
| Results []DownloadResults |
| Data []byte |
| } |
| |
| var defaultSoftwareOptions = SoftwareOptions{ |
| WindowSize: 0, |
| SectionNumber: 0, |
| ImageSize: 0, |
| CircuitPacks: nil, |
| Results: nil, |
| Data: nil, |
| } |
| |
| // EncodeFrame will encode the Managed Entity specific protocol struct and an |
| // OMCILayer struct. This struct can be provided to the gopacket.SerializeLayers() |
| // function to be serialized into a buffer for transmission. |
| func EncodeFrame(m *me.ManagedEntity, messageType MessageType, opt ...FrameOption) (*OMCI, gopacket.SerializableLayer, error) { |
| // Check for message type support |
| msgType := me.MsgType(messageType & me.MsgTypeMask) |
| meDefinition := m.GetManagedEntityDefinition() |
| |
| if !me.SupportsMsgType(meDefinition, msgType) { |
| msg := fmt.Sprintf("managed entity %v does not support %v Message-Type", |
| meDefinition.GetName(), msgType) |
| return nil, nil, errors.New(msg) |
| } |
| // Decode options |
| opts := defaultFrameOptions |
| for _, o := range opt { |
| o(&opts) |
| } |
| // TODO: If AttributesMask option passed in, check for deprecated options. Allow encoding option |
| // that will ignore deprecated option. Add additional in the get and set meframe_test,go |
| // test functions to test this. Also have it test attribute name(s) to see if the attribute |
| // is deprecated. The OMCI-Parser now supports detection of deprecated attributes and |
| // provides that to the code-generator (and currently available in generated golang code). |
| // Note: Transaction ID should be set before frame serialization |
| omci := &OMCI{ |
| TransactionID: opts.transactionID, |
| MessageType: messageType, |
| DeviceIdentifier: opts.frameFormat, |
| } |
| var meInfo gopacket.SerializableLayer |
| var err error |
| |
| if encoder, ok := encoderMap[messageType]; ok { |
| meInfo, err = encoder(m, opts) |
| } else { |
| err = fmt.Errorf("message-type: %v/%#x is not supported", messageType, messageType) |
| } |
| if err != nil { |
| return nil, nil, err |
| } |
| return omci, meInfo, err |
| } |
| |
| // For most all create methods below, error checking for valid masks, attribute |
| // values, and other fields is left to when the frame is actually serialized. |
| |
| func checkAttributeMask(m *me.ManagedEntity, mask uint16) (uint16, error) { |
| if mask == defaultFrameOptions.attributeMask { |
| // Scale back to just what is allowed |
| return m.GetAllowedAttributeMask(), nil |
| } |
| if mask&m.GetManagedEntityDefinition().GetAllowedAttributeMask() != mask { |
| return 0, errors.New("invalid attribute mask") |
| } |
| return mask & m.GetManagedEntityDefinition().GetAllowedAttributeMask(), nil |
| } |
| |
| // return the maximum space that can be used by attributes |
| func maxPacketAvailable(m *me.ManagedEntity, opt options) uint { |
| if opt.frameFormat == BaselineIdent { |
| // OMCI Header - 4 octets |
| // Class ID/Instance ID - 4 octets |
| // Length field - 4 octets |
| // MIC - 4 octets |
| return MaxBaselineLength - 16 |
| } |
| // OMCI Header - 4 octets |
| // Class ID/Instance ID - 4 octets |
| // Length field - 2 octets |
| // MIC - 4 octets |
| return MaxExtendedLength - 14 |
| } |
| |
| func calculateAttributeMask(m *me.ManagedEntity, requestedMask uint16) (uint16, error) { |
| attrDefs := m.GetAttributeDefinitions() |
| var entityIDName string |
| if entry, ok := attrDefs[0]; ok { |
| entityIDName = entry.GetName() |
| } else { |
| panic("unexpected error") // All attribute definition maps have an entity ID |
| } |
| attributeNames := make([]interface{}, 0) |
| for attrName := range m.GetAttributeValueMap() { |
| if attrName == entityIDName { |
| continue // No mask for EntityID |
| } |
| attributeNames = append(attributeNames, attrName) |
| } |
| calculatedMask, err := me.GetAttributesBitmap(attrDefs, mapset.NewSetWith(attributeNames...)) |
| |
| if err != nil { |
| return 0, err |
| } |
| return calculatedMask & requestedMask, nil |
| } |
| |
| // GenFrame is a helper function to make tests a little easier to read. |
| // For a real application, use the .../omci/generated/class.go 'New' |
| // functions to create your Managed Entity and then use it to call the |
| // EncodeFrame method. |
| func GenFrame(meInstance *me.ManagedEntity, messageType MessageType, options ...FrameOption) ([]byte, error) { |
| omciLayer, msgLayer, err := EncodeFrame(meInstance, messageType, options...) |
| if err != nil { |
| return nil, err |
| } |
| // Serialize the frame and send it |
| var serializeOptions gopacket.SerializeOptions |
| serializeOptions.FixLengths = true |
| |
| buffer := gopacket.NewSerializeBuffer() |
| err = gopacket.SerializeLayers(buffer, serializeOptions, omciLayer, msgLayer) |
| if err != nil { |
| return nil, err |
| } |
| return buffer.Bytes(), nil |
| } |
| |
| 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 |
| meLayer := &CreateRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| Attributes: m.GetAttributeValueMap(), |
| } |
| // Add any missing SetByCreate options if requested |
| if opt.addDefaults { |
| if attrDefs, err := me.GetAttributesDefinitions(m.GetClassID()); err.StatusCode() == me.Success { |
| for index, attr := range attrDefs { |
| if me.SupportsAttributeAccess(attr, me.SetByCreate) { |
| if index == 0 { |
| continue // Skip Entity ID, if it is SetByCreate, they should always specify it |
| } |
| if _, found := meLayer.Attributes[attr.GetName()]; !found { |
| meLayer.Attributes[attr.GetName()] = attr.DefValue |
| } |
| } |
| } |
| } |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| if meLayer.Result == me.ParameterError { |
| meLayer.AttributeExecutionMask = opt.attrExecutionMask |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| func SetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) { |
| mask, err := checkAttributeMask(m, opt.attributeMask) |
| if err != nil { |
| return nil, err |
| } |
| mask, err = calculateAttributeMask(m, mask) |
| if err != nil { |
| return nil, err |
| } |
| meDefinition := m.GetManagedEntityDefinition() |
| attrDefs := meDefinition.GetAttributeDefinitions() |
| attrMap := m.GetAttributeValueMap() |
| |
| // 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), |
| } |
| for mask != 0 { |
| // Iterate down the attributes (Attribute 0 is the ManagedEntity ID) |
| var attrIndex uint |
| for attrIndex = 1; attrIndex <= 16; attrIndex++ { |
| // Is this attribute requested |
| if mask&(1<<(16-attrIndex)) != 0 { |
| // Get definitions since we need the name |
| attrDef, ok := attrDefs[attrIndex] |
| if !ok { |
| msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v", |
| attrIndex, meDefinition.GetName()) |
| return nil, errors.New(msg) |
| } |
| var attrValue interface{} |
| attrValue, ok = attrMap[attrDef.Name] |
| if !ok { |
| msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v", |
| attrDef.GetName(), meDefinition.GetName(), m) |
| return nil, errors.New(msg) |
| } |
| // Is space available? |
| if attrDef.Size <= payloadAvailable { |
| // Mark bit handled |
| mask &= ^attrDef.Mask |
| meLayer.AttributeMask |= attrDef.Mask |
| meLayer.Attributes[attrDef.Name] = attrValue |
| payloadAvailable -= attrDef.Size |
| } else { |
| // TODO: Should we set truncate? |
| msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into SetRequest message", |
| attrDef.GetName()) |
| return nil, me.NewMessageTruncatedError(msg) |
| } |
| } |
| } |
| } |
| if err == nil && meLayer.AttributeMask == 0 { |
| // TODO: Is a set request with no attributes valid? |
| return nil, errors.New("no attributes encoded for SetRequest") |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| if meLayer.Result == me.AttributeFailure { |
| meLayer.UnsupportedAttributeMask = opt.unsupportedMask |
| meLayer.FailedAttributeMask = opt.attrExecutionMask |
| } |
| return meLayer, nil |
| } |
| |
| func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) { |
| // Given mask sent in (could be default of 0xFFFF) get what is allowable. |
| // This will be all allowed if 0xFFFF is passed in, or a subset if a fixed |
| // number of items. |
| maxMask, err := checkAttributeMask(m, opt.attributeMask) |
| if err != nil { |
| return nil, err |
| } |
| // Now scan attributes and reduce mask to only those requested |
| var mask uint16 |
| mask, err = calculateAttributeMask(m, maxMask) |
| if err != nil { |
| return nil, err |
| } |
| if mask == 0 { |
| // TODO: Is a Get request with no attributes valid? |
| return nil, errors.New("no attributes requested for GetRequest") |
| } |
| meLayer := &GetRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| AttributeMask: mask, |
| } |
| return meLayer, nil |
| } |
| |
| func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) { |
| mask, err := checkAttributeMask(m, opt.attributeMask) |
| if err != nil { |
| return nil, err |
| } |
| mask, err = calculateAttributeMask(m, mask) |
| if err != nil { |
| return nil, err |
| } |
| meLayer := &GetResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| Result: opt.result, |
| AttributeMask: 0, |
| Attributes: make(me.AttributeValueMap), |
| } |
| if meLayer.Result == me.AttributeFailure { |
| meLayer.UnsupportedAttributeMask = opt.unsupportedMask |
| meLayer.FailedAttributeMask = opt.attrExecutionMask |
| } |
| // Encode whatever we can |
| if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure { |
| // Encode results |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding |
| meDefinition := m.GetManagedEntityDefinition() |
| attrDefs := meDefinition.GetAttributeDefinitions() |
| attrMap := m.GetAttributeValueMap() |
| |
| if mask != 0 { |
| // Iterate down the attributes (Attribute 0 is the ManagedEntity ID) |
| var attrIndex uint |
| for attrIndex = 1; attrIndex <= 16; attrIndex++ { |
| // Is this attribute requested |
| if mask&(1<<(16-attrIndex)) != 0 { |
| // Get definitions since we need the name |
| attrDef, ok := attrDefs[attrIndex] |
| if !ok { |
| msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v", |
| attrIndex, meDefinition.GetName()) |
| return nil, errors.New(msg) |
| } |
| var attrValue interface{} |
| attrValue, ok = attrMap[attrDef.Name] |
| if !ok { |
| msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v", |
| attrDef.GetName(), meDefinition.GetName(), m) |
| return nil, errors.New(msg) |
| } |
| // Is space available? |
| if attrDef.Size <= payloadAvailable { |
| // Mark bit handled |
| mask &= ^attrDef.Mask |
| meLayer.AttributeMask |= attrDef.Mask |
| meLayer.Attributes[attrDef.Name] = attrValue |
| payloadAvailable -= attrDef.Size |
| |
| } else if opt.failIfTruncated { |
| // TODO: Should we set truncate? |
| msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message", |
| attrDef.GetName()) |
| return nil, me.NewMessageTruncatedError(msg) |
| } else { |
| // Add to existing 'failed' mask and update result |
| meLayer.FailedAttributeMask |= attrDef.Mask |
| meLayer.Result = me.AttributeFailure |
| } |
| } |
| } |
| } |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| if len(opt.alarm.AlarmBitmap) > 28 { |
| return nil, errors.New("invalid Alarm Bitmap Size. Must be [0..27]") |
| } |
| for octet := 0; octet < len(opt.alarm.AlarmBitmap); octet++ { |
| meLayer.AlarmBitMap[octet] = opt.alarm.AlarmBitmap[octet] |
| } |
| for octet := len(opt.alarm.AlarmBitmap); octet < 28; octet++ { |
| meLayer.AlarmBitMap[octet] = 0 |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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 { |
| // Shortcut used to specify the request sequence number is out of range, encode |
| // a ME instance with class ID of zero to specify this per ITU G.988 |
| meDef := me.ManagedEntityDefinition{ |
| Name: "InvalidSequenceNumberManagedEntity", |
| ClassID: me.ClassID(0), |
| MessageTypes: nil, |
| AttributeDefinitions: make(me.AttributeDefinitionMap), |
| } |
| opt.payload, _ = me.NewManagedEntity(meDef) |
| } |
| if _, ok := opt.payload.(*[]me.ManagedEntity); ok { |
| if opt.frameFormat == BaselineIdent { |
| return nil, errors.New("invalid payload for Baseline message") |
| } |
| // TODO: List of MEs. valid for extended messages only |
| } else if managedEntity, ok := opt.payload.(*me.ManagedEntity); ok { |
| // Single ME |
| meLayer.ReportedME = *managedEntity |
| } else { |
| return nil, errors.New("invalid payload for MibUploadNextResponse frame") |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &AlarmNotificationMsg{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| payloadAvailable := int(maxPayload) - 1 // Less alarm sequence number |
| |
| // TODO: Lots of work to do |
| fmt.Println(mask, maxPayload, payloadAvailable) |
| |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &AttributeValueChangeMsg{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| AttributeMask: 0, |
| Attributes: make(me.AttributeValueMap), |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| payloadAvailable := int(maxPayload) - 2 // Less attribute mask |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload, payloadAvailable) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| //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 |
| // } |
| // // Common for all MEs |
| // meLayer := &TestRequest{ |
| // MeBasePacket: MeBasePacket{ |
| // EntityClass: m.GetClassID(), |
| // EntityInstance: m.GetEntityID(), |
| // Extended: opt.frameFormat == ExtendedIdent, |
| // }, |
| // } |
| // // Get payload space available |
| // maxPayload := maxPacketAvailable(m, opt) |
| // |
| // // TODO: Lots of work to do |
| // |
| // fmt.Println(mask, maxPayload) |
| // return meLayer, errors.New("todo: Not implemented") |
| //} |
| |
| //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 |
| // } |
| // // Common for all MEs |
| // meLayer := &TestResponse{ |
| // MeBasePacket: MeBasePacket{ |
| // EntityClass: m.GetClassID(), |
| // EntityInstance: m.GetEntityID(), |
| // Extended: opt.frameFormat == ExtendedIdent, |
| // }, |
| // } |
| // // Get payload space available |
| // maxPayload := maxPacketAvailable(m, opt) |
| // |
| // // TODO: Lots of work to do |
| // |
| // fmt.Println(mask, maxPayload) |
| // return meLayer, errors.New("todo: Not implemented") |
| //} |
| |
| 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, |
| NumberOfCircuitPacks: byte(len(opt.software.CircuitPacks)), |
| CircuitPacks: opt.software.CircuitPacks, |
| } |
| // TODO: Add length check to insure we do not exceed maximum packet size |
| // payloadAvailable := int(maxPacketAvailable(m, opt)) |
| payloadAvailable := 2 |
| sizeNeeded := 1 |
| if sizeNeeded > payloadAvailable { |
| // TODO: Should we set truncate? |
| msg := "out-of-space. Cannot fit Circuit Pack instances into Start Software Download Request message" |
| return nil, me.NewMessageTruncatedError(msg) |
| } |
| return meLayer, nil |
| } |
| |
| 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)), |
| MeResults: opt.software.Results, |
| } |
| // TODO: Add length check to insure we do not exceed maximum packet size |
| // payloadAvailable := int(maxPacketAvailable(m, opt)) |
| payloadAvailable := 2 |
| sizeNeeded := 1 |
| if sizeNeeded > payloadAvailable { |
| // TODO: Should we set truncate? |
| msg := "out-of-space. Cannot fit Results into Start Software Download Response message" |
| return nil, me.NewMessageTruncatedError(msg) |
| } |
| return meLayer, nil |
| } |
| |
| func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) { |
| if opt.software.Data == nil { |
| return nil, me.NewNonStatusError("Software image data missing") |
| } |
| // Common for all MEs |
| meLayer := &DownloadSectionRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| SectionNumber: opt.software.SectionNumber, |
| SectionData: opt.software.Data, |
| } |
| return meLayer, nil |
| } |
| |
| func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) { |
| // Common for all MEs |
| meLayer := &DownloadSectionResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| Result: opt.result, |
| SectionNumber: opt.software.SectionNumber, |
| } |
| return meLayer, nil |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &EndSoftwareDownloadRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &EndSoftwareDownloadResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &ActivateSoftwareRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &ActivateSoftwareResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &CommitSoftwareRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &CommitSoftwareResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| if timestamp, ok := opt.payload.(int64); ok { |
| tm := time.Unix(timestamp, 0) |
| meLayer.Year = uint16(tm.UTC().Year()) |
| meLayer.Month = uint8(tm.UTC().Month()) |
| meLayer.Day = uint8(tm.UTC().Day()) |
| meLayer.Hour = uint8(tm.UTC().Hour()) |
| meLayer.Minute = uint8(tm.UTC().Minute()) |
| meLayer.Second = uint8(tm.UTC().Second()) |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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, |
| } |
| return meLayer, nil |
| } |
| |
| 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 { |
| return nil, err |
| } |
| // Now scan attributes and reduce mask to only those requested |
| mask, err = calculateAttributeMask(m, mask) |
| if err != nil { |
| return nil, err |
| } |
| if mask == 0 { |
| return nil, errors.New("no attributes requested for GetNextRequest") |
| } |
| // TODO: If more than one attribute or the attribute requested is not a table attribute, return an error |
| // Common for all MEs |
| meLayer := &GetNextRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| AttributeMask: mask, |
| SequenceNumber: opt.sequenceNumberCountOrSize, |
| } |
| return meLayer, nil |
| } |
| |
| 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 { |
| return nil, err |
| } |
| mask, err = calculateAttributeMask(m, mask) |
| if err != nil { |
| return nil, err |
| } |
| // |
| // Common for all MEs |
| meLayer := &GetNextResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| Result: opt.result, |
| AttributeMask: 0, |
| Attributes: make(me.AttributeValueMap), |
| } |
| if meLayer.Result == me.Success { |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| payloadAvailable := int(maxPayload) - 3 // Less results and attribute mask |
| meDefinition := m.GetManagedEntityDefinition() |
| attrDefs := meDefinition.GetAttributeDefinitions() |
| attrMap := m.GetAttributeValueMap() |
| |
| if mask == 0 { |
| return nil, errors.New("no attributes requested for GetNextResponse") |
| } |
| // TODO: If more than one attribute or the attribute requested is not a table attribute, return an error |
| // Iterate down the attributes (Attribute 0 is the ManagedEntity ID) |
| var attrIndex uint |
| for attrIndex = 1; attrIndex <= 16; attrIndex++ { |
| // Is this attribute requested |
| if mask&(1<<(16-attrIndex)) != 0 { |
| // Get definitions since we need the name |
| attrDef, ok := attrDefs[attrIndex] |
| if !ok { |
| msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v", |
| attrIndex, meDefinition.GetName()) |
| return nil, errors.New(msg) |
| } |
| var attrValue interface{} |
| attrValue, ok = attrMap[attrDef.Name] |
| if !ok || attrValue == nil { |
| msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v", |
| attrDef.GetName(), meDefinition.GetName(), m) |
| return nil, errors.New(msg) |
| } |
| // Is space available? |
| if attrDef.Size <= payloadAvailable { |
| // Mark bit handled |
| mask &= ^attrDef.Mask |
| meLayer.AttributeMask |= attrDef.Mask |
| meLayer.Attributes[attrDef.Name] = attrValue |
| payloadAvailable -= attrDef.Size |
| } else { |
| // TODO: Should we set truncate? |
| msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetNextResponse message", |
| attrDef.GetName()) |
| return nil, me.NewMessageTruncatedError(msg) |
| } |
| } |
| } |
| } |
| return meLayer, nil |
| } |
| |
| //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 |
| // } |
| // // Common for all MEs |
| // meLayer := &TestResultNotification{ |
| // MeBasePacket: MeBasePacket{ |
| // EntityClass: m.GetClassID(), |
| // EntityInstance: m.GetEntityID(), |
| // Extended: opt.frameFormat == ExtendedIdent, |
| // }, |
| // } |
| // // Get payload space available |
| // maxPayload := maxPacketAvailable(m, opt) |
| // |
| // // TODO: Lots of work to do |
| // |
| // fmt.Println(mask, maxPayload) |
| // return meLayer, errors.New("todo: Not implemented") |
| //} |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &GetCurrentDataRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &GetCurrentDataResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| func SetTableRequestFrame(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") |
| } |
| 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 |
| } |
| // Common for all MEs |
| meLayer := &SetTableRequest{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: opt.frameFormat == ExtendedIdent, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |
| |
| 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 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 { |
| return nil, err |
| } |
| // Common for all MEs |
| meLayer := &SetTableResponse{ |
| MeBasePacket: MeBasePacket{ |
| EntityClass: m.GetClassID(), |
| EntityInstance: m.GetEntityID(), |
| Extended: true, |
| }, |
| } |
| // Get payload space available |
| maxPayload := maxPacketAvailable(m, opt) |
| |
| // TODO: Lots of work to do |
| |
| fmt.Println(mask, maxPayload) |
| return meLayer, errors.New("todo: Not implemented") |
| } |