blob: 2bb163c8a9682dc10a1e7c1c989db449d8396e8f [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"
Holger Hildebrandt8c4afc02022-07-07 15:11:26 +000024
Chip Boling610117d2021-09-09 11:24:34 -050025 "github.com/google/gopacket"
Andrea Campanellae0cd8232021-10-15 15:10:23 +020026 me "github.com/opencord/omci-lib-go/v2/generated"
Chip Boling610117d2021-09-09 11:24:34 -050027)
28
29type GetAllAlarmsRequest struct {
30 MeBasePacket
31 AlarmRetrievalMode byte
32}
33
34func (omci *GetAllAlarmsRequest) String() string {
35 return fmt.Sprintf("%v, Retrieval Mode: %v",
36 omci.MeBasePacket.String(), omci.AlarmRetrievalMode)
37}
38
39// LayerType returns LayerTypeGetAllAlarmsRequest
40func (omci *GetAllAlarmsRequest) LayerType() gopacket.LayerType {
41 return LayerTypeGetAllAlarmsRequest
42}
43
44// CanDecode returns the set of layer types that this DecodingLayer can decode
45func (omci *GetAllAlarmsRequest) CanDecode() gopacket.LayerClass {
46 return LayerTypeGetAllAlarmsRequest
47}
48
49// NextLayerType returns the layer type contained by this DecodingLayer.
50func (omci *GetAllAlarmsRequest) NextLayerType() gopacket.LayerType {
51 return gopacket.LayerTypePayload
52}
53
54// DecodeFromBytes decodes the given bytes of a Get All Alarms Request into this layer
55func (omci *GetAllAlarmsRequest) 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 + 1
61 } else {
62 hdrSize = 4 + 1
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 Get All Alarms
74 if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
75 return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
76 }
77 // Entity Class are always ONU DATA (2) and Entity Instance of 0
78 if omci.EntityClass != me.OnuDataClassID {
79 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms request: %v",
80 omci.EntityClass)
81 return me.NewProcessingError(msg)
82 }
83 if omci.EntityInstance != 0 {
84 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms request: %v",
85 omci.EntityInstance)
86 return me.NewUnknownInstanceError(msg)
87 }
88 var offset int
89 if omci.Extended {
90 offset = 2
91 }
92 omci.AlarmRetrievalMode = data[4+offset]
93 if omci.AlarmRetrievalMode > 1 {
94 msg := fmt.Sprintf("invalid Alarm Retrieval Mode for Get All Alarms request: %v, must be 0..1",
95 omci.AlarmRetrievalMode)
96 return errors.New(msg)
97 }
98 return nil
99}
100
101func decodeGetAllAlarmsRequest(data []byte, p gopacket.PacketBuilder) error {
102 omci := &GetAllAlarmsRequest{}
103 omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
104 return decodingLayerDecoder(omci, data, p)
105}
106
107func decodeGetAllAlarmsRequestExtended(data []byte, p gopacket.PacketBuilder) error {
108 omci := &GetAllAlarmsRequest{}
109 omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
110 omci.Extended = true
111 return decodingLayerDecoder(omci, data, p)
112}
113
114// SerializeTo provides serialization of an Get All Alarms Request message
115func (omci *GetAllAlarmsRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
116 // Basic (common) OMCI Header is 8 octets, 10
117 err := omci.MeBasePacket.SerializeTo(b)
118 if err != nil {
119 return err
120 }
121 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
122 me.ParamData{EntityID: omci.EntityInstance})
123 if omciErr.StatusCode() != me.Success {
124 return omciErr.GetError()
125 }
126 // ME needs to support Get All Alarms
127 if !me.SupportsMsgType(entity, me.GetAllAlarms) {
128 return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
129 }
130 var offset int
131 if omci.Extended {
132 offset = 2
133 }
134 bytes, err := b.AppendBytes(offset + 1)
135 if err != nil {
136 return err
137 }
138 if omci.Extended {
139 binary.BigEndian.PutUint16(bytes, uint16(1))
140 }
141 bytes[offset] = omci.AlarmRetrievalMode
142 return nil
143}
144
145type GetAllAlarmsResponse struct {
146 MeBasePacket
147 NumberOfCommands uint16
148}
149
150func (omci *GetAllAlarmsResponse) String() string {
151 return fmt.Sprintf("%v, NumberOfCommands: %d",
152 omci.MeBasePacket.String(), omci.NumberOfCommands)
153}
154
155// LayerType returns LayerTypeGetAllAlarmsResponse
156func (omci *GetAllAlarmsResponse) LayerType() gopacket.LayerType {
157 return LayerTypeGetAllAlarmsResponse
158}
159
160// CanDecode returns the set of layer types that this DecodingLayer can decode
161func (omci *GetAllAlarmsResponse) CanDecode() gopacket.LayerClass {
162 return LayerTypeGetAllAlarmsResponse
163}
164
165// NextLayerType returns the layer type contained by this DecodingLayer.
166func (omci *GetAllAlarmsResponse) NextLayerType() gopacket.LayerType {
167 return gopacket.LayerTypePayload
168}
169
170// DecodeFromBytes decodes the given bytes of a Get All Alarms Response into this layer
171func (omci *GetAllAlarmsResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
172 // Common ClassID/EntityID decode in msgBase
173 var hdrSize int
174 if omci.Extended {
175 //start here
176 hdrSize = 6 + 2
177 } else {
178 hdrSize = 4 + 2
179 }
180 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
181 if err != nil {
182 return err
183 }
184 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
185 me.ParamData{EntityID: omci.EntityInstance})
186 if omciErr.StatusCode() != me.Success {
187 return omciErr.GetError()
188 }
189 // ME needs to support Get All Alarms
190 if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
191 return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
192 }
193 // Entity Class are always ONU DATA (2) and Entity Instance of 0
194 if omci.EntityClass != me.OnuDataClassID {
195 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms response: %v",
196 omci.EntityClass)
197 return me.NewProcessingError(msg)
198 }
199 if omci.EntityInstance != 0 {
200 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms response: %v",
201 omci.EntityInstance)
202 return me.NewUnknownInstanceError(msg)
203 }
204 var offset int
205 if omci.Extended {
206 offset = 2
207 }
208 omci.NumberOfCommands = binary.BigEndian.Uint16(data[4+offset:])
209 return nil
210}
211
212func decodeGetAllAlarmsResponse(data []byte, p gopacket.PacketBuilder) error {
213 omci := &GetAllAlarmsResponse{}
214 omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
215 return decodingLayerDecoder(omci, data, p)
216}
217
218func decodeGetAllAlarmsResponseExtended(data []byte, p gopacket.PacketBuilder) error {
219 omci := &GetAllAlarmsResponse{}
220 omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
221 omci.Extended = true
222 return decodingLayerDecoder(omci, data, p)
223}
224
225// SerializeTo provides serialization of an Get All Alarms Response message
226func (omci *GetAllAlarmsResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
227 // Basic (common) OMCI Header is 8 octets, 10
228 err := omci.MeBasePacket.SerializeTo(b)
229 if err != nil {
230 return err
231 }
232 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
233 me.ParamData{EntityID: omci.EntityInstance})
234 if omciErr.StatusCode() != me.Success {
235 return omciErr.GetError()
236 }
237 // ME needs to support Get All Alarms
238 if !me.SupportsMsgType(entity, me.GetAllAlarms) {
239 return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
240 }
241 var offset int
242 if omci.Extended {
243 offset = 2
244 }
245 bytes, err := b.AppendBytes(offset + 2)
246 if err != nil {
247 return err
248 }
249 if omci.Extended {
250 binary.BigEndian.PutUint16(bytes, uint16(2))
251 }
252 binary.BigEndian.PutUint16(bytes[offset:], omci.NumberOfCommands)
253 return nil
254}
255
256type GetAllAlarmsNextRequest struct {
257 MeBasePacket
258 CommandSequenceNumber uint16
259}
260
261func (omci *GetAllAlarmsNextRequest) String() string {
262 return fmt.Sprintf("%v, Sequence Number: %d",
263 omci.MeBasePacket.String(), omci.CommandSequenceNumber)
264}
265
266// LayerType returns LayerTypeGetAllAlarmsNextRequest
267func (omci *GetAllAlarmsNextRequest) LayerType() gopacket.LayerType {
268 return LayerTypeGetAllAlarmsNextRequest
269}
270
271// CanDecode returns the set of layer types that this DecodingLayer can decode
272func (omci *GetAllAlarmsNextRequest) CanDecode() gopacket.LayerClass {
273 return LayerTypeGetAllAlarmsNextRequest
274}
275
276// NextLayerType returns the layer type contained by this DecodingLayer.
277func (omci *GetAllAlarmsNextRequest) NextLayerType() gopacket.LayerType {
278 return gopacket.LayerTypePayload
279}
280
281// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Request into this layer
282func (omci *GetAllAlarmsNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
283 // Common ClassID/EntityID decode in msgBase
284 var hdrSize int
285 if omci.Extended {
286 //start here
287 hdrSize = 6 + 2
288 } else {
289 hdrSize = 4 + 2
290 }
291 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
292 if err != nil {
293 return err
294 }
295 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
296 me.ParamData{EntityID: omci.EntityInstance})
297 if omciErr.StatusCode() != me.Success {
298 return omciErr.GetError()
299 }
300 // ME needs to support Get All Alarms
301 if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
302 return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
303 }
304 // Entity Class are always ONU DATA (2) and Entity Instance of 0
305 if omci.EntityClass != me.OnuDataClassID {
306 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next request: %v",
307 omci.EntityClass)
308 return me.NewProcessingError(msg)
309 }
310 if omci.EntityInstance != 0 {
311 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next request: %v",
312 omci.EntityInstance)
313 return me.NewUnknownInstanceError(msg)
314 }
315 var offset int
316 if omci.Extended {
317 offset = 2
318 }
319 omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4+offset:])
320 return nil
321}
322
323func decodeGetAllAlarmsNextRequest(data []byte, p gopacket.PacketBuilder) error {
324 omci := &GetAllAlarmsNextRequest{}
325 omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
326 return decodingLayerDecoder(omci, data, p)
327}
328
329func decodeGetAllAlarmsNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
330 omci := &GetAllAlarmsNextRequest{}
331 omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
332 omci.Extended = true
333 return decodingLayerDecoder(omci, data, p)
334}
335
336// SerializeTo provides serialization of an Get All Alarms Next Request message
337func (omci *GetAllAlarmsNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
338 // Basic (common) OMCI Header is 8 octets, 10
339 err := omci.MeBasePacket.SerializeTo(b)
340 if err != nil {
341 return err
342 }
343 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
344 me.ParamData{EntityID: omci.EntityInstance})
345 if omciErr.StatusCode() != me.Success {
346 return omciErr.GetError()
347 }
348 // ME needs to support Get All Alarms Next
349 if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
350 return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
351 }
352 var offset int
353 if omci.Extended {
354 offset = 2
355 }
356 bytes, err := b.AppendBytes(offset + 2)
357 if err != nil {
358 return err
359 }
360 if omci.Extended {
361 binary.BigEndian.PutUint16(bytes, uint16(2))
362 }
363 binary.BigEndian.PutUint16(bytes[offset:], omci.CommandSequenceNumber)
364 return nil
365}
366
367type AdditionalAlarmsData struct {
368 AlarmEntityClass me.ClassID
369 AlarmEntityInstance uint16
370 AlarmBitMap [28]byte // 224 bits
371}
372
373type GetAllAlarmsNextResponse struct {
374 MeBasePacket
375 AlarmEntityClass me.ClassID
376 AlarmEntityInstance uint16
377 AlarmBitMap [28]byte // 224 bits
378 AdditionalAlarms []AdditionalAlarmsData // Valid only for extended message set version
379}
380
381func (omci *GetAllAlarmsNextResponse) String() string {
382 return fmt.Sprintf("%v, CID: %v, EID: (%d/%#x), Bitmap: %v",
383 omci.MeBasePacket.String(), omci.AlarmEntityClass, omci.AlarmEntityInstance,
384 omci.AlarmEntityInstance, omci.AlarmBitMap)
385}
386
387// LayerType returns LayerTypeGetAllAlarmsNextResponse
388func (omci *GetAllAlarmsNextResponse) LayerType() gopacket.LayerType {
389 return LayerTypeGetAllAlarmsNextResponse
390}
391
392// CanDecode returns the set of layer types that this DecodingLayer can decode
393func (omci *GetAllAlarmsNextResponse) CanDecode() gopacket.LayerClass {
394 return LayerTypeGetAllAlarmsNextResponse
395}
396
397// NextLayerType returns the layer type contained by this DecodingLayer.
398func (omci *GetAllAlarmsNextResponse) NextLayerType() gopacket.LayerType {
399 return gopacket.LayerTypePayload
400}
401
402// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Response into this layer
403func (omci *GetAllAlarmsNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
404 // Common ClassID/EntityID decode in msgBase
405 var hdrSize int
406 if omci.Extended {
407 hdrSize = 6
408 } else {
409 hdrSize = 4
410 }
411 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
412 if err != nil {
413 return err
414 }
415 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
416 me.ParamData{EntityID: omci.EntityInstance})
417 if omciErr.StatusCode() != me.Success {
418 return omciErr.GetError()
419 }
420 // ME needs to support Get All Alarms Next
421 if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
422 return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
423 }
424 // Entity Class are always ONU DATA (2) and Entity Instance of 0
425 if omci.EntityClass != me.OnuDataClassID {
426 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next response: %v",
427 omci.EntityClass)
428 return me.NewProcessingError(msg)
429 }
430 if omci.EntityInstance != 0 {
431 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next response: %v",
432 omci.EntityInstance)
433 return me.NewUnknownInstanceError(msg)
434 }
435 //err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4+28) // Decode reported ME. If an out-of-range sequence number was sent, this will
436 // // contain an ME with class ID and entity ID of zero and you should get an
437 // // error of "managed entity definition not found" returned.
438 var offset int
439 msgContentsLen := 28
440 if omci.Extended {
441 offset = 2 // Message Contents length (2)
442 msgContentsLen = int(binary.BigEndian.Uint16(data[6:]))
443 }
444 if len(data[4+offset:]) < 4+msgContentsLen {
445 p.SetTruncated()
446 return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
447 }
448 omci.AlarmEntityClass = me.ClassID(binary.BigEndian.Uint16(data[4+offset:]))
449 omci.AlarmEntityInstance = binary.BigEndian.Uint16(data[6+offset:])
450
451 copy(omci.AlarmBitMap[:], data[8+offset:36])
452 remaining := len(data) - (6 + 4 + 28)
453
454 if !omci.Extended || remaining <= 0 {
455 return nil
456 }
457 offset = 6 + 4 + 28
458 omci.AdditionalAlarms = make([]AdditionalAlarmsData, 0)
459 for remaining > 0 {
460 if remaining < 4+28 {
461 p.SetTruncated()
462 return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
463 }
464 alarm := AdditionalAlarmsData{
465 AlarmEntityClass: me.ClassID(binary.BigEndian.Uint16(data[offset:])),
466 AlarmEntityInstance: binary.BigEndian.Uint16(data[offset+2:]),
467 }
468 copy(alarm.AlarmBitMap[:], data[offset+4:])
469 omci.AdditionalAlarms = append(omci.AdditionalAlarms, alarm)
470
471 offset += 4 + 28
472 remaining -= 4 + 28
473 }
474 return nil
475}
476
477func decodeGetAllAlarmsNextResponse(data []byte, p gopacket.PacketBuilder) error {
478 omci := &GetAllAlarmsNextResponse{}
479 omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
480 return decodingLayerDecoder(omci, data, p)
481}
482
483func decodeGetAllAlarmsNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
484 omci := &GetAllAlarmsNextResponse{}
485 omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
486 omci.Extended = true
487 return decodingLayerDecoder(omci, data, p)
488}
489
490// SerializeTo provides serialization of an Get All Alarms Next Response message
491func (omci *GetAllAlarmsNextResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
492 // Basic (common) OMCI Header is 8 octets, 10
493 err := omci.MeBasePacket.SerializeTo(b)
494 if err != nil {
495 return err
496 }
497 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
498 me.ParamData{EntityID: omci.EntityInstance})
499 if omciErr.StatusCode() != me.Success {
500 return omciErr.GetError()
501 }
502 // ME needs to support Get All Alarms Next
503 if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
504 return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
505 }
506 contentLength := 2 + 2 + 28
507 maxLength := MaxBaselineLength - 8 - 8
508 var extraMEs int
509 var offset int
510
511 if omci.Extended {
512 maxLength = MaxExtendedLength - 10 - 4
513 offset = 2
514 contentLength += 2 // Length field
515 if omci.AdditionalAlarms != nil {
516 extraMEs = len(omci.AdditionalAlarms)
Holger Hildebrandt8c4afc02022-07-07 15:11:26 +0000517 contentLength += extraMEs * (4 + 28)
Chip Boling610117d2021-09-09 11:24:34 -0500518 }
519 }
520 if contentLength > maxLength {
521 msg := fmt.Sprintf("not enough space to fit all requested Managed Entities, have %v, requested: %v",
522 maxLength, contentLength)
523 return me.NewMessageTruncatedError(msg)
524 }
525 // Allocate space for all
526 bytes, err := b.AppendBytes(contentLength)
527 if err != nil {
528 return err
529 }
530 // Always encode the first ME alarm data
531 binary.BigEndian.PutUint16(bytes[offset:], uint16(omci.AlarmEntityClass))
532 binary.BigEndian.PutUint16(bytes[offset+2:], omci.AlarmEntityInstance)
533 copy(bytes[offset+4:], omci.AlarmBitMap[:])
534
535 if omci.Extended {
536 binary.BigEndian.PutUint16(bytes, uint16(contentLength-2))
537
538 if omci.AdditionalAlarms != nil {
539 for index, value := range omci.AdditionalAlarms {
540 offset = (32 * (index + 1)) + 2
541 binary.BigEndian.PutUint16(bytes[offset:], uint16(value.AlarmEntityClass))
542 binary.BigEndian.PutUint16(bytes[offset+2:], value.AlarmEntityInstance)
543 copy(bytes[offset+4:], value.AlarmBitMap[:])
544 }
545 }
546 }
547 return nil
548}
549
550const AlarmBitmapSize = 224
551
552type AlarmNotificationMsg struct {
553 MeBasePacket
554 AlarmBitmap [AlarmBitmapSize / 8]byte
555 zeroPadding [3]byte // Note: This zero padding is not present in the Extended Message Set
556 AlarmSequenceNumber byte
557}
558
559func (omci *AlarmNotificationMsg) String() string {
560 return fmt.Sprintf("%v, Sequence Number: %d, Alarm Bitmap: %v",
561 omci.MeBasePacket.String(), omci.AlarmSequenceNumber, omci.AlarmBitmap)
562}
563
564// LayerType returns LayerTypeAlarmNotification
565func (omci *AlarmNotificationMsg) LayerType() gopacket.LayerType {
566 return LayerTypeAlarmNotification
567}
568
569// CanDecode returns the set of layer types that this DecodingLayer can decode
570func (omci *AlarmNotificationMsg) CanDecode() gopacket.LayerClass {
571 return LayerTypeAlarmNotification
572}
573
574// NextLayerType returns the layer type contained by this DecodingLayer.
575func (omci *AlarmNotificationMsg) NextLayerType() gopacket.LayerType {
576 return gopacket.LayerTypePayload
577}
578
579func (omci *AlarmNotificationMsg) IsAlarmActive(alarmNumber uint8) (bool, error) {
580 if alarmNumber >= AlarmBitmapSize {
581 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
582 return false, errors.New(msg)
583 }
584 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
585 me.ParamData{EntityID: omci.EntityInstance})
586 if omciErr.StatusCode() != me.Success {
587 return false, omciErr.GetError()
588 }
589 alarmMap := entity.GetAlarmMap()
590 if alarmMap == nil {
591 msg := "managed entity does not support Alarm notifications"
592 return false, errors.New(msg)
593 }
594 if _, ok := alarmMap[alarmNumber]; !ok {
595 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
596 return false, errors.New(msg)
597 }
598 octet := alarmNumber / 8
599 bit := 7 - (alarmNumber % 8)
600 return omci.AlarmBitmap[octet]>>bit == 1, nil
601}
602
603func (omci *AlarmNotificationMsg) IsAlarmClear(alarmNumber uint8) (bool, error) {
604 if alarmNumber >= AlarmBitmapSize {
605 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
606 return false, errors.New(msg)
607 }
608 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
609 me.ParamData{EntityID: omci.EntityInstance})
610 if omciErr.StatusCode() != me.Success {
611 return false, omciErr.GetError()
612 }
613 alarmMap := entity.GetAlarmMap()
614 if alarmMap == nil {
615 return false, errors.New("managed entity does not support Alarm notifications")
616 }
617 if _, ok := alarmMap[alarmNumber]; !ok {
618 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
619 return false, errors.New(msg)
620 }
621 octet := alarmNumber / 8
622 bit := 7 - (alarmNumber % 8)
623 return omci.AlarmBitmap[octet]>>bit == 0, nil
624}
625
626func (omci *AlarmNotificationMsg) ActivateAlarm(alarmNumber uint8) error {
627 if alarmNumber >= AlarmBitmapSize {
628 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
629 return errors.New(msg)
630 }
631 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
632 me.ParamData{EntityID: omci.EntityInstance})
633 if omciErr.StatusCode() != me.Success {
634 return omciErr.GetError()
635 }
636 alarmMap := entity.GetAlarmMap()
637 if alarmMap == nil {
638 return errors.New("managed entity does not support Alarm notifications")
639 }
640 if _, ok := alarmMap[alarmNumber]; !ok {
641 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
642 return errors.New(msg)
643 }
644 octet := alarmNumber / 8
645 bit := 7 - (alarmNumber % 8)
646 omci.AlarmBitmap[octet] |= 1 << bit
647 return nil
648}
649
650func (omci *AlarmNotificationMsg) ClearAlarm(alarmNumber uint8) error {
651 if alarmNumber >= AlarmBitmapSize {
652 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
653 return errors.New(msg)
654 }
655 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
656 me.ParamData{EntityID: omci.EntityInstance})
657 if omciErr.StatusCode() != me.Success {
658 return omciErr.GetError()
659 }
660 alarmMap := entity.GetAlarmMap()
661 if alarmMap == nil {
662 return errors.New("managed entity does not support Alarm notifications")
663 }
664 if _, ok := alarmMap[alarmNumber]; !ok {
665 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
666 return errors.New(msg)
667 }
668 octet := alarmNumber / 8
669 bit := 7 - (alarmNumber % 8)
670 omci.AlarmBitmap[octet] &= ^(1 << bit)
671 return nil
672}
673
674// DecodeFromBytes decodes the given bytes of an Alarm Notification into this layer
675func (omci *AlarmNotificationMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
676 // Common ClassID/EntityID decode in msgBase
677 err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+28)
678 if err != nil {
679 return err
680 }
681 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
682 me.ParamData{EntityID: omci.EntityInstance})
683 if omciErr.StatusCode() != me.Success {
684 return omciErr.GetError()
685 }
686 // Is this an unsupported or vendor specific ME. If so, it is not an error to decode
687 // the alarms. We just cannot provide any alarm names. Handle decode here.
688 classSupport := meDefinition.GetClassSupport()
689 isUnsupported := classSupport == me.UnsupportedManagedEntity ||
690 classSupport == me.UnsupportedVendorSpecificManagedEntity
691
692 mapOffset := 4
693 if omci.Extended {
694 mapOffset = 6
695 if len(data) < 6+28+1 {
696 p.SetTruncated()
697 return errors.New("frame too small")
698 }
699 }
700 // Look for a non-nil/not empty Alarm Map to determine if this ME supports alarms
701 if alarmMap := meDefinition.GetAlarmMap(); isUnsupported || (alarmMap != nil && len(alarmMap) > 0) {
702 for index, octet := range data[mapOffset : (AlarmBitmapSize/8)-mapOffset] {
703 omci.AlarmBitmap[index] = octet
704 }
705 if omci.Extended {
706 omci.AlarmSequenceNumber = data[mapOffset+(AlarmBitmapSize/8)]
707 } else {
708 padOffset := mapOffset + (AlarmBitmapSize / 8)
709 omci.zeroPadding[0] = data[padOffset]
710 omci.zeroPadding[1] = data[padOffset+1]
711 omci.zeroPadding[2] = data[padOffset+2]
712 omci.AlarmSequenceNumber = data[padOffset+3]
713 }
714 return nil
715 }
716 return me.NewProcessingError("managed entity does not support alarm notifications")
717}
718
719func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
720 omci := &AlarmNotificationMsg{}
721 omci.MsgLayerType = LayerTypeAlarmNotification
722 return decodingLayerDecoder(omci, data, p)
723}
724
725func decodeAlarmNotificationExtended(data []byte, p gopacket.PacketBuilder) error {
726 omci := &AlarmNotificationMsg{}
727 omci.MsgLayerType = LayerTypeAlarmNotification
728 omci.Extended = true
729 return decodingLayerDecoder(omci, data, p)
730}
731
732// SerializeTo provides serialization of an Alarm Notification message
733func (omci *AlarmNotificationMsg) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
734 // Basic (common) OMCI Header is 8 octets, 10
735 err := omci.MeBasePacket.SerializeTo(b)
736 if err != nil {
737 return err
738 }
739 // TODO: Support of encoding AlarmNotification into supported types not yet supported
740 //meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
741 // me.ParamData{EntityID: omci.EntityInstance})
742 //if omciErr.StatusCode() != me.Success {
743 // return omciErr.GetError()
744 //}
745 //if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
746 // return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
747 //}
748 if omci.Extended {
749 bytes, err := b.AppendBytes(2 + (AlarmBitmapSize / 8) + 1)
750 if err != nil {
751 return err
752 }
753 binary.BigEndian.PutUint16(bytes, uint16((AlarmBitmapSize/8)+1))
754
755 for index, octet := range omci.AlarmBitmap {
756 bytes[2+index] = octet
757 }
758 bytes[2+(AlarmBitmapSize/8)] = omci.AlarmSequenceNumber
759 } else {
760 bytes, err := b.AppendBytes((AlarmBitmapSize / 8) + 3 + 1)
761 if err != nil {
762 return err
763 }
764 for index, octet := range omci.AlarmBitmap {
765 bytes[index] = octet
766 }
767 padOffset := AlarmBitmapSize / 8
768 bytes[padOffset] = 0
769 bytes[padOffset+1] = 0
770 bytes[padOffset+2] = 0
771 bytes[padOffset+3] = omci.AlarmSequenceNumber
772 }
773 return nil
774}