blob: 70edf4fdd4b9d4675ff804c853681b95e35670b2 [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001/*
2 * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
Matteo Scandolof9d43412021-01-12 11:11:34 -080013 */
14 /*
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070015 * NOTE: This file was generated, manual edits will be overwritten!
16 *
17 * Generated by 'goCodeGenerator.py':
Matteo Scandolof9d43412021-01-12 11:11:34 -080018 * https://github.com/opencord/omci-lib-go/OMCI-parser/README.md
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070019 */
Matteo Scandolof9d43412021-01-12 11:11:34 -080020
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070021package omci
22
23import (
24 "errors"
25 "fmt"
Matteo Scandolof9d43412021-01-12 11:11:34 -080026 me "github.com/opencord/omci-lib-go/generated"
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070027 "github.com/deckarep/golang-set"
28 "github.com/google/gopacket"
29 "time"
30)
31
32var encoderMap map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error)
33
34func init() {
35 encoderMap = make(map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error))
36
37 encoderMap[CreateRequestType] = CreateRequestFrame
38 encoderMap[DeleteRequestType] = DeleteRequestFrame
39 encoderMap[SetRequestType] = SetRequestFrame
40 encoderMap[GetRequestType] = GetRequestFrame
41 encoderMap[GetAllAlarmsRequestType] = GetAllAlarmsRequestFrame
42 encoderMap[GetAllAlarmsNextRequestType] = GetAllAlarmsNextRequestFrame
43 encoderMap[MibUploadRequestType] = MibUploadRequestFrame
44 encoderMap[MibUploadNextRequestType] = MibUploadNextRequestFrame
45 encoderMap[MibResetRequestType] = MibResetRequestFrame
46 encoderMap[TestRequestType] = TestRequestFrame
47 encoderMap[StartSoftwareDownloadRequestType] = StartSoftwareDownloadRequestFrame
48 encoderMap[DownloadSectionRequestType] = DownloadSectionRequestFrame
49 encoderMap[EndSoftwareDownloadRequestType] = EndSoftwareDownloadRequestFrame
50 encoderMap[ActivateSoftwareRequestType] = ActivateSoftwareRequestFrame
51 encoderMap[CommitSoftwareRequestType] = CommitSoftwareRequestFrame
52 encoderMap[SynchronizeTimeRequestType] = SynchronizeTimeRequestFrame
53 encoderMap[RebootRequestType] = RebootRequestFrame
54 encoderMap[GetNextRequestType] = GetNextRequestFrame
55 encoderMap[GetCurrentDataRequestType] = GetCurrentDataRequestFrame
56 encoderMap[SetTableRequestType] = SetTableRequestFrame
57 encoderMap[CreateResponseType] = CreateResponseFrame
58 encoderMap[DeleteResponseType] = DeleteResponseFrame
59 encoderMap[SetResponseType] = SetResponseFrame
60 encoderMap[GetResponseType] = GetResponseFrame
61 encoderMap[GetAllAlarmsResponseType] = GetAllAlarmsResponseFrame
62 encoderMap[GetAllAlarmsNextResponseType] = GetAllAlarmsNextResponseFrame
63 encoderMap[MibUploadResponseType] = MibUploadResponseFrame
64 encoderMap[MibUploadNextResponseType] = MibUploadNextResponseFrame
65 encoderMap[MibResetResponseType] = MibResetResponseFrame
66 encoderMap[TestResponseType] = TestResponseFrame
67 encoderMap[StartSoftwareDownloadResponseType] = StartSoftwareDownloadResponseFrame
68 encoderMap[DownloadSectionResponseType] = DownloadSectionResponseFrame
69 encoderMap[EndSoftwareDownloadResponseType] = EndSoftwareDownloadResponseFrame
70 encoderMap[ActivateSoftwareResponseType] = ActivateSoftwareResponseFrame
71 encoderMap[CommitSoftwareResponseType] = CommitSoftwareResponseFrame
72 encoderMap[SynchronizeTimeResponseType] = SynchronizeTimeResponseFrame
73 encoderMap[RebootResponseType] = RebootResponseFrame
74 encoderMap[GetNextResponseType] = GetNextResponseFrame
75 encoderMap[GetCurrentDataResponseType] = GetCurrentDataResponseFrame
76 encoderMap[SetTableResponseType] = SetTableResponseFrame
77 encoderMap[AlarmNotificationType] = AlarmNotificationFrame
78 encoderMap[AttributeValueChangeType] = AttributeValueChangeFrame
79 encoderMap[TestResultType] = TestResultFrame
80}
81
82type options struct {
83 frameFormat DeviceIdent
84 failIfTruncated bool
85 attributeMask uint16
86 result me.Results // Common for many responses
87 attrExecutionMask uint16 // Create Response Only if results == 3 or Set Response only if results == 0
88 unsupportedMask uint16 // Set Response only if results == 9
89 sequenceNumberCountOrSize uint16 // For get-next request frames and for frames that return number of commands or length
90 transactionID uint16 // OMCI TID
91 mode uint8 // Get All Alarms retrieval mode
92 alarm AlarmOptions // Alarm related frames
93 software SoftwareOptions // Software image related frames
94 payload interface{} // ME or list of MEs, alarm bitmap, timestamp, ...
Matteo Scandolof9d43412021-01-12 11:11:34 -080095 addDefaults bool // Add missing SetByCreate attributes for Create Requests
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070096}
97
98var defaultFrameOptions = options{
99 frameFormat: BaselineIdent,
100 failIfTruncated: false,
101 attributeMask: 0xFFFF,
102 result: me.Success,
103 attrExecutionMask: 0,
104 unsupportedMask: 0,
105 sequenceNumberCountOrSize: 0,
106 transactionID: 0,
107 mode: 0,
108 software: defaultSoftwareOptions,
109 alarm: defaultAlarmOptions,
110 payload: nil,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800111 addDefaults: false,
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700112}
113
114// FrameOption sets options such as frame format, etc.
115type FrameOption func(*options)
116
117// FrameFormat determines determines the OMCI message format used on the fiber.
118// The default value is BaselineIdent
119func FrameFormat(ff DeviceIdent) FrameOption {
120 return func(o *options) {
121 o.frameFormat = ff
122 }
123}
124
125// FailIfTruncated determines whether a request to encode a frame that does
126// not have enough room for all requested options should fail and return an
127// error.
128//
129// If set to 'false', the behaviour depends on the message type/operation
130// requested. The table below provides more information:
131//
132// Request Type Behavour
133// ------------------------------------------------------------------------
134// CreateRequest A single CreateRequest struct is always returned as the
135// CreateRequest message does not have an attributes Mask
136// field and a Baseline OMCI message is large enough to
137// support all Set-By-Create attributes.
138//
139// GetResponse If multiple OMCI response frames are needed to return
140// all requested attributes, only the attributes that can
141// fit will be returned and the FailedAttributeMask field
142// set to the attributes that could not be returned
143//
144// If this is an ME with an attribute that is a table, the
145// first GetResponse struct will return the size of the
146// attribute and the following GetNextResponse structs will
147// contain the attribute data. The ONU application is
148// responsible for stashing these extra struct(s) away in
149// anticipation of possible GetNext Requests occurring for
150// the attribute. See the discussion on Table attributes
151// in the GetResponse section of ITU G.988 for more
152// information.
153//
154// If set to 'true', no struct(s) are returned and an error is provided.
155//
156// The default value is 'false'
157func FailIfTruncated(f bool) FrameOption {
158 return func(o *options) {
159 o.failIfTruncated = f
160 }
161}
162
163// attributeMask determines the attributes to encode into the frame.
164// The default value is 0xFFFF which specifies all available attributes
165// in the frame
166func AttributeMask(m uint16) FrameOption {
167 return func(o *options) {
168 o.attributeMask = m
169 }
170}
171
172// AttributeExecutionMask is used by the Create and Set Response frames to indicate
173// attributes that failed to be created/set.
174func AttributeExecutionMask(m uint16) FrameOption {
175 return func(o *options) {
176 o.attrExecutionMask = m
177 }
178}
179
180// UnsupportedAttributeMask is used by the Set Response frames to indicate
181// attributes are not supported on this ONU
182func UnsupportedAttributeMask(m uint16) FrameOption {
183 return func(o *options) {
184 o.unsupportedMask = m
185 }
186}
187
188// Result is used to set returned results in responses
189// that have that field
190func Result(r me.Results) FrameOption {
191 return func(o *options) {
192 o.result = r
193 }
194}
195
196// SequenceNumberCountOrSize is used by the GetNext and MibUploadGetNext request frames and for
197// frames that return number of commands or length such as Get (table attribute) or
198// MibUpload/GetAllAlarms/...
199func SequenceNumberCountOrSize(m uint16) FrameOption {
200 return func(o *options) {
201 o.sequenceNumberCountOrSize = m
202 }
203}
204
205// TransactionID is to specify the TID in the OMCI header. The default is
206// zero which requires the caller to set it to the appropriate value if this
207// is not an autonomous ONU notification frame
208func TransactionID(tid uint16) FrameOption {
209 return func(o *options) {
210 o.transactionID = tid
211 }
212}
213
214// RetrievalMode is to specify the the Alarm Retrieval Mode in a GetAllAlarms Request
215func RetrievalMode(m uint8) FrameOption {
216 return func(o *options) {
217 o.mode = m
218 }
219}
220
221// SuccessResult is to specify the the SuccessResult for a SynchronizeTime Response
222func SuccessResult(m uint8) FrameOption {
223 return func(o *options) {
224 o.mode = m
225 }
226}
227
228// RebootCondition is to specify the the Reboot Condition for a ONU Reboot request
229func RebootCondition(m uint8) FrameOption {
230 return func(o *options) {
231 o.mode = m
232 }
233}
234
235// Alarm is used to specify a collection of options related to Alarm notifications
236func Alarm(ao AlarmOptions) FrameOption {
237 return func(o *options) {
238 o.alarm = ao
239 }
240}
241
242// Software is used to specify a collection of options related to Software image
243// manipulation
244func Software(so SoftwareOptions) FrameOption {
245 return func(o *options) {
246 o.software = so
247 }
248}
249
250// Payload is used to specify ME payload options that are not simple types. This
251// include the ME (list of MEs) to encode into a GetNextMibUpload response, the
252// alarm bitmap for alarm relates responses/notifications, alarm bitmaps, and
253// for specifying the download section data when performing Software Download.
254func Payload(p interface{}) FrameOption {
255 return func(o *options) {
256 o.payload = p
257 }
258}
259
Matteo Scandolof9d43412021-01-12 11:11:34 -0800260// AddDefaults is used to specify that if a SetByCreate attribute is not
261// specified in the list of attributes for a Create Request, use the attribute
262// defined default
263func AddDefaults(add bool) FrameOption {
264 return func(o *options) {
265 o.addDefaults = add
266 }
267}
268
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700269// Alarm related frames have a wide variety of settable values. Placing them
270// in a separate struct is mainly to keep the base options simple
271type AlarmOptions struct {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800272 AlarmClassID me.ClassID
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700273 AlarmInstance uint16
274 AlarmBitmap []byte // Should be up to 58 octets
275}
276
277var defaultAlarmOptions = AlarmOptions{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800278 AlarmClassID: 0,
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700279 AlarmInstance: 0,
280 AlarmBitmap: nil,
281}
282
283// Software related frames have a wide variety of settable values. Placing them
284// in a separate struct is mainly to keep the base options simple
285type SoftwareOptions struct {
286 WindowSize uint8 // Window size - 1
287 ImageSize uint32
288 CircuitPacks []uint16 // slot (upper 8 bits) and instance (lower 8 bits)
289 Results []downloadResults
290}
291
292var defaultSoftwareOptions = SoftwareOptions{
293 WindowSize: 0,
294 ImageSize: 0,
295 CircuitPacks: nil,
296 Results: nil,
297}
298
299// EncodeFrame will encode the Managed Entity specific protocol struct and an
300// OMCILayer struct. This struct can be provided to the gopacket.SerializeLayers()
301// function to be serialized into a buffer for transmission.
302func EncodeFrame(m *me.ManagedEntity, messageType MessageType, opt ...FrameOption) (*OMCI, gopacket.SerializableLayer, error) {
303 // Check for message type support
304 msgType := me.MsgType(messageType & me.MsgTypeMask)
305 meDefinition := m.GetManagedEntityDefinition()
306
307 if !me.SupportsMsgType(meDefinition, msgType) {
308 msg := fmt.Sprintf("managed entity %v does not support %v Message-Type",
309 meDefinition.GetName(), msgType)
310 return nil, nil, errors.New(msg)
311 }
312 // Decode options
313 opts := defaultFrameOptions
314 for _, o := range opt {
315 o(&opts)
316 }
317 // TODO: If AttributesMask option passed in, check for deprecated options. Allow encoding option
318 // that will ignore deprecated option. Add additional in the get and set meframe_test,go
319 // test functions to test this. Also have it test attribute name(s) to see if the attribute
Matteo Scandolof9d43412021-01-12 11:11:34 -0800320 // is deprecated. The OMCI-Parser now supports detection of deprecated attributes and
321 // provides that to the code-generator (and currently available in generated golang code).
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700322 // Note: Transaction ID should be set before frame serialization
323 omci := &OMCI{
324 TransactionID: opts.transactionID,
325 MessageType: messageType,
326 DeviceIdentifier: opts.frameFormat,
327 }
328 var meInfo gopacket.SerializableLayer
329 var err error
330
331 if encoder, ok := encoderMap[messageType]; ok {
332 meInfo, err = encoder(m, opts)
333 } else {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800334 err = fmt.Errorf("message-type: %v/%#x is not supported", messageType, messageType)
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700335 }
336 if err != nil {
337 return nil, nil, err
338 }
339 return omci, meInfo, err
340}
341
342// For most all create methods below, error checking for valid masks, attribute
343// values, and other fields is left to when the frame is actually serialized.
344
345func checkAttributeMask(m *me.ManagedEntity, mask uint16) (uint16, error) {
346 if mask == defaultFrameOptions.attributeMask {
347 // Scale back to just what is allowed
348 return m.GetAllowedAttributeMask(), nil
349 }
350 if mask&m.GetManagedEntityDefinition().GetAllowedAttributeMask() != mask {
351 return 0, errors.New("invalid attribute mask")
352 }
353 return mask & m.GetManagedEntityDefinition().GetAllowedAttributeMask(), nil
354}
355
356// return the maximum space that can be used by attributes
357func maxPacketAvailable(m *me.ManagedEntity, opt options) uint {
358 if opt.frameFormat == BaselineIdent {
359 // OMCI Header - 4 octets
360 // Class ID/Instance ID - 4 octets
361 // Length field - 4 octets
362 // MIC - 4 octets
363 return MaxBaselineLength - 16
364 }
365 // OMCI Header - 4 octets
366 // Class ID/Instance ID - 4 octets
367 // Length field - 4 octets
368 // MIC - 4 octets
369 return MaxExtendedLength - 16
370}
371
372func calculateAttributeMask(m *me.ManagedEntity, requestedMask uint16) (uint16, error) {
373 attrDefs := m.GetAttributeDefinitions()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800374 var entityIDName string
375 if entry, ok := attrDefs[0]; ok {
376 entityIDName = entry.GetName()
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700377 } else {
378 panic("unexpected error") // All attribute definition maps have an entity ID
379 }
380 attributeNames := make([]interface{}, 0)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800381 for attrName := range m.GetAttributeValueMap() {
382 if attrName == entityIDName {
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700383 continue // No mask for EntityID
384 }
385 attributeNames = append(attributeNames, attrName)
386 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800387 calculatedMask, err := me.GetAttributesBitmap(attrDefs, mapset.NewSetWith(attributeNames...))
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700388
389 if err != nil {
390 return 0, err
391 }
392 return calculatedMask & requestedMask, nil
393}
394
395// GenFrame is a helper function to make tests a little easier to read.
396// For a real application, use the .../omci/generated/class.go 'New'
397// functions to create your Managed Entity and then use it to call the
398// EncodeFrame method.
399func GenFrame(meInstance *me.ManagedEntity, messageType MessageType, options ...FrameOption) ([]byte, error) {
400 omciLayer, msgLayer, err := EncodeFrame(meInstance, messageType, options...)
401 if err != nil {
402 return nil, err
403 }
404 // Serialize the frame and send it
405 var serializeOptions gopacket.SerializeOptions
406 serializeOptions.FixLengths = true
407
408 buffer := gopacket.NewSerializeBuffer()
409 err = gopacket.SerializeLayers(buffer, serializeOptions, omciLayer, msgLayer)
410 if err != nil {
411 return nil, err
412 }
413 return buffer.Bytes(), nil
414}
415
416func CreateRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
417 // NOTE: The OMCI parser does not extract the default values of set-by-create attributes
418 // and are the zero 'default' (or nil) at this time. For this reason, make sure
419 // you specify all non-zero default values and pass them in appropriate
420 meLayer := &CreateRequest{
421 MeBasePacket: MeBasePacket{
422 EntityClass: m.GetClassID(),
423 EntityInstance: m.GetEntityID(),
424 },
Matteo Scandolof9d43412021-01-12 11:11:34 -0800425 Attributes: m.GetAttributeValueMap(),
426 }
427 // Add any missing SetByCreate options if requested
428 if opt.addDefaults {
429 if attrDefs, err := me.GetAttributesDefinitions(m.GetClassID()); err.StatusCode() == me.Success {
430 for index, attr := range attrDefs {
431 if me.SupportsAttributeAccess(attr, me.SetByCreate) {
432 if index == 0 {
433 continue // Skip Entity ID, if it is SetByCreate, they should always specify it
434 }
435 if _, found := meLayer.Attributes[attr.GetName()]; !found {
436 meLayer.Attributes[attr.GetName()] = attr.DefValue
437 }
438 }
439 }
440 }
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700441 }
442 return meLayer, nil
443}
444
445func CreateResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
446 meLayer := &CreateResponse{
447 MeBasePacket: MeBasePacket{
448 EntityClass: m.GetClassID(),
449 EntityInstance: m.GetEntityID(),
450 },
Matteo Scandolof9d43412021-01-12 11:11:34 -0800451 Result: opt.result,
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700452 }
453 if meLayer.Result == me.ParameterError {
454 meLayer.AttributeExecutionMask = opt.attrExecutionMask
455 }
456 return meLayer, nil
457}
458
459func DeleteRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
460 meLayer := &DeleteRequest{
461 MeBasePacket: MeBasePacket{
462 EntityClass: m.GetClassID(),
463 EntityInstance: m.GetEntityID(),
464 },
465 }
466 return meLayer, nil
467}
468
469func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
470 meLayer := &DeleteResponse{
471 MeBasePacket: MeBasePacket{
472 EntityClass: m.GetClassID(),
473 EntityInstance: m.GetEntityID(),
474 },
475 Result: opt.result,
476 }
477 return meLayer, nil
478}
479
480func SetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
481 mask, err := checkAttributeMask(m, opt.attributeMask)
482 if err != nil {
483 return nil, err
484 }
485 mask, err = calculateAttributeMask(m, mask)
486 if err != nil {
487 return nil, err
488 }
489 meDefinition := m.GetManagedEntityDefinition()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800490 attrDefs := meDefinition.GetAttributeDefinitions()
491 attrMap := m.GetAttributeValueMap()
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700492
493 // Get payload space available
494 maxPayload := maxPacketAvailable(m, opt)
495 payloadAvailable := int(maxPayload) - 2 // Less attribute mask
496
497 meLayer := &SetRequest{
498 MeBasePacket: MeBasePacket{
499 EntityClass: m.GetClassID(),
500 EntityInstance: m.GetEntityID(),
501 },
502 AttributeMask: 0,
503 Attributes: make(me.AttributeValueMap),
504 }
505 for mask != 0 {
506 // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
507 var attrIndex uint
508 for attrIndex = 1; attrIndex <= 16; attrIndex++ {
509 // Is this attribute requested
510 if mask&(1<<(16-attrIndex)) != 0 {
511 // Get definitions since we need the name
512 attrDef, ok := attrDefs[attrIndex]
513 if !ok {
514 msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
515 attrIndex, meDefinition.GetName())
516 return nil, errors.New(msg)
517 }
518 var attrValue interface{}
519 attrValue, ok = attrMap[attrDef.Name]
520 if !ok {
521 msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
522 attrDef.GetName(), meDefinition.GetName(), m)
523 return nil, errors.New(msg)
524 }
525 // Is space available?
526 if attrDef.Size <= payloadAvailable {
527 // Mark bit handled
Matteo Scandolof9d43412021-01-12 11:11:34 -0800528 mask &= ^attrDef.Mask
529 meLayer.AttributeMask |= attrDef.Mask
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700530 meLayer.Attributes[attrDef.Name] = attrValue
531 payloadAvailable -= attrDef.Size
532 } else {
533 // TODO: Should we set truncate?
534 msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into SetRequest message",
535 attrDef.GetName())
536 return nil, me.NewMessageTruncatedError(msg)
537 }
538 }
539 }
540 }
541 if err == nil && meLayer.AttributeMask == 0 {
542 // TODO: Is a set request with no attributes valid?
543 return nil, errors.New("no attributes encoded for SetRequest")
544 }
545 return meLayer, nil
546}
547
548func SetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
549 meLayer := &SetResponse{
550 MeBasePacket: MeBasePacket{
551 EntityClass: m.GetClassID(),
552 EntityInstance: m.GetEntityID(),
553 },
554 Result: opt.result,
555 }
556 if meLayer.Result == me.AttributeFailure {
557 meLayer.UnsupportedAttributeMask = opt.unsupportedMask
558 meLayer.FailedAttributeMask = opt.attrExecutionMask
559 }
560 return meLayer, nil
561}
562
563func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
564 // Given mask sent in (could be default of 0xFFFF) get what is allowable.
565 // This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
566 // number of items.
567 maxMask, err := checkAttributeMask(m, opt.attributeMask)
568 if err != nil {
569 return nil, err
570 }
571 // Now scan attributes and reduce mask to only those requested
572 var mask uint16
573 mask, err = calculateAttributeMask(m, maxMask)
574 if err != nil {
575 return nil, err
576 }
577 if mask == 0 {
578 // TODO: Is a Get request with no attributes valid?
579 return nil, errors.New("no attributes requested for GetRequest")
580 }
581 meLayer := &GetRequest{
582 MeBasePacket: MeBasePacket{
583 EntityClass: m.GetClassID(),
584 EntityInstance: m.GetEntityID(),
585 },
586 AttributeMask: mask,
587 }
588 return meLayer, nil
589}
590
591func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
592 mask, err := checkAttributeMask(m, opt.attributeMask)
593 if err != nil {
594 return nil, err
595 }
596 mask, err = calculateAttributeMask(m, mask)
597 if err != nil {
598 return nil, err
599 }
600 meLayer := &GetResponse{
601 MeBasePacket: MeBasePacket{
602 EntityClass: m.GetClassID(),
603 EntityInstance: m.GetEntityID(),
604 },
605 Result: opt.result,
606 AttributeMask: 0,
607 Attributes: make(me.AttributeValueMap),
608 }
609 if meLayer.Result == me.AttributeFailure {
610 meLayer.UnsupportedAttributeMask = opt.unsupportedMask
611 meLayer.FailedAttributeMask = opt.attrExecutionMask
612 }
613 // Encode whatever we can
614 if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
615 // Encode results
616 // Get payload space available
617 maxPayload := maxPacketAvailable(m, opt)
618 payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
619 meDefinition := m.GetManagedEntityDefinition()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800620 attrDefs := meDefinition.GetAttributeDefinitions()
621 attrMap := m.GetAttributeValueMap()
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700622
623 if mask != 0 {
624 // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
625 var attrIndex uint
626 for attrIndex = 1; attrIndex <= 16; attrIndex++ {
627 // Is this attribute requested
628 if mask&(1<<(16-attrIndex)) != 0 {
629 // Get definitions since we need the name
630 attrDef, ok := attrDefs[attrIndex]
631 if !ok {
632 msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
633 attrIndex, meDefinition.GetName())
634 return nil, errors.New(msg)
635 }
636 var attrValue interface{}
637 attrValue, ok = attrMap[attrDef.Name]
638 if !ok {
639 msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
640 attrDef.GetName(), meDefinition.GetName(), m)
641 return nil, errors.New(msg)
642 }
643 // Is space available?
644 if attrDef.Size <= payloadAvailable {
645 // Mark bit handled
Matteo Scandolof9d43412021-01-12 11:11:34 -0800646 mask &= ^attrDef.Mask
647 meLayer.AttributeMask |= attrDef.Mask
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700648 meLayer.Attributes[attrDef.Name] = attrValue
649 payloadAvailable -= attrDef.Size
650
651 } else if opt.failIfTruncated {
652 // TODO: Should we set truncate?
653 msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message",
654 attrDef.GetName())
655 return nil, me.NewMessageTruncatedError(msg)
656 } else {
657 // Add to existing 'failed' mask and update result
Matteo Scandolof9d43412021-01-12 11:11:34 -0800658 meLayer.FailedAttributeMask |= attrDef.Mask
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700659 meLayer.Result = me.AttributeFailure
660 }
661 }
662 }
663 }
664 }
665 return meLayer, nil
666}
667
668func GetAllAlarmsRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
669 // Common for all MEs
670 meLayer := &GetAllAlarmsRequest{
671 MeBasePacket: MeBasePacket{
672 EntityClass: m.GetClassID(),
673 EntityInstance: m.GetEntityID(),
674 },
675 AlarmRetrievalMode: opt.mode,
676 }
677 return meLayer, nil
678}
679
680func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
681 // Common for all MEs
682 meLayer := &GetAllAlarmsResponse{
683 MeBasePacket: MeBasePacket{
684 EntityClass: m.GetClassID(),
685 EntityInstance: m.GetEntityID(),
686 },
687 NumberOfCommands: opt.sequenceNumberCountOrSize,
688 }
689 return meLayer, nil
690}
691
692func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
693 // Common for all MEs
694 meLayer := &GetAllAlarmsNextRequest{
695 MeBasePacket: MeBasePacket{
696 EntityClass: m.GetClassID(),
697 EntityInstance: m.GetEntityID(),
698 },
699 CommandSequenceNumber: opt.sequenceNumberCountOrSize,
700 }
701 return meLayer, nil
702}
703
704func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
705 // Common for all MEs
706 meLayer := &GetAllAlarmsNextResponse{
707 MeBasePacket: MeBasePacket{
708 EntityClass: m.GetClassID(),
709 EntityInstance: m.GetEntityID(),
710 },
Matteo Scandolof9d43412021-01-12 11:11:34 -0800711 AlarmEntityClass: opt.alarm.AlarmClassID,
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700712 AlarmEntityInstance: opt.alarm.AlarmInstance,
713 }
714 if len(opt.alarm.AlarmBitmap) > 28 {
715 return nil, errors.New("invalid Alarm Bitmap Size. Must be [0..27]")
716 }
717 for octet := 0; octet < len(opt.alarm.AlarmBitmap); octet++ {
718 meLayer.AlarmBitMap[octet] = opt.alarm.AlarmBitmap[octet]
719 }
720 for octet := len(opt.alarm.AlarmBitmap); octet < 28; octet++ {
721 meLayer.AlarmBitMap[octet] = 0
722 }
723 return meLayer, nil
724}
725
726func MibUploadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
727 // Common for all MEs
728 meLayer := &MibUploadRequest{
729 MeBasePacket: MeBasePacket{
730 EntityClass: m.GetClassID(),
731 EntityInstance: 0,
732 },
733 }
734 return meLayer, nil
735}
736
737func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
738 // Common for all MEs
739 meLayer := &MibUploadResponse{
740 MeBasePacket: MeBasePacket{
741 EntityClass: m.GetClassID(),
742 EntityInstance: 0,
743 },
744 NumberOfCommands: opt.sequenceNumberCountOrSize,
745 }
746 return meLayer, nil
747}
748
749func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
750 // Common for all MEs
751 meLayer := &MibUploadNextRequest{
752 MeBasePacket: MeBasePacket{
753 EntityClass: m.GetClassID(),
754 EntityInstance: 0,
755 },
756 CommandSequenceNumber: opt.sequenceNumberCountOrSize,
757 }
758 return meLayer, nil
759}
760
761func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
762 // Common for all MEs
763 meLayer := &MibUploadNextResponse{
764 MeBasePacket: MeBasePacket{
765 EntityClass: m.GetClassID(),
766 EntityInstance: m.GetEntityID(),
767 },
768 }
769 if opt.payload == nil {
770 // Shortcut used to specify the request sequence number is out of range, encode
771 // a ME instance with class ID of zero to specify this per ITU G.988
Matteo Scandolof9d43412021-01-12 11:11:34 -0800772 meDef := me.ManagedEntityDefinition{
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700773 Name: "InvalidSequenceNumberManagedEntity",
774 ClassID: me.ClassID(0),
775 MessageTypes: nil,
776 AttributeDefinitions: make(me.AttributeDefinitionMap),
777 }
778 opt.payload, _ = me.NewManagedEntity(meDef)
779 }
780 if _, ok := opt.payload.(*[]me.ManagedEntity); ok {
781 if opt.frameFormat == BaselineIdent {
782 return nil, errors.New("invalid payload for Baseline message")
783 }
784 // TODO: List of MEs. valid for extended messages only
785 } else if managedEntity, ok := opt.payload.(*me.ManagedEntity); ok {
786 // Single ME
787 meLayer.ReportedME = *managedEntity
788 } else {
789 return nil, errors.New("invalid payload for MibUploadNextResponse frame")
790 }
791 return meLayer, nil
792}
793
794func MibResetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
795 // Common for all MEs
796 meLayer := &MibResetRequest{
797 MeBasePacket: MeBasePacket{
798 EntityClass: m.GetClassID(),
799 EntityInstance: m.GetEntityID(),
800 },
801 }
802 return meLayer, nil
803}
804
805func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
806 // Common for all MEs
807 meLayer := &MibResetResponse{
808 MeBasePacket: MeBasePacket{
809 EntityClass: m.GetClassID(),
810 EntityInstance: m.GetEntityID(),
811 },
812 Result: opt.result,
813 }
814 return meLayer, nil
815}
816
817func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
818 mask, err := checkAttributeMask(m, opt.attributeMask)
819 if err != nil {
820 return nil, err
821 }
822 // Common for all MEs
823 meLayer := &AlarmNotificationMsg{
824 MeBasePacket: MeBasePacket{
825 EntityClass: m.GetClassID(),
826 EntityInstance: m.GetEntityID(),
827 },
828 }
829 // Get payload space available
830 maxPayload := maxPacketAvailable(m, opt)
831 payloadAvailable := int(maxPayload) - 1 // Less alarm sequence number
832
833 // TODO: Lots of work to do
834 fmt.Println(mask, maxPayload, payloadAvailable)
835
836 return meLayer, errors.New("todo: Not implemented")
837}
838
839func AttributeValueChangeFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
840 mask, err := checkAttributeMask(m, opt.attributeMask)
841 if err != nil {
842 return nil, err
843 }
844 // Common for all MEs
845 meLayer := &AttributeValueChangeMsg{
846 MeBasePacket: MeBasePacket{
847 EntityClass: m.GetClassID(),
848 EntityInstance: m.GetEntityID(),
849 },
850 AttributeMask: 0,
851 Attributes: make(me.AttributeValueMap),
852 }
853 // Get payload space available
854 maxPayload := maxPacketAvailable(m, opt)
855 payloadAvailable := int(maxPayload) - 2 // Less attribute mask
856
857 // TODO: Lots of work to do
858
859 fmt.Println(mask, maxPayload, payloadAvailable)
860 return meLayer, errors.New("todo: Not implemented")
861}
862
863func TestRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
864 mask, err := checkAttributeMask(m, opt.attributeMask)
865 if err != nil {
866 return nil, err
867 }
868 // Common for all MEs
869 meLayer := &TestRequest{
870 MeBasePacket: MeBasePacket{
871 EntityClass: m.GetClassID(),
872 EntityInstance: m.GetEntityID(),
873 },
874 }
875 // Get payload space available
876 maxPayload := maxPacketAvailable(m, opt)
877
878 // TODO: Lots of work to do
879
880 fmt.Println(mask, maxPayload)
881 return meLayer, errors.New("todo: Not implemented")
882}
883
884func TestResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
885 mask, err := checkAttributeMask(m, opt.attributeMask)
886 if err != nil {
887 return nil, err
888 }
889 // Common for all MEs
890 meLayer := &TestResponse{
891 MeBasePacket: MeBasePacket{
892 EntityClass: m.GetClassID(),
893 EntityInstance: m.GetEntityID(),
894 },
895 }
896 // Get payload space available
897 maxPayload := maxPacketAvailable(m, opt)
898
899 // TODO: Lots of work to do
900
901 fmt.Println(mask, maxPayload)
902 return meLayer, errors.New("todo: Not implemented")
903}
904
905func StartSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
906 // Common for all MEs
907 meLayer := &StartSoftwareDownloadRequest{
908 MeBasePacket: MeBasePacket{
909 EntityClass: m.GetClassID(),
910 EntityInstance: m.GetEntityID(),
911 },
912 WindowSize: opt.software.WindowSize,
913 ImageSize: opt.software.ImageSize,
914 NumberOfCircuitPacks: byte(len(opt.software.CircuitPacks)),
915 CircuitPacks: opt.software.CircuitPacks,
916 }
917 // TODO: Add length check to insure we do not exceed maximum packet size
918 // payloadAvailable := int(maxPacketAvailable(m, opt))
919 payloadAvailable := 2
920 sizeNeeded := 1
921 if sizeNeeded > payloadAvailable {
922 // TODO: Should we set truncate?
923 msg := "out-of-space. Cannot fit Circuit Pack instances into Start Software Download Request message"
924 return nil, me.NewMessageTruncatedError(msg)
925 }
926 return meLayer, nil
927}
928
929func StartSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
930 // Common for all MEs
931 meLayer := &StartSoftwareDownloadResponse{
932 MeBasePacket: MeBasePacket{
933 EntityClass: m.GetClassID(),
934 EntityInstance: m.GetEntityID(),
935 },
936 WindowSize: opt.software.WindowSize,
937 NumberOfInstances: byte(len(opt.software.CircuitPacks)),
938 MeResults: opt.software.Results,
939 }
940 // TODO: Add length check to insure we do not exceed maximum packet size
941 // payloadAvailable := int(maxPacketAvailable(m, opt))
942 payloadAvailable := 2
943 sizeNeeded := 1
944 if sizeNeeded > payloadAvailable {
945 // TODO: Should we set truncate?
946 msg := "out-of-space. Cannot fit Results into Start Software Download Response message"
947 return nil, me.NewMessageTruncatedError(msg)
948 }
949 return meLayer, nil
950}
951
952func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
953 mask, err := checkAttributeMask(m, opt.attributeMask)
954 if err != nil {
955 return nil, err
956 }
957 // Common for all MEs
958 meLayer := &DownloadSectionRequest{
959 MeBasePacket: MeBasePacket{
960 EntityClass: m.GetClassID(),
961 EntityInstance: m.GetEntityID(),
962 },
963 }
964 // Get payload space available
965 maxPayload := maxPacketAvailable(m, opt)
966
967 // TODO: Lots of work to do
968
969 fmt.Println(mask, maxPayload)
970 return meLayer, errors.New("todo: Not implemented")
971}
972
973func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
974 mask, err := checkAttributeMask(m, opt.attributeMask)
975 if err != nil {
976 return nil, err
977 }
978 // Common for all MEs
979 meLayer := &DownloadSectionResponse{
980 MeBasePacket: MeBasePacket{
981 EntityClass: m.GetClassID(),
982 EntityInstance: m.GetEntityID(),
983 },
984 }
985 // Get payload space available
986 maxPayload := maxPacketAvailable(m, opt)
987
988 // TODO: Lots of work to do
989
990 fmt.Println(mask, maxPayload)
991 return meLayer, errors.New("todo: Not implemented")
992}
993
994func EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
995 mask, err := checkAttributeMask(m, opt.attributeMask)
996 if err != nil {
997 return nil, err
998 }
999 // Common for all MEs
1000 meLayer := &EndSoftwareDownloadRequest{
1001 MeBasePacket: MeBasePacket{
1002 EntityClass: m.GetClassID(),
1003 EntityInstance: m.GetEntityID(),
1004 },
1005 }
1006 // Get payload space available
1007 maxPayload := maxPacketAvailable(m, opt)
1008
1009 // TODO: Lots of work to do
1010
1011 fmt.Println(mask, maxPayload)
1012 return meLayer, errors.New("todo: Not implemented")
1013}
1014
1015func EndSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1016 mask, err := checkAttributeMask(m, opt.attributeMask)
1017 if err != nil {
1018 return nil, err
1019 }
1020 // Common for all MEs
1021 meLayer := &EndSoftwareDownloadResponse{
1022 MeBasePacket: MeBasePacket{
1023 EntityClass: m.GetClassID(),
1024 EntityInstance: m.GetEntityID(),
1025 },
1026 }
1027 // Get payload space available
1028 maxPayload := maxPacketAvailable(m, opt)
1029
1030 // TODO: Lots of work to do
1031
1032 fmt.Println(mask, maxPayload)
1033 return meLayer, errors.New("todo: Not implemented")
1034}
1035
1036func ActivateSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1037 mask, err := checkAttributeMask(m, opt.attributeMask)
1038 if err != nil {
1039 return nil, err
1040 }
1041 // Common for all MEs
1042 meLayer := &ActivateSoftwareRequest{
1043 MeBasePacket: MeBasePacket{
1044 EntityClass: m.GetClassID(),
1045 EntityInstance: m.GetEntityID(),
1046 },
1047 }
1048 // Get payload space available
1049 maxPayload := maxPacketAvailable(m, opt)
1050
1051 // TODO: Lots of work to do
1052
1053 fmt.Println(mask, maxPayload)
1054 return meLayer, errors.New("todo: Not implemented")
1055}
1056
1057func ActivateSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1058 mask, err := checkAttributeMask(m, opt.attributeMask)
1059 if err != nil {
1060 return nil, err
1061 }
1062 // Common for all MEs
1063 meLayer := &ActivateSoftwareResponse{
1064 MeBasePacket: MeBasePacket{
1065 EntityClass: m.GetClassID(),
1066 EntityInstance: m.GetEntityID(),
1067 },
1068 }
1069 // Get payload space available
1070 maxPayload := maxPacketAvailable(m, opt)
1071
1072 // TODO: Lots of work to do
1073
1074 fmt.Println(mask, maxPayload)
1075 return meLayer, errors.New("todo: Not implemented")
1076}
1077
1078func CommitSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1079 mask, err := checkAttributeMask(m, opt.attributeMask)
1080 if err != nil {
1081 return nil, err
1082 }
1083 // Common for all MEs
1084 meLayer := &CommitSoftwareRequest{
1085 MeBasePacket: MeBasePacket{
1086 EntityClass: m.GetClassID(),
1087 EntityInstance: m.GetEntityID(),
1088 },
1089 }
1090 // Get payload space available
1091 maxPayload := maxPacketAvailable(m, opt)
1092
1093 // TODO: Lots of work to do
1094
1095 fmt.Println(mask, maxPayload)
1096 return meLayer, errors.New("todo: Not implemented")
1097}
1098
1099func CommitSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1100 mask, err := checkAttributeMask(m, opt.attributeMask)
1101 if err != nil {
1102 return nil, err
1103 }
1104 // Common for all MEs
1105 meLayer := &CommitSoftwareResponse{
1106 MeBasePacket: MeBasePacket{
1107 EntityClass: m.GetClassID(),
1108 EntityInstance: m.GetEntityID(),
1109 },
1110 }
1111 // Get payload space available
1112 maxPayload := maxPacketAvailable(m, opt)
1113
1114 // TODO: Lots of work to do
1115
1116 fmt.Println(mask, maxPayload)
1117 return meLayer, errors.New("todo: Not implemented")
1118}
1119
1120func SynchronizeTimeRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1121 // Common for all MEs
1122 meLayer := &SynchronizeTimeRequest{
1123 MeBasePacket: MeBasePacket{
1124 EntityClass: m.GetClassID(),
1125 EntityInstance: m.GetEntityID(),
1126 },
1127 }
1128 // Decode payload option. If nil, no timestamp provided
1129 if timestamp, ok := opt.payload.(int64); ok {
1130 tm := time.Unix(timestamp, 0)
1131 meLayer.Year = uint16(tm.UTC().Year())
1132 meLayer.Month = uint8(tm.UTC().Month())
1133 meLayer.Day = uint8(tm.UTC().Day())
1134 meLayer.Hour = uint8(tm.UTC().Hour())
1135 meLayer.Minute = uint8(tm.UTC().Minute())
1136 meLayer.Second = uint8(tm.UTC().Second())
1137 }
1138 return meLayer, nil
1139}
1140
1141func SynchronizeTimeResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1142 // Common for all MEs
1143 meLayer := &SynchronizeTimeResponse{
1144 MeBasePacket: MeBasePacket{
1145 EntityClass: m.GetClassID(),
1146 EntityInstance: m.GetEntityID(),
1147 },
1148 Result: opt.result,
1149 SuccessResults: opt.mode,
1150 }
1151 return meLayer, nil
1152}
1153
1154func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1155 // Common for all MEs
1156 meLayer := &RebootRequest{
1157 MeBasePacket: MeBasePacket{
1158 EntityClass: m.GetClassID(),
1159 EntityInstance: m.GetEntityID(),
1160 },
1161 RebootCondition: opt.mode,
1162 }
1163 return meLayer, nil
1164}
1165
1166func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1167 // Common for all MEs
1168 meLayer := &RebootResponse{
1169 MeBasePacket: MeBasePacket{
1170 EntityClass: m.GetClassID(),
1171 EntityInstance: m.GetEntityID(),
1172 },
1173 Result: opt.result,
1174 }
1175 return meLayer, nil
1176}
1177
1178func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1179 // Validate attribute mask
1180 mask, err := checkAttributeMask(m, opt.attributeMask)
1181 if err != nil {
1182 return nil, err
1183 }
1184 // Now scan attributes and reduce mask to only those requested
1185 mask, err = calculateAttributeMask(m, mask)
1186 if err != nil {
1187 return nil, err
1188 }
1189 if mask == 0 {
1190 return nil, errors.New("no attributes requested for GetNextRequest")
1191 }
1192 // TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
1193 // Common for all MEs
1194 meLayer := &GetNextRequest{
1195 MeBasePacket: MeBasePacket{
1196 EntityClass: m.GetClassID(),
1197 EntityInstance: m.GetEntityID(),
1198 },
1199 AttributeMask: mask,
1200 SequenceNumber: opt.sequenceNumberCountOrSize,
1201 }
1202 return meLayer, nil
1203}
1204
1205func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1206 // Validate attribute mask
1207 mask, err := checkAttributeMask(m, opt.attributeMask)
1208 if err != nil {
1209 return nil, err
1210 }
1211 mask, err = calculateAttributeMask(m, mask)
1212 if err != nil {
1213 return nil, err
1214 }
1215 //
1216 // Common for all MEs
1217 meLayer := &GetNextResponse{
1218 MeBasePacket: MeBasePacket{
1219 EntityClass: m.GetClassID(),
1220 EntityInstance: m.GetEntityID(),
1221 },
1222 Result: opt.result,
1223 AttributeMask: 0,
1224 Attributes: make(me.AttributeValueMap),
1225 }
1226 if meLayer.Result == me.Success {
1227 // Get payload space available
1228 maxPayload := maxPacketAvailable(m, opt)
1229 payloadAvailable := int(maxPayload) - 3 // Less results and attribute mask
1230 meDefinition := m.GetManagedEntityDefinition()
Matteo Scandolof9d43412021-01-12 11:11:34 -08001231 attrDefs := meDefinition.GetAttributeDefinitions()
1232 attrMap := m.GetAttributeValueMap()
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001233
1234 if mask == 0 {
1235 return nil, errors.New("no attributes requested for GetNextResponse")
1236 }
1237 // TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
1238 // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
1239 var attrIndex uint
1240 for attrIndex = 1; attrIndex <= 16; attrIndex++ {
1241 // Is this attribute requested
1242 if mask&(1<<(16-attrIndex)) != 0 {
1243 // Get definitions since we need the name
1244 attrDef, ok := attrDefs[attrIndex]
1245 if !ok {
1246 msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
1247 attrIndex, meDefinition.GetName())
1248 return nil, errors.New(msg)
1249 }
1250 var attrValue interface{}
1251 attrValue, ok = attrMap[attrDef.Name]
1252 if !ok || attrValue == nil {
1253 msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
1254 attrDef.GetName(), meDefinition.GetName(), m)
1255 return nil, errors.New(msg)
1256 }
1257 // Is space available?
1258 if attrDef.Size <= payloadAvailable {
1259 // Mark bit handled
Matteo Scandolof9d43412021-01-12 11:11:34 -08001260 mask &= ^attrDef.Mask
1261 meLayer.AttributeMask |= attrDef.Mask
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001262 meLayer.Attributes[attrDef.Name] = attrValue
1263 payloadAvailable -= attrDef.Size
1264 } else {
1265 // TODO: Should we set truncate?
1266 msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetNextResponse message",
1267 attrDef.GetName())
1268 return nil, me.NewMessageTruncatedError(msg)
1269 }
1270 }
1271 }
1272 }
1273 return meLayer, nil
1274}
1275
1276func TestResultFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1277 mask, err := checkAttributeMask(m, opt.attributeMask)
1278 if err != nil {
1279 return nil, err
1280 }
1281 // Common for all MEs
1282 meLayer := &TestResultMsg{
1283 MeBasePacket: MeBasePacket{
1284 EntityClass: m.GetClassID(),
1285 EntityInstance: m.GetEntityID(),
1286 },
1287 }
1288 // Get payload space available
1289 maxPayload := maxPacketAvailable(m, opt)
1290
1291 // TODO: Lots of work to do
1292
1293 fmt.Println(mask, maxPayload)
1294 return meLayer, errors.New("todo: Not implemented")
1295}
1296
1297func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1298 mask, err := checkAttributeMask(m, opt.attributeMask)
1299 if err != nil {
1300 return nil, err
1301 }
1302 // Common for all MEs
1303 meLayer := &GetCurrentDataRequest{
1304 MeBasePacket: MeBasePacket{
1305 EntityClass: m.GetClassID(),
1306 EntityInstance: m.GetEntityID(),
1307 },
1308 }
1309 // Get payload space available
1310 maxPayload := maxPacketAvailable(m, opt)
1311
1312 // TODO: Lots of work to do
1313
1314 fmt.Println(mask, maxPayload)
1315 return meLayer, errors.New("todo: Not implemented")
1316}
1317
1318func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1319 mask, err := checkAttributeMask(m, opt.attributeMask)
1320 if err != nil {
1321 return nil, err
1322 }
1323 // Common for all MEs
1324 meLayer := &GetCurrentDataResponse{
1325 MeBasePacket: MeBasePacket{
1326 EntityClass: m.GetClassID(),
1327 EntityInstance: m.GetEntityID(),
1328 },
1329 }
1330 // Get payload space available
1331 maxPayload := maxPacketAvailable(m, opt)
1332
1333 // TODO: Lots of work to do
1334
1335 fmt.Println(mask, maxPayload)
1336 return meLayer, errors.New("todo: Not implemented")
1337}
1338
1339func SetTableRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1340 if opt.frameFormat != ExtendedIdent {
1341 return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
1342 }
1343 mask, err := checkAttributeMask(m, opt.attributeMask)
1344 if err != nil {
1345 return nil, err
1346 }
1347 // Common for all MEs
1348 meLayer := &SetTableRequest{
1349 MeBasePacket: MeBasePacket{
1350 EntityClass: m.GetClassID(),
1351 EntityInstance: m.GetEntityID(),
1352 },
1353 }
1354 // Get payload space available
1355 maxPayload := maxPacketAvailable(m, opt)
1356
1357 // TODO: Lots of work to do
1358
1359 fmt.Println(mask, maxPayload)
1360 return meLayer, errors.New("todo: Not implemented")
1361}
1362
1363func SetTableResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
1364 if opt.frameFormat != ExtendedIdent {
1365 return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
1366 }
1367 mask, err := checkAttributeMask(m, opt.attributeMask)
1368 if err != nil {
1369 return nil, err
1370 }
1371 // Common for all MEs
1372 meLayer := &SetTableResponse{
1373 MeBasePacket: MeBasePacket{
1374 EntityClass: m.GetClassID(),
1375 EntityInstance: m.GetEntityID(),
1376 },
1377 }
1378 // Get payload space available
1379 maxPayload := maxPacketAvailable(m, opt)
1380
1381 // TODO: Lots of work to do
1382
1383 fmt.Println(mask, maxPayload)
1384 return meLayer, errors.New("todo: Not implemented")
1385}