blob: dd893d472803eadd48afda9425e0280fb5312085 [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 MibUploadRequest struct {
29 MeBasePacket
30}
31
32func (omci *MibUploadRequest) String() string {
33 return fmt.Sprintf("%v", omci.MeBasePacket.String())
34}
35
36// LayerType returns LayerTypeMibUploadRequest
37func (omci *MibUploadRequest) LayerType() gopacket.LayerType {
38 return LayerTypeMibUploadRequest
39}
40
41// CanDecode returns the set of layer types that this DecodingLayer can decode
42func (omci *MibUploadRequest) CanDecode() gopacket.LayerClass {
43 return LayerTypeMibUploadRequest
44}
45
46// NextLayerType returns the layer type contained by this DecodingLayer.
47func (omci *MibUploadRequest) NextLayerType() gopacket.LayerType {
48 return gopacket.LayerTypePayload
49}
50
51// DecodeFromBytes decodes the given bytes of a MIB Upload Request into this layer
52func (omci *MibUploadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
53 // Common ClassID/EntityID decode in msgBase
54 var hdrSize int
55 if omci.Extended {
56 hdrSize = 6
57 } else {
58 hdrSize = 4
59 }
60 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
61 if err != nil {
62 return err
63 }
64 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
65 me.ParamData{EntityID: omci.EntityInstance})
66 if omciErr.StatusCode() != me.Success {
67 return omciErr.GetError()
68 }
69 // ME needs to support MIB Upload
70 if !me.SupportsMsgType(meDefinition, me.MibUpload) {
71 return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
72 }
73 // Entity Class are always ONU DATA (2) and Entity Instance of 0
74 if omci.EntityClass != me.OnuDataClassID {
75 msg := fmt.Sprintf("invalid Entity Class for MIB Upload request: %v",
76 omci.EntityClass)
77 return me.NewProcessingError(msg)
78 }
79 if omci.EntityInstance != 0 {
80 msg := fmt.Sprintf("invalid Entity Instance for MIB Upload request: %v",
81 omci.EntityInstance)
82 return me.NewUnknownInstanceError(msg)
83 }
84 return nil
85}
86
87func decodeMibUploadRequest(data []byte, p gopacket.PacketBuilder) error {
88 omci := &MibUploadRequest{}
89 omci.MsgLayerType = LayerTypeMibUploadRequest
90 return decodingLayerDecoder(omci, data, p)
91}
92
93func decodeMibUploadRequestExtended(data []byte, p gopacket.PacketBuilder) error {
94 omci := &MibUploadRequest{}
95 omci.MsgLayerType = LayerTypeMibUploadRequest
96 omci.Extended = true
97 return decodingLayerDecoder(omci, data, p)
98}
99
100// SerializeTo provides serialization of an MIB Upload Request message
101func (omci *MibUploadRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
102 // Basic (common) OMCI Header is 8 octets, 10
103 err := omci.MeBasePacket.SerializeTo(b)
104 if err != nil {
105 return err
106 }
107 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
108 me.ParamData{EntityID: omci.EntityInstance})
109 if omciErr.StatusCode() != me.Success {
110 return omciErr.GetError()
111 }
112 // ME needs to support Get
113 if !me.SupportsMsgType(meDefinition, me.MibUpload) {
114 return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
115 }
116 // Add length if extended ident
117 if omci.Extended {
118 bytes, err := b.AppendBytes(2)
119 if err != nil {
120 return err
121 }
122 binary.BigEndian.PutUint16(bytes, 0)
123 }
124 return nil
125}
126
127type MibUploadResponse struct {
128 MeBasePacket
129 NumberOfCommands uint16
130}
131
132func (omci *MibUploadResponse) String() string {
133 return fmt.Sprintf("%v, NumberOfCommands: %#v",
134 omci.MeBasePacket.String(), omci.NumberOfCommands)
135}
136
137// LayerType returns LayerTypeMibUploadResponse
138func (omci *MibUploadResponse) LayerType() gopacket.LayerType {
139 return LayerTypeMibUploadResponse
140}
141
142// CanDecode returns the set of layer types that this DecodingLayer can decode
143func (omci *MibUploadResponse) CanDecode() gopacket.LayerClass {
144 return LayerTypeMibUploadResponse
145}
146
147// NextLayerType returns the layer type contained by this DecodingLayer.
148func (omci *MibUploadResponse) NextLayerType() gopacket.LayerType {
149 return gopacket.LayerTypePayload
150}
151
152// DecodeFromBytes decodes the given bytes of a MIB Upload Response into this layer
153func (omci *MibUploadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
154 // Common ClassID/EntityID decode in msgBase
155 var hdrSize int
156 if omci.Extended {
157 hdrSize = 6 + 2
158 } else {
159 hdrSize = 4 + 2
160 }
161 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
162 if err != nil {
163 return err
164 }
165 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
166 me.ParamData{EntityID: omci.EntityInstance})
167 if omciErr.StatusCode() != me.Success {
168 return omciErr.GetError()
169 }
170 // ME needs to support MIB Upload
171 if !me.SupportsMsgType(meDefinition, me.MibUpload) {
172 return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
173 }
174 // Entity Class are always ONU DATA (2) and Entity Instance of 0
175 if omci.EntityClass != me.OnuDataClassID {
176 msg := fmt.Sprintf("invalid Entity Class for MIB Upload response: %v",
177 omci.EntityClass)
178 return me.NewProcessingError(msg)
179 }
180 if omci.EntityInstance != 0 {
181 msg := fmt.Sprintf("invalid Entity Instance for MIB Upload response: %v",
182 omci.EntityInstance)
183 return me.NewUnknownInstanceError(msg)
184 }
185 offset := hdrSize - 2
186 omci.NumberOfCommands = binary.BigEndian.Uint16(data[offset:])
187 return nil
188}
189
190func decodeMibUploadResponse(data []byte, p gopacket.PacketBuilder) error {
191 omci := &MibUploadResponse{}
192 omci.MsgLayerType = LayerTypeMibUploadResponse
193 return decodingLayerDecoder(omci, data, p)
194}
195
196func decodeMibUploadResponseExtended(data []byte, p gopacket.PacketBuilder) error {
197 omci := &MibUploadResponse{}
198 omci.MsgLayerType = LayerTypeMibUploadResponse
199 omci.Extended = true
200 return decodingLayerDecoder(omci, data, p)
201}
202
203// SerializeTo provides serialization of an MIB Upload Response message
204func (omci *MibUploadResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
205 // Basic (common) OMCI Header
206 err := omci.MeBasePacket.SerializeTo(b)
207 if err != nil {
208 return err
209 }
210 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
211 me.ParamData{EntityID: omci.EntityInstance})
212 if omciErr.StatusCode() != me.Success {
213 return omciErr.GetError()
214 }
215 // ME needs to support MIB Upload
216 if !me.SupportsMsgType(entity, me.MibUpload) {
217 return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
218 }
219 var offset int
220 if omci.Extended {
221 offset = 2
222 }
223 bytes, err := b.AppendBytes(offset + 2)
224 if err != nil {
225 return err
226 }
227 // Add length if extended ident
228 if omci.Extended {
229 binary.BigEndian.PutUint16(bytes, 2)
230 }
231 binary.BigEndian.PutUint16(bytes[offset:], omci.NumberOfCommands)
232 return nil
233}
234
235type MibUploadNextRequest struct {
236 MeBasePacket
237 CommandSequenceNumber uint16
238}
239
240func (omci *MibUploadNextRequest) String() string {
241 return fmt.Sprintf("%v, SequenceNumberCountOrSize: %v",
242 omci.MeBasePacket.String(), omci.CommandSequenceNumber)
243}
244
245// LayerType returns LayerTypeMibUploadNextRequest
246func (omci *MibUploadNextRequest) LayerType() gopacket.LayerType {
247 return LayerTypeMibUploadNextRequest
248}
249
250// CanDecode returns the set of layer types that this DecodingLayer can decode
251func (omci *MibUploadNextRequest) CanDecode() gopacket.LayerClass {
252 return LayerTypeMibUploadNextRequest
253}
254
255// NextLayerType returns the layer type contained by this DecodingLayer.
256func (omci *MibUploadNextRequest) NextLayerType() gopacket.LayerType {
257 return gopacket.LayerTypePayload
258}
259
260// DecodeFromBytes decodes the given bytes of a MIB Upload Next Request into this layer
261func (omci *MibUploadNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
262 // Common ClassID/EntityID decode in msgBase
263 var hdrSize int
264 if omci.Extended {
265 hdrSize = 6 + 2
266 } else {
267 hdrSize = 4 + 2
268 }
269 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
270 if err != nil {
271 return err
272 }
273 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
274 me.ParamData{EntityID: omci.EntityInstance})
275 if omciErr.StatusCode() != me.Success {
276 return omciErr.GetError()
277 }
278 // ME needs to support Get All Alarms
279 if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
280 return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
281 }
282 // Entity Class are always ONU DATA (2) and Entity Instance of 0
283 if omci.EntityClass != me.OnuDataClassID {
284 msg := fmt.Sprintf("invalid Entity Class for MIB Upload Next request: %v",
285 omci.EntityClass)
286 return me.NewProcessingError(msg)
287 }
288 if omci.EntityInstance != 0 {
289 msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next request: %v",
290 omci.EntityInstance)
291 return me.NewUnknownInstanceError(msg)
292 }
293 var offset int
294 if omci.Extended {
295 offset = 2
296 }
297 omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4+offset:])
298 return nil
299}
300
301func decodeMibUploadNextRequest(data []byte, p gopacket.PacketBuilder) error {
302 omci := &MibUploadNextRequest{}
303 omci.MsgLayerType = LayerTypeMibUploadNextRequest
304 return decodingLayerDecoder(omci, data, p)
305}
306
307func decodeMibUploadNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
308 omci := &MibUploadNextRequest{}
309 omci.MsgLayerType = LayerTypeMibUploadNextRequest
310 omci.Extended = true
311 return decodingLayerDecoder(omci, data, p)
312}
313
314// SerializeTo provides serialization of an MIB Upload Next Request message
315func (omci *MibUploadNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
316 // Basic (common) OMCI Header is 8 octets, 10
317 err := omci.MeBasePacket.SerializeTo(b)
318 if err != nil {
319 return err
320 }
321 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
322 me.ParamData{EntityID: omci.EntityInstance})
323 if omciErr.StatusCode() != me.Success {
324 return omciErr.GetError()
325 }
326 // ME needs to support MIB upload
327 if !me.SupportsMsgType(entity, me.MibUploadNext) {
328 return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
329 }
330 var offset int
331 if omci.Extended {
332 offset = 2
333 }
334 bytes, err := b.AppendBytes(2 + offset)
335 if err != nil {
336 return err
337 }
338 if omci.Extended {
339 binary.BigEndian.PutUint16(bytes, 2)
340 }
341 binary.BigEndian.PutUint16(bytes[offset:], omci.CommandSequenceNumber)
342 return nil
343}
344
345type IMibUploadNextResponse interface {
346 GetMeBasePacket() *MeBasePacket
347 GetMeCount() int
348 GetManagedEntity(int) *me.ManagedEntity
349 AddManagedEntity(*me.ManagedEntity) error
350}
351
352type MibUploadNextResponse struct {
353 MeBasePacket
354 ReportedME me.ManagedEntity
355 AdditionalMEs []me.ManagedEntity // Valid only for extended message set version
356}
357
358type MibUploadNextManageEntity struct {
359 AttrSize uint16 // Size of ME instance attribute values included
360 ReportedME me.ManagedEntity
361}
362
363func (omci *MibUploadNextResponse) String() string {
364 return fmt.Sprintf("%v, ReportedME: [%v]",
365 omci.MeBasePacket.String(), omci.ReportedME.String())
366}
367
368// LayerType returns LayerTypeMibUploadNextResponse
369func (omci *MibUploadNextResponse) LayerType() gopacket.LayerType {
370 return LayerTypeMibUploadNextResponse
371}
372
373// CanDecode returns the set of layer types that this DecodingLayer can decode
374func (omci *MibUploadNextResponse) CanDecode() gopacket.LayerClass {
375 return LayerTypeMibUploadNextResponse
376}
377
378// NextLayerType returns the layer type contained by this DecodingLayer.
379func (omci *MibUploadNextResponse) NextLayerType() gopacket.LayerType {
380 return gopacket.LayerTypePayload
381}
382
383// DecodeFromBytes decodes the given bytes of a MIB Upload Next Response into this layer
384func (omci *MibUploadNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
385 // Common ClassID/EntityID decode in msgBase
386 var hdrSize int
387 if omci.Extended {
388 hdrSize = 6
389 } else {
390 hdrSize = 4
391 }
392 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
393 if err != nil {
394 return err
395 }
396 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
397 me.ParamData{EntityID: omci.EntityInstance})
398 if omciErr.StatusCode() != me.Success {
399 return omciErr.GetError()
400 }
401 // ME needs to support MibUploadNext
402 if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
403 return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
404 }
405 // Entity Class are always ONU DATA (2) and Entity Instance of 0
406 if omci.EntityClass != me.OnuDataClassID {
407 msg := fmt.Sprintf("invalid Entity Class for MIB Upload Next response: %v",
408 omci.EntityClass)
409 return me.NewProcessingError(msg)
410 }
411 if omci.EntityInstance != 0 {
412 msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next response: %v",
413 omci.EntityInstance)
414 return me.NewUnknownInstanceError(msg)
415 }
416 // Decode reported ME. If an out-of-range sequence number was sent, this will
417 // contain an ME with class ID and entity ID of zero and you should get an
418 // error of "managed entity definition not found" returned.
419 var offset int
420 var attrLen int
421 if omci.Extended {
422 offset = 2 + 2 // Message Contents length (2) + first ME attribute values len (2)
423 attrLen = int(binary.BigEndian.Uint16(data[6:]))
424
425 if len(data[4+offset:]) < 6+attrLen {
426 p.SetTruncated()
427 return errors.New("frame too small: MIB Upload Response Managed Entity attribute truncated")
428 }
429 }
430 err = omci.ReportedME.DecodeFromBytes(data[4+offset:], p, byte(MibUploadNextResponseType))
431 if err != nil || !omci.Extended {
432 return err
433 }
434 // Handle extended message set decode here for additional attributes
435 remaining := len(data) - (6 + 8 + attrLen)
436 if remaining > 0 {
437 offset = 6 + 8 + attrLen
438 omci.AdditionalMEs = make([]me.ManagedEntity, 0)
439 for remaining > 0 {
440 if len(data[offset:]) < 8 {
441 p.SetTruncated()
442 // TODO: Review all "frame to small" and add an extra hint for developers
443 return errors.New("frame too small: MIB Upload Response Managed Entity header truncated")
444 }
445 additional := me.ManagedEntity{}
446 attrLen = int(binary.BigEndian.Uint16(data[offset:]))
447
448 if len(data[offset:]) < 8+attrLen {
449 p.SetTruncated()
450 return errors.New("frame too small: MIB Upload Response Managed Entity attribute truncated")
451 }
452 err = additional.DecodeFromBytes(data[offset+2:], p, byte(MibUploadNextResponseType))
453 if err != nil {
454 return err
455 }
456 omci.AdditionalMEs = append(omci.AdditionalMEs, additional)
457 remaining -= 8 + attrLen
458 offset += 8 + attrLen
459 }
460 }
461 return nil
462}
463
464func decodeMibUploadNextResponse(data []byte, p gopacket.PacketBuilder) error {
465 omci := &MibUploadNextResponse{}
466 omci.MsgLayerType = LayerTypeMibUploadNextResponse
467 return decodingLayerDecoder(omci, data, p)
468}
469
470func decodeMibUploadNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
471 omci := &MibUploadNextResponse{}
472 omci.MsgLayerType = LayerTypeMibUploadNextResponse
473 omci.Extended = true
474 return decodingLayerDecoder(omci, data, p)
475}
476
477// SerializeTo provides serialization of an MIB Upload Next Response message
478func (omci *MibUploadNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
479 // Basic (common) OMCI Header
480 err := omci.MeBasePacket.SerializeTo(b)
481 if err != nil {
482 return err
483 }
484 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
485 me.ParamData{EntityID: omci.EntityInstance})
486 if omciErr.StatusCode() != me.Success {
487 return omciErr.GetError()
488 }
489 // ME needs to support MIB Upload
490 if !me.SupportsMsgType(entity, me.MibUploadNext) {
491 return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
492 }
493 bytesAvailable := MaxBaselineLength - 8 - 8
494
495 if omci.Extended {
496 bytesAvailable = MaxExtendedLength - 10 - 4
497 }
498 attributeBuffer := gopacket.NewSerializeBuffer()
499 attrErr := omci.ReportedME.SerializeTo(attributeBuffer, byte(MibUploadNextResponseType), bytesAvailable, opts)
500 if attrErr != nil {
501 return attrErr
502 }
503 var offset int
504 if omci.Extended {
505 offset = 2 + 2 // Message Contents length (2) + first ME attribute values len (2)
506 }
507 meLength := len(attributeBuffer.Bytes())
508 buf, attrErr := b.AppendBytes(meLength + offset)
509 if attrErr != nil {
510 return attrErr
511 }
512 if omci.Extended {
513 binary.BigEndian.PutUint16(buf, uint16(meLength+2))
514 binary.BigEndian.PutUint16(buf[2:], uint16(meLength-6))
515 }
516 copy(buf[offset:], attributeBuffer.Bytes())
517
518 if omci.Extended && omci.AdditionalMEs != nil {
519 // Handle additional Managed Entities here for the Extended Message set
520 bytesAvailable -= 4 + meLength
521 length := meLength + 2
522
523 for index, entry := range omci.AdditionalMEs {
524 if bytesAvailable <= 8 {
525 msg := fmt.Sprintf("not enough space to fit all requested Managed Entities, entry: %v", index)
526 attrErr = me.NewMessageTruncatedError(msg)
527 if attrErr != nil {
528 return attrErr
529 }
530 }
531 attributeBuffer = gopacket.NewSerializeBuffer()
532 attrErr = entry.SerializeTo(attributeBuffer, byte(MibUploadNextResponseType), bytesAvailable, opts)
533 if attrErr != nil {
534 return attrErr
535 }
536 meLength = len(attributeBuffer.Bytes())
537 buf, attrErr = b.AppendBytes(2 + meLength)
538 if attrErr != nil {
539 return attrErr
540 }
541 binary.BigEndian.PutUint16(buf, uint16(meLength-6))
542 copy(buf[2:], attributeBuffer.Bytes())
543 length += 2 + meLength
544 bytesAvailable -= 2 + meLength
545 }
546 msgBuffer := b.Bytes()
547 binary.BigEndian.PutUint16(msgBuffer[4:], uint16(length))
548 }
549 return nil
550}