blob: de9343d39f0b903b5bde7494df192c36bb5e9f96 [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"
pnalmas61093da2025-08-19 12:42:56 +053023
Chip Boling610117d2021-09-09 11:24:34 -050024 "github.com/google/gopacket"
Andrea Campanellae0cd8232021-10-15 15:10:23 +020025 . "github.com/opencord/omci-lib-go/v2"
26 me "github.com/opencord/omci-lib-go/v2/generated"
Chip Boling610117d2021-09-09 11:24:34 -050027)
28
29func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
30 if opt.frameFormat == ExtendedIdent {
31 return nil, errors.New("extended message set for this message type is not supported")
32 }
pnalmas61093da2025-08-19 12:42:56 +053033 // Given mask sent in (could be default of 0xFFFF) get what is allowable.
34 // This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
35 // number of items.
36 maxMask, err := checkAttributeMask(m, opt.attributeMask)
Chip Boling610117d2021-09-09 11:24:34 -050037 if err != nil {
38 return nil, err
39 }
pnalmas61093da2025-08-19 12:42:56 +053040 // Now scan attributes and reduce mask to only those requested
41 var mask uint16
42 mask, err = calculateAttributeMask(m, maxMask)
43 if err != nil {
44 return nil, err
45 }
46 if mask == 0 {
47 // TODO: Is a GetCurrentData request with no attributes valid?
48 return nil, errors.New("no attributes requested for GetCurrentDataRequest")
49 }
50
Chip Boling610117d2021-09-09 11:24:34 -050051 // Common for all MEs
52 meLayer := &GetCurrentDataRequest{
53 MeBasePacket: MeBasePacket{
54 EntityClass: m.GetClassID(),
55 EntityInstance: m.GetEntityID(),
56 Extended: opt.frameFormat == ExtendedIdent,
57 },
pnalmas61093da2025-08-19 12:42:56 +053058 AttributeMask: mask,
Chip Boling610117d2021-09-09 11:24:34 -050059 }
Chip Boling610117d2021-09-09 11:24:34 -050060
pnalmas61093da2025-08-19 12:42:56 +053061 return meLayer, nil
Chip Boling610117d2021-09-09 11:24:34 -050062}
63
64func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
65 if opt.frameFormat == ExtendedIdent {
66 return nil, errors.New("extended message set for this message type is not supported")
67 }
68 mask, err := checkAttributeMask(m, opt.attributeMask)
69 if err != nil {
70 return nil, err
71 }
pnalmas61093da2025-08-19 12:42:56 +053072 mask, err = calculateAttributeMask(m, mask)
73 if err != nil {
74 return nil, err
75 }
76
Chip Boling610117d2021-09-09 11:24:34 -050077 // Common for all MEs
78 meLayer := &GetCurrentDataResponse{
79 MeBasePacket: MeBasePacket{
80 EntityClass: m.GetClassID(),
81 EntityInstance: m.GetEntityID(),
82 Extended: opt.frameFormat == ExtendedIdent,
83 },
pnalmas61093da2025-08-19 12:42:56 +053084 Result: opt.result,
85 AttributeMask: 0,
86 Attributes: make(me.AttributeValueMap),
Chip Boling610117d2021-09-09 11:24:34 -050087 }
Chip Boling610117d2021-09-09 11:24:34 -050088
pnalmas61093da2025-08-19 12:42:56 +053089 if meLayer.Result == me.AttributeFailure {
90 meLayer.UnsupportedAttributeMask = opt.unsupportedMask
91 meLayer.FailedAttributeMask = opt.attrExecutionMask
92 }
Chip Boling610117d2021-09-09 11:24:34 -050093
pnalmas61093da2025-08-19 12:42:56 +053094 // Encode whatever we can
95 if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
96 // Get payload space available
97 maxPayload := maxPacketAvailable(m, opt)
98 payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
99 meDefinition := m.GetManagedEntityDefinition()
100 attrDefs := meDefinition.GetAttributeDefinitions()
101 attrMap := m.GetAttributeValueMap()
102
103 if mask != 0 {
104 // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
105 var attrIndex uint
106 for attrIndex = 1; attrIndex <= 16; attrIndex++ {
107 // Is this attribute requested
108 if mask&(1<<(16-attrIndex)) != 0 {
109 // Get definitions since we need the name
110 attrDef, ok := attrDefs[attrIndex]
111 if !ok {
112 msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
113 attrIndex, meDefinition.GetName())
114 return nil, errors.New(msg)
115 }
116 var attrValue interface{}
117 attrValue, ok = attrMap[attrDef.Name]
118 if !ok {
119 msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
120 attrDef.GetName(), meDefinition.GetName(), m)
121 return nil, errors.New(msg)
122 }
123 // Is space available?
124 if attrDef.Size <= payloadAvailable {
125 // Mark bit handled
126 mask &= ^attrDef.Mask
127 meLayer.AttributeMask |= attrDef.Mask
128 meLayer.Attributes[attrDef.Name] = attrValue
129 payloadAvailable -= attrDef.Size
130
131 } else if opt.failIfTruncated {
132 msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetCurrentDataResponse message",
133 attrDef.GetName())
134 return nil, me.NewMessageTruncatedError(msg)
135 } else {
136 // Add to existing 'failed' mask and update result
137 meLayer.FailedAttributeMask |= attrDef.Mask
138 meLayer.Result = me.AttributeFailure
139 }
140 }
141 }
142 }
143 }
144
145 return meLayer, nil
Chip Boling610117d2021-09-09 11:24:34 -0500146}