blob: 1a79bdc28d004c8b5a34ada691502a6546a0a0b0 [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 GetNextRequest struct {
29 MeBasePacket
30 AttributeMask uint16
31 SequenceNumber uint16
32}
33
34func (omci *GetNextRequest) String() string {
35 return fmt.Sprintf("%v, Attribute Mask: %#x, Sequence Number: %v",
36 omci.MeBasePacket.String(), omci.AttributeMask, omci.SequenceNumber)
37}
38
39// LayerType returns LayerTypeGetNextRequest
40func (omci *GetNextRequest) LayerType() gopacket.LayerType {
41 return LayerTypeGetNextRequest
42}
43
44// CanDecode returns the set of layer types that this DecodingLayer can decode
45func (omci *GetNextRequest) CanDecode() gopacket.LayerClass {
46 return LayerTypeGetNextRequest
47}
48
49// NextLayerType returns the layer type contained by this DecodingLayer.
50func (omci *GetNextRequest) NextLayerType() gopacket.LayerType {
51 return gopacket.LayerTypePayload
52}
53
54// DecodeFromBytes decodes the given bytes of a Get Next Request into this layer
55func (omci *GetNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
56 // Common ClassID/EntityID decode in msgBase
57 var hdrSize int
58 if omci.Extended {
59 //start here
60 hdrSize = 6 + 4
61 } else {
62 hdrSize = 4 + 4
63 }
64 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
65 if err != nil {
66 return err
67 }
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 GetNext
74 if !me.SupportsMsgType(meDefinition, me.GetNext) {
75 return me.NewProcessingError("managed entity does not support Get Next Message-Type")
76 }
77 // Note: G.988 specifies that an error code of (3) should result if more
78 // than one attribute is requested
79 // TODO: Return error. Have flag to optionally allow it to be encoded
80 // TODO: Check that the attribute is a table attribute. Issue warning or return error
81 omci.AttributeMask = binary.BigEndian.Uint16(data[hdrSize-4:])
82 omci.SequenceNumber = binary.BigEndian.Uint16(data[hdrSize-2:])
83 return nil
84}
85
86func decodeGetNextRequest(data []byte, p gopacket.PacketBuilder) error {
87 omci := &GetNextRequest{}
88 omci.MsgLayerType = LayerTypeGetNextRequest
89 return decodingLayerDecoder(omci, data, p)
90}
91
92func decodeGetNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
93 omci := &GetNextRequest{}
94 omci.MsgLayerType = LayerTypeGetNextRequest
95 omci.Extended = true
96 return decodingLayerDecoder(omci, data, p)
97}
98
99// SerializeTo provides serialization of an Get Next Message Type Request
100func (omci *GetNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
101 // Basic (common) OMCI Header is 8 octets, 10
102 err := omci.MeBasePacket.SerializeTo(b)
103 if err != nil {
104 return err
105 }
106 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
107 me.ParamData{EntityID: omci.EntityInstance})
108 if omciErr.StatusCode() != me.Success {
109 return omciErr.GetError()
110 }
111 // ME needs to support GetNext
112 if !me.SupportsMsgType(meDefinition, me.GetNext) {
113 return me.NewProcessingError("managed entity does not support Get Next Message-Type")
114 }
115 maskOffset := 0
116 if omci.Extended {
117 maskOffset = 2
118 }
119 bytes, err := b.AppendBytes(4 + maskOffset)
120 if err != nil {
121 return err
122 }
123 if omci.Extended {
124 binary.BigEndian.PutUint16(bytes, uint16(4))
125 }
126 binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
127 binary.BigEndian.PutUint16(bytes[maskOffset+2:], omci.SequenceNumber)
128 return nil
129}
130
131type GetNextResponse struct {
132 MeBasePacket
133 Result me.Results
134 AttributeMask uint16
135 Attributes me.AttributeValueMap
136}
137
138// SerializeTo provides serialization of an Get Next Message Type Response
139func (omci *GetNextResponse) String() string {
140 return fmt.Sprintf("%v, Result: %v, Attribute Mask: %#x, Attributes: %v",
141 omci.MeBasePacket.String(), omci.Result, omci.AttributeMask, omci.Attributes)
142}
143
144// LayerType returns LayerTypeGetNextResponse
145func (omci *GetNextResponse) LayerType() gopacket.LayerType {
146 return LayerTypeGetNextResponse
147}
148
149// CanDecode returns the set of layer types that this DecodingLayer can decode
150func (omci *GetNextResponse) CanDecode() gopacket.LayerClass {
151 return LayerTypeGetNextResponse
152}
153
154// NextLayerType returns the layer type contained by this DecodingLayer.
155func (omci *GetNextResponse) NextLayerType() gopacket.LayerType {
156 return gopacket.LayerTypePayload
157}
158
159// DecodeFromBytes decodes the given bytes of a Get Next Response into this layer
160func (omci *GetNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
161 // Common ClassID/EntityID decode in msgBase
162 var hdrSize int
163 if omci.Extended {
164 //start here
165 hdrSize = 6 + 3
166 } else {
167 hdrSize = 4 + 3
168 }
169 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
170 if err != nil {
171 return err
172 }
173 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
174 me.ParamData{EntityID: omci.EntityInstance})
175 if omciErr.StatusCode() != me.Success {
176 return omciErr.GetError()
177 }
178 // ME needs to support Set
179 if !me.SupportsMsgType(meDefinition, me.GetNext) {
180 return me.NewProcessingError("managed entity does not support Get Next Message-Type")
181 }
182 var offset int
183 if omci.Extended {
184 offset = 2
185 }
186 omci.Result = me.Results(data[4+offset])
187 if omci.Result > 6 {
188 msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
189 return errors.New(msg)
190 }
191 omci.AttributeMask = binary.BigEndian.Uint16(data[4+offset+1:])
192
193 // Attribute decode
194 omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[4+offset+3:], p, byte(GetNextResponseType))
195 if err != nil {
196 return err
197 }
198 // Validate all attributes support read
199 for attrName := range omci.Attributes {
200 attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
201 if err != nil {
202 return err
203 }
204 if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
205 msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
206 return me.NewProcessingError(msg)
207 }
208 }
209 if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
210 omci.Attributes[eidDef.GetName()] = omci.EntityInstance
211 return nil
212 }
213 panic("All Managed Entities have an EntityID attribute")
214}
215
216func decodeGetNextResponse(data []byte, p gopacket.PacketBuilder) error {
217 omci := &GetNextResponse{}
218 omci.MsgLayerType = LayerTypeGetNextResponse
219 return decodingLayerDecoder(omci, data, p)
220}
221
222func decodeGetNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
223 omci := &GetNextResponse{}
224 omci.MsgLayerType = LayerTypeGetNextResponse
225 omci.Extended = true
226 return decodingLayerDecoder(omci, data, p)
227}
228
229// SerializeTo provides serialization of an Get Next Message Type Response
230func (omci *GetNextResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
231 // Basic (common) OMCI Header is 8 octets, 10
232 err := omci.MeBasePacket.SerializeTo(b)
233 if err != nil {
234 return err
235 }
236 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
237 me.ParamData{EntityID: omci.EntityInstance})
238 if omciErr.StatusCode() != me.Success {
239 return omciErr.GetError()
240 }
241 // ME needs to support Get
242 if !me.SupportsMsgType(meDefinition, me.GetNext) {
243 return me.NewProcessingError("managed entity does not support the Get Next Message-Type")
244 }
245 var offset int
246 if omci.Extended {
247 offset = 2
248 }
249 bytes, err := b.AppendBytes(offset + 3)
250 if err != nil {
251 return err
252 }
253 bytes[offset] = byte(omci.Result)
254 if omci.Result > 6 {
255 msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
256 return errors.New(msg)
257 }
258 binary.BigEndian.PutUint16(bytes[offset+1:], omci.AttributeMask)
259
260 // Validate all attributes support read
261 for attrName := range omci.Attributes {
262 attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
263 if err != nil {
264 return err
265 }
266 if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
267 msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
268 return me.NewProcessingError(msg)
269 }
270 }
271 // Attribute serialization
272 switch omci.Result {
273 default:
274 break
275
276 case me.Success:
277 // TODO: Only Baseline supported at this time
278 if omci.Extended {
279 bytesAvailable := MaxExtendedLength - 13 - 4
280 attributeBuffer := gopacket.NewSerializeBuffer()
281 err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
282 attributeBuffer, byte(GetNextResponseType), bytesAvailable, false)
283 if err != nil {
284 return err
285 }
286 binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+3))
287 var newSpace []byte
288
289 newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
290 if err != nil {
291 return err
292 }
293 copy(newSpace, attributeBuffer.Bytes())
294 } else {
295 bytesAvailable := MaxBaselineLength - 11 - 8
296
297 err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
298 byte(GetNextResponseType), bytesAvailable, false)
299 if err != nil {
300 return err
301 }
302 }
303 }
304 return nil
305}