blob: c3fe8a530ea2666fd399e3a7378e48a4c67a2274 [file] [log] [blame]
Chip Boling610117d2021-09-09 11:24:34 -05001/*
2 * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net)
3 * Copyright 2020-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package meframe
19
20import (
21 "errors"
22 "fmt"
23 "github.com/google/gopacket"
Andrea Campanellae0cd8232021-10-15 15:10:23 +020024 . "github.com/opencord/omci-lib-go/v2"
25 me "github.com/opencord/omci-lib-go/v2/generated"
Chip Boling610117d2021-09-09 11:24:34 -050026)
27
28func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
29 // Given mask sent in (could be default of 0xFFFF) get what is allowable.
30 // This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
31 // number of items.
32 maxMask, err := checkAttributeMask(m, opt.attributeMask)
33 if err != nil {
34 return nil, err
35 }
36 // Now scan attributes and reduce mask to only those requested
37 var mask uint16
38 mask, err = calculateAttributeMask(m, maxMask)
39 if err != nil {
40 return nil, err
41 }
42 if mask == 0 {
43 // TODO: Is a Get request with no attributes valid?
44 return nil, errors.New("no attributes requested for GetRequest")
45 }
46 meLayer := &GetRequest{
47 MeBasePacket: MeBasePacket{
48 EntityClass: m.GetClassID(),
49 EntityInstance: m.GetEntityID(),
50 Extended: opt.frameFormat == ExtendedIdent,
51 },
52 AttributeMask: mask,
53 }
54 return meLayer, nil
55}
56
57func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
58 mask, err := checkAttributeMask(m, opt.attributeMask)
59 if err != nil {
60 return nil, err
61 }
62 mask, err = calculateAttributeMask(m, mask)
63 if err != nil {
64 return nil, err
65 }
66 meLayer := &GetResponse{
67 MeBasePacket: MeBasePacket{
68 EntityClass: m.GetClassID(),
69 EntityInstance: m.GetEntityID(),
70 Extended: opt.frameFormat == ExtendedIdent,
71 },
72 Result: opt.result,
73 AttributeMask: 0,
74 Attributes: make(me.AttributeValueMap),
75 }
76 if meLayer.Result == me.AttributeFailure {
77 meLayer.UnsupportedAttributeMask = opt.unsupportedMask
78 meLayer.FailedAttributeMask = opt.attrExecutionMask
79 }
80 // Encode whatever we can
81 if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
82 // Encode results
83 // Get payload space available
84 maxPayload := maxPacketAvailable(m, opt)
85 payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
86 meDefinition := m.GetManagedEntityDefinition()
87 attrDefs := meDefinition.GetAttributeDefinitions()
88 attrMap := m.GetAttributeValueMap()
89
90 if mask != 0 {
91 // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
92 var attrIndex uint
93 for attrIndex = 1; attrIndex <= 16; attrIndex++ {
94 // Is this attribute requested
95 if mask&(1<<(16-attrIndex)) != 0 {
96 // Get definitions since we need the name
97 attrDef, ok := attrDefs[attrIndex]
98 if !ok {
99 msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
100 attrIndex, meDefinition.GetName())
101 return nil, errors.New(msg)
102 }
103 var attrValue interface{}
104 attrValue, ok = attrMap[attrDef.Name]
105 if !ok {
106 msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
107 attrDef.GetName(), meDefinition.GetName(), m)
108 return nil, errors.New(msg)
109 }
110 // Is space available?
111 if attrDef.Size <= payloadAvailable {
112 // Mark bit handled
113 mask &= ^attrDef.Mask
114 meLayer.AttributeMask |= attrDef.Mask
115 meLayer.Attributes[attrDef.Name] = attrValue
116 payloadAvailable -= attrDef.Size
117
118 } else if opt.failIfTruncated {
119 // TODO: Should we set truncate?
120 msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message",
121 attrDef.GetName())
122 return nil, me.NewMessageTruncatedError(msg)
123 } else {
124 // Add to existing 'failed' mask and update result
125 meLayer.FailedAttributeMask |= attrDef.Mask
126 meLayer.Result = me.AttributeFailure
127 }
128 }
129 }
130 }
131 }
132 return meLayer, nil
133}