blob: 4f7519fe4f99fca29c3a7d3bdb3b744b3b07e088 [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
28// CreateRequest message apply only to attributes that are defined to be set by create.
29// Writeable attributes that are not set by create are not permitted in a create message
30type CreateRequest struct {
31 MeBasePacket
32 Attributes me.AttributeValueMap
33}
34
35func (omci *CreateRequest) String() string {
36 return fmt.Sprintf("%v, attributes: %v", omci.MeBasePacket.String(), omci.Attributes)
37}
38
39// LayerType returns LayerTypeCreateRequest
40func (omci *CreateRequest) LayerType() gopacket.LayerType {
41 return LayerTypeCreateRequest
42}
43
44// CanDecode returns the set of layer types that this DecodingLayer can decode
45func (omci *CreateRequest) CanDecode() gopacket.LayerClass {
46 return LayerTypeCreateRequest
47}
48
49// NextLayerType returns the layer type contained by this DecodingLayer.
50func (omci *CreateRequest) NextLayerType() gopacket.LayerType {
51 return gopacket.LayerTypePayload
52}
53
54// DecodeFromBytes decodes the given bytes of a Create Request into this layer
55func (omci *CreateRequest) 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
60 } else {
61 hdrSize = 4
62 }
63 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
64 if err != nil {
65 return err
66 }
67 // Create attribute mask for all set-by-create entries
68 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
69 me.ParamData{EntityID: omci.EntityInstance})
70 if omciErr.StatusCode() != me.Success {
71 return omciErr.GetError()
72 }
73 // ME needs to support Create
74 if !me.SupportsMsgType(meDefinition, me.Create) {
75 return me.NewProcessingError("managed entity does not support Create Message-Type")
76 }
77 var sbcMask uint16
78 for index, attr := range meDefinition.GetAttributeDefinitions() {
79 if me.SupportsAttributeAccess(attr, me.SetByCreate) {
80 if index == 0 {
81 continue // Skip Entity ID
82 }
83 sbcMask |= attr.Mask
84 }
85 }
86 // Attribute decode
87 omci.Attributes, err = meDefinition.DecodeAttributes(sbcMask, data[hdrSize:], p, byte(CreateRequestType))
88 if err != nil {
89 return err
90 }
91 if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
92 omci.Attributes[eidDef.GetName()] = omci.EntityInstance
93 return nil
94 }
95 return me.NewProcessingError("All Managed Entities have an EntityID attribute")
96}
97
98func decodeCreateRequest(data []byte, p gopacket.PacketBuilder) error {
99 omci := &CreateRequest{}
100 omci.MsgLayerType = LayerTypeCreateRequest
101 return decodingLayerDecoder(omci, data, p)
102}
103
104func decodeCreateRequestExtended(data []byte, p gopacket.PacketBuilder) error {
105 omci := &CreateRequest{}
106 omci.MsgLayerType = LayerTypeCreateRequest
107 omci.Extended = true
108 return decodingLayerDecoder(omci, data, p)
109}
110
111// SerializeTo provides serialization of an Create Request Message
112func (omci *CreateRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
113 // Basic (common) OMCI Header is 8 octets, 10
114 err := omci.MeBasePacket.SerializeTo(b)
115 if err != nil {
116 return err
117 }
118 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
119 me.ParamData{EntityID: omci.EntityInstance})
120 if omciErr.StatusCode() != me.Success {
121 return omciErr.GetError()
122 }
123 // Create attribute mask of SetByCreate attributes that should be present in the provided
124 // attributes.
125 var sbcMask uint16
126 for index, attr := range meDefinition.GetAttributeDefinitions() {
127 if me.SupportsAttributeAccess(attr, me.SetByCreate) {
128 if index == 0 {
129 continue // Skip Entity ID
130 }
131 sbcMask |= attr.Mask
132 }
133 }
134 // Attribute serialization
135 var bytesAvailable int
136 var bytes []byte
137 if omci.Extended {
138 bytesAvailable = MaxExtendedLength - 10 - 4
139 bytes, err = b.AppendBytes(2)
140 if err != nil {
141 return err
142 }
143 } else {
144 bytesAvailable = MaxBaselineLength - 8 - 8
145 }
146 attributeBuffer := gopacket.NewSerializeBuffer()
147 if err, _ = meDefinition.SerializeAttributes(omci.Attributes, sbcMask,
148 attributeBuffer, byte(CreateRequestType), bytesAvailable, false); err != nil {
149 return err
150 }
151 if omci.Extended {
152 binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())))
153 }
154 bytes, err = b.AppendBytes(len(attributeBuffer.Bytes()))
155 if err != nil {
156 return err
157 }
158 copy(bytes, attributeBuffer.Bytes())
159 return nil
160}
161
162// CreateResponse returns the result of a CreateRequest
163type CreateResponse struct {
164 MeBasePacket
165 Result me.Results
166 AttributeExecutionMask uint16 // Used when Result == ParameterError
167}
168
169func (omci *CreateResponse) String() string {
170 return fmt.Sprintf("%v, Result: %d (%v), Mask: %#x",
171 omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeExecutionMask)
172}
173
174// LayerType returns LayerTypeCreateResponse
175func (omci *CreateResponse) LayerType() gopacket.LayerType {
176 return LayerTypeCreateResponse
177}
178
179// CanDecode returns the set of layer types that this DecodingLayer can decode
180func (omci *CreateResponse) CanDecode() gopacket.LayerClass {
181 return LayerTypeCreateResponse
182}
183
184// NextLayerType returns the layer type contained by this DecodingLayer.
185func (omci *CreateResponse) NextLayerType() gopacket.LayerType {
186 return gopacket.LayerTypePayload
187}
188
189// DecodeFromBytes decodes the given bytes of a Create Response into this layer
190func (omci *CreateResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
191 // Common ClassID/EntityID decode in msgBase
192 var hdrSize, offset int
193 if omci.Extended {
194 offset = 6
195 hdrSize = offset + 1 // Plus 2 more if result = 3
196 } else {
197 offset = 4
198 hdrSize = offset + 3
199 }
200 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
201 if err != nil {
202 return err
203 }
204 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
205 me.ParamData{EntityID: omci.EntityInstance})
206 if omciErr.StatusCode() != me.Success {
207 return omciErr.GetError()
208 }
209 // ME needs to support Create
210 if !me.SupportsMsgType(entity, me.Create) {
211 return me.NewProcessingError("managed entity does not support the Create Message-Type")
212 }
213 omci.Result = me.Results(data[offset])
214 if omci.Result == me.ParameterError {
215 // Optional attribute execution mask (2 octets) is required
216 if len(data) < hdrSize+2 {
217 p.SetTruncated()
218 return errors.New("frame too small")
219 }
220 omci.AttributeExecutionMask = binary.BigEndian.Uint16(data[offset+1:])
221 }
222 return nil
223}
224
225func decodeCreateResponse(data []byte, p gopacket.PacketBuilder) error {
226 omci := &CreateResponse{}
227 omci.MsgLayerType = LayerTypeCreateResponse
228 return decodingLayerDecoder(omci, data, p)
229}
230
231func decodeCreateResponseExtended(data []byte, p gopacket.PacketBuilder) error {
232 omci := &CreateResponse{}
233 omci.MsgLayerType = LayerTypeCreateResponse
234 omci.Extended = true
235 return decodingLayerDecoder(omci, data, p)
236}
237
238// SerializeTo provides serialization of an Create Response message
239func (omci *CreateResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
240 // Basic (common) OMCI Header is 8 octets, 10
241 err := omci.MeBasePacket.SerializeTo(b)
242 if err != nil {
243 return err
244 }
245 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
246 me.ParamData{EntityID: omci.EntityInstance})
247 if omciErr.StatusCode() != me.Success {
248 return omciErr.GetError()
249 }
250 // ME needs to support Create
251 if !me.SupportsMsgType(entity, me.Create) {
252 return me.NewProcessingError("managed entity does not support the Create Message-Type")
253 }
254 var offset, extra int
255 if omci.Extended {
256 offset = 2
257 }
258 if omci.Result == me.ParameterError {
259 extra = 2
260 }
261 bytes, err := b.AppendBytes(offset + 1 + extra)
262 if err != nil {
263 return err
264 }
265 if omci.Extended {
266 binary.BigEndian.PutUint16(bytes, uint16(1+extra))
267 }
268 bytes[offset] = byte(omci.Result)
269 if omci.Result == me.ParameterError {
270 binary.BigEndian.PutUint16(bytes[offset+1:], omci.AttributeExecutionMask)
271 }
272 return nil
273}