blob: e3fdb3b9869db24c3b240f51a3d9f784e97560cb [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 omci
19
20import (
21 "encoding/binary"
22 "errors"
23 "fmt"
24 "github.com/google/gopacket"
25 me "github.com/opencord/omci-lib-go/generated"
26)
27
28type SetRequest struct {
29 MeBasePacket
30 AttributeMask uint16
31 Attributes me.AttributeValueMap
32}
33
34func (omci *SetRequest) String() string {
35 return fmt.Sprintf("%v, Mask: %#x, attributes: %v",
36 omci.MeBasePacket.String(), omci.AttributeMask, omci.Attributes)
37}
38
39// LayerType returns LayerTypeSetRequest
40func (omci *SetRequest) LayerType() gopacket.LayerType {
41 return LayerTypeSetRequest
42}
43
44// CanDecode returns the set of layer types that this DecodingLayer can decode
45func (omci *SetRequest) CanDecode() gopacket.LayerClass {
46 return LayerTypeSetRequest
47}
48
49// NextLayerType returns the layer type contained by this DecodingLayer.
50func (omci *SetRequest) NextLayerType() gopacket.LayerType {
51 return gopacket.LayerTypePayload
52}
53
54// DecodeFromBytes decodes the given bytes of a Set Request into this layer
55func (omci *SetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
56 // Common ClassID/EntityID decode in msgBase
57 var hdrSize int
58 if omci.Extended {
59 hdrSize = 6 + 2
60 } else {
61 hdrSize = 4 + 2
62 }
63 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
64 if err != nil {
65 return err
66 }
67 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
68 me.ParamData{EntityID: omci.EntityInstance})
69 if omciErr.StatusCode() != me.Success {
70 return omciErr.GetError()
71 }
72 // ME needs to support Set
73 if !me.SupportsMsgType(meDefinition, me.Set) {
74 return me.NewProcessingError("managed entity does not support Set Message-Type")
75 }
76 offset := hdrSize - 2
77 omci.AttributeMask = binary.BigEndian.Uint16(data[offset:])
78
79 // Attribute decode
80 omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[hdrSize:], p, byte(SetRequestType))
81 if err != nil {
82 return err
83 }
84 // Validate all attributes support write
85 for attrName := range omci.Attributes {
86 attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
87 if err != nil {
88 return err
89 }
90 if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
91 msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
92 return me.NewProcessingError(msg)
93 }
94 }
95 if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
96 omci.Attributes[eidDef.GetName()] = omci.EntityInstance
97 return nil
98 }
99 return me.NewProcessingError("All Managed Entities have an EntityID attribute")
100}
101
102func decodeSetRequest(data []byte, p gopacket.PacketBuilder) error {
103 omci := &SetRequest{}
104 omci.MsgLayerType = LayerTypeSetRequest
105 return decodingLayerDecoder(omci, data, p)
106}
107
108func decodeSetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
109 omci := &SetRequest{}
110 omci.MsgLayerType = LayerTypeSetRequest
111 omci.Extended = true
112 return decodingLayerDecoder(omci, data, p)
113}
114
115// SerializeTo provides serialization of an Set Request message
116func (omci *SetRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
117 // Basic (common) OMCI Header is 8 octets, 10
118 err := omci.MeBasePacket.SerializeTo(b)
119 if err != nil {
120 return err
121 }
122 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
123 me.ParamData{EntityID: omci.EntityInstance})
124 if omciErr.StatusCode() != me.Success {
125 return omciErr.GetError()
126 }
127 // ME needs to support Set
128 if !me.SupportsMsgType(meDefinition, me.Set) {
129 return me.NewProcessingError("managed entity does not support Set Message-Type")
130 }
131 // Validate all attributes support write
132 for attrName := range omci.Attributes {
133 attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
134 if err != nil {
135 return err
136 }
137 // Do not test for write of Entity ID in the attribute list
138 if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
139 // TODO: Check ITU spec to see if this should be listed as a failed
140 // attribute and not a processing error.
141 msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
142 return me.NewProcessingError(msg)
143 }
144 }
145 var maskOffset int
146 var bytesAvailable int
147 if omci.Extended {
148 maskOffset = 2
149 bytesAvailable = MaxExtendedLength - 12 - 4
150 } else {
151 maskOffset = 0
152 bytesAvailable = MaxBaselineLength - 10 - 8
153 }
154 // Attribute serialization
155 attributeBuffer := gopacket.NewSerializeBuffer()
156 err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, attributeBuffer,
157 byte(SetRequestType), bytesAvailable, false)
158
159 bytes, err := b.AppendBytes(maskOffset + 2 + len(attributeBuffer.Bytes()))
160 if err != nil {
161 return err
162 }
163 if omci.Extended {
164 binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+2))
165 }
166 binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
167 copy(bytes[maskOffset+2:], attributeBuffer.Bytes())
168 return nil
169}
170
171type SetResponse struct {
172 MeBasePacket
173 Result me.Results
174 UnsupportedAttributeMask uint16
175 FailedAttributeMask uint16
176}
177
178func (omci *SetResponse) String() string {
179 return fmt.Sprintf("%v, Result: %d (%v), Unsupported Mask: %#x, Failed Mask: %#x",
180 omci.MeBasePacket.String(), omci.Result, omci.Result, omci.UnsupportedAttributeMask,
181 omci.FailedAttributeMask)
182}
183
184// LayerType returns LayerTypeSetResponse
185func (omci *SetResponse) LayerType() gopacket.LayerType {
186 return LayerTypeSetResponse
187}
188
189// CanDecode returns the set of layer types that this DecodingLayer can decode
190func (omci *SetResponse) CanDecode() gopacket.LayerClass {
191 return LayerTypeSetResponse
192}
193
194// NextLayerType returns the layer type contained by this DecodingLayer.
195func (omci *SetResponse) NextLayerType() gopacket.LayerType {
196 return gopacket.LayerTypePayload
197}
198
199// DecodeFromBytes decodes the given bytes of a Set Response into this layer
200func (omci *SetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
201 // Common ClassID/EntityID decode in msgBase
202 var hdrSize int
203 if omci.Extended {
204 hdrSize = 6 + 1 // Plus 4 more if result = 9
205 } else {
206 hdrSize = 4 + 5
207 }
208 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
209 if err != nil {
210 return err
211 }
212 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
213 me.ParamData{EntityID: omci.EntityInstance})
214 if omciErr.StatusCode() != me.Success {
215 return omciErr.GetError()
216 }
217 // ME needs to support Set
218 if !me.SupportsMsgType(entity, me.Set) {
219 return me.NewProcessingError("managed entity does not support the Set Message-Type")
220 }
221 offset := hdrSize - 5
222 omci.Result = me.Results(data[offset])
223
224 if omci.Result == me.AttributeFailure {
225 // Optional attribute masks (4 octets) is required
226 if len(data) < hdrSize+4 {
227 p.SetTruncated()
228 return errors.New("frame too small")
229 }
230 omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[offset+1:])
231 omci.FailedAttributeMask = binary.BigEndian.Uint16(data[offset+3:])
232 }
233 return nil
234}
235
236func decodeSetResponse(data []byte, p gopacket.PacketBuilder) error {
237 omci := &SetResponse{}
238 omci.MsgLayerType = LayerTypeSetResponse
239 return decodingLayerDecoder(omci, data, p)
240}
241
242func decodeSetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
243 omci := &SetResponse{}
244 omci.MsgLayerType = LayerTypeSetResponse
245 omci.Extended = true
246 return decodingLayerDecoder(omci, data, p)
247}
248
249// SerializeTo provides serialization of an Set Response message
250func (omci *SetResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
251 // Basic (common) OMCI Header is 8 octets, 10
252
253 err := omci.MeBasePacket.SerializeTo(b)
254 if err != nil {
255 return err
256 }
257 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
258 me.ParamData{EntityID: omci.EntityInstance})
259 if omciErr.StatusCode() != me.Success {
260 return omciErr.GetError()
261 }
262 // ME needs to support Set
263 if !me.SupportsMsgType(entity, me.Set) {
264 return me.NewProcessingError("managed entity does not support the Set Message-Type")
265 }
266 var offset, length int
267 if omci.Extended {
268 offset = 2
269 length = 1
270 if omci.Result == me.AttributeFailure {
271 length += 4
272 }
273 } else {
274 offset = 0
275 length = 5
276 }
277 bytes, err := b.AppendBytes(offset + length)
278 if err != nil {
279 return err
280 }
281
282 if omci.Extended {
283 binary.BigEndian.PutUint16(bytes, uint16(length))
284 bytes[offset] = byte(omci.Result)
285 if omci.Result == me.AttributeFailure {
286 binary.BigEndian.PutUint16(bytes[offset+1:], omci.UnsupportedAttributeMask)
287 binary.BigEndian.PutUint16(bytes[offset+3:], omci.FailedAttributeMask)
288 }
289 } else {
290 bytes[offset] = byte(omci.Result)
291 binary.BigEndian.PutUint16(bytes[offset+1:], omci.UnsupportedAttributeMask)
292 binary.BigEndian.PutUint16(bytes[offset+3:], omci.FailedAttributeMask)
293 }
294 return nil
295}