blob: 923fc0263406caab5da245b97749d3d874c6fc04 [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"
Andrea Campanellae0cd8232021-10-15 15:10:23 +020025 me "github.com/opencord/omci-lib-go/v2/generated"
Chip Boling610117d2021-09-09 11:24:34 -050026)
27
28func decodeTestRequest(data []byte, p gopacket.PacketBuilder) error {
29 // Peek at Managed Entity Type
30 if len(data) < 8 {
31 p.SetTruncated()
32 return errors.New("frame too small")
33 }
34 classID := binary.BigEndian.Uint16(data)
35
36 // Is it a Managed Entity class we support customized decode of?
37 switch me.ClassID(classID) {
38 default:
39 omci := &TestRequest{}
40 omci.MsgLayerType = LayerTypeTestRequest
41 return decodingLayerDecoder(omci, data, p)
42
43 case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
44 me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
45 omci := &OpticalLineSupervisionTestRequest{}
46 omci.MsgLayerType = LayerTypeTestRequest
47 return decodingLayerDecoder(omci, data, p)
48 }
49}
50
51// TestRequest message
52type TestRequest struct {
53 MeBasePacket
54 Payload []byte
55}
56
57func (omci *TestRequest) String() string {
58 return fmt.Sprintf("%v, Request: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
59}
60
61// LayerType returns LayerTypeTestRequest
62func (omci *TestRequest) LayerType() gopacket.LayerType {
63 return LayerTypeTestRequest
64}
65
66// CanDecode returns the set of layer types that this DecodingLayer can decode
67func (omci *TestRequest) CanDecode() gopacket.LayerClass {
68 return LayerTypeTestRequest
69}
70
71// NextLayerType returns the layer type contained by this DecodingLayer.
72func (omci *TestRequest) NextLayerType() gopacket.LayerType {
73 return gopacket.LayerTypePayload
74}
75
76func (omci *TestRequest) TestRequest() []byte {
77 return omci.Payload
78}
79
80// DecodeFromBytes decodes the given bytes of a Test Request into this layer
81func (omci *TestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
82 // Common ClassID/EntityID decode in msgBase
83 err := omci.MeBasePacket.DecodeFromBytes(data, p, 4)
84 if err != nil {
85 return err
86 }
87
88 omci.Payload = make([]byte, MaxTestRequestLength)
89 copy(omci.Payload, omci.MeBasePacket.Payload)
90 return nil
91}
92
93// SerializeTo provides serialization of an Test Request message
94func (omci *TestRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
95 // Basic (common) OMCI Header is 8 octets, 10
96 err := omci.MeBasePacket.SerializeTo(b)
97 if err != nil {
98 return err
99 }
100 if omci.Payload == nil {
101 return errors.New("test results payload is missing")
102 }
103
104 if len(omci.Payload) > MaxTestRequestLength {
105 msg := fmt.Sprintf("Invalid Test Request payload size. Received %v bytes, expected %v",
106 len(omci.Payload), MaxTestRequestLength)
107 return errors.New(msg)
108 }
109 bytes, err := b.AppendBytes(len(omci.Payload))
110 if err != nil {
111 return err
112 }
113
114 copy(bytes, omci.Payload)
115 return nil
116}
117
118type OpticalLineSupervisionTestRequest struct {
119 MeBasePacket
120 SelectTest uint8 // Bitfield
121 GeneralPurposeBuffer uint16 // Pointer to General Purpose Buffer ME
122 VendorSpecificParameters uint16 // Pointer to Octet String ME
123}
124
125func (omci *OpticalLineSupervisionTestRequest) String() string {
126 return fmt.Sprintf("Optical Line Supervision Test Result: SelectTest: %#x, Buffer: %#x, Params: %#x",
127 omci.SelectTest, omci.GeneralPurposeBuffer, omci.VendorSpecificParameters)
128}
129
130// LayerType returns LayerTypeTestRequest
131func (omci *OpticalLineSupervisionTestRequest) LayerType() gopacket.LayerType {
132 return LayerTypeTestRequest
133}
134
135// CanDecode returns the set of layer types that this DecodingLayer can decode
136func (omci *OpticalLineSupervisionTestRequest) CanDecode() gopacket.LayerClass {
137 return LayerTypeTestRequest
138}
139
140// NextLayerType returns the layer type contained by this DecodingLayer.
141func (omci *OpticalLineSupervisionTestRequest) NextLayerType() gopacket.LayerType {
142 return gopacket.LayerTypePayload
143}
144
145func (omci *OpticalLineSupervisionTestRequest) TestRequest() []byte {
146 return omci.Payload
147}
148
149// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
150func (omci *OpticalLineSupervisionTestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
151 // Common ClassID/EntityID decode in msgBase
152 err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+5)
153 if err != nil {
154 return err
155 }
156
157 omci.SelectTest = data[4]
158 omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[5:])
159 omci.VendorSpecificParameters = binary.BigEndian.Uint16(data[7:])
160 return nil
161}
162
163// SerializeTo provides serialization of an Test Result notification message
164func (omci *OpticalLineSupervisionTestRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
165 // Basic (common) OMCI Header is 8 octets, 10
166 err := omci.MeBasePacket.SerializeTo(b)
167 if err != nil {
168 return err
169 }
170
171 bytes, err := b.AppendBytes(8)
172 if err != nil {
173 return err
174 }
175
176 bytes[0] = omci.SelectTest
177 binary.BigEndian.PutUint16(bytes[1:], omci.GeneralPurposeBuffer)
178 binary.BigEndian.PutUint16(bytes[3:], omci.VendorSpecificParameters)
179 return nil
180}
181
182// TestResponse message
183type TestResponse struct {
184 MeBasePacket
185 Result me.Results
186}
187
188func (omci *TestResponse) String() string {
189 return fmt.Sprintf("%v, Results: %d (%v)", omci.MeBasePacket.String(), omci.Result, omci.Result)
190}
191
192// LayerType returns LayerTypeTestResponse
193func (omci *TestResponse) LayerType() gopacket.LayerType {
194 return LayerTypeTestResponse
195}
196
197// CanDecode returns the set of layer types that this DecodingLayer can decode
198func (omci *TestResponse) CanDecode() gopacket.LayerClass {
199 return LayerTypeTestResponse
200}
201
202// NextLayerType returns the layer type contained by this DecodingLayer.
203func (omci *TestResponse) NextLayerType() gopacket.LayerType {
204 return gopacket.LayerTypePayload
205}
206
207// DecodeFromBytes decodes the given bytes of a Test Response into this layer
208func (omci *TestResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
209 // Common ClassID/EntityID decode in msgBase
210 err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
211 if err != nil {
212 return err
213 }
214 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
215 me.ParamData{EntityID: omci.EntityInstance})
216 if omciErr.StatusCode() != me.Success {
217 return omciErr.GetError()
218 }
219
220 // ME needs to support Test requests
221 if !me.SupportsMsgType(meDefinition, me.Test) {
222 return me.NewProcessingError("managed entity does not support Test Message-Type")
223 }
224 omci.Result = me.Results(data[4])
225 return nil
226}
227
228func decodeTestResponse(data []byte, p gopacket.PacketBuilder) error {
229 omci := &TestResponse{}
230 omci.MsgLayerType = LayerTypeTestResponse
231 return decodingLayerDecoder(omci, data, p)
232}
233
234// SerializeTo provides serialization of an Test Response message
235func (omci *TestResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
236 // Basic (common) OMCI Header is 8 octets, 10
237 err := omci.MeBasePacket.SerializeTo(b)
238 if err != nil {
239 return err
240 }
241 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
242 me.ParamData{EntityID: omci.EntityInstance})
243 if omciErr.StatusCode() != me.Success {
244 return omciErr.GetError()
245 }
246 // ME needs to support Set
247 if !me.SupportsMsgType(entity, me.Test) {
248 return me.NewProcessingError("managed entity does not support the Test Message-Type")
249 }
250 bytes, err := b.AppendBytes(1)
251 if err != nil {
252 return err
253 }
254 bytes[0] = byte(omci.Result)
255
256 if omci.Result > me.DeviceBusy {
257 msg := fmt.Sprintf("invalid results code: %v, must be 0..6", omci.Result)
258 return errors.New(msg)
259 }
260 return nil
261}
262
263func decodeTestResult(data []byte, p gopacket.PacketBuilder) error {
264 // Peek at Managed Entity Type
265 if len(data) < 8 {
266 p.SetTruncated()
267 return errors.New("frame too small")
268 }
269 classID := binary.BigEndian.Uint16(data)
270
271 // Is it a Managed Entity class we support customized decode of?
272 switch me.ClassID(classID) {
273 default:
274 omci := &TestResultNotification{}
275 omci.MsgLayerType = LayerTypeTestResult
276 return decodingLayerDecoder(omci, data, p)
277
278 case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
279 me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
280 omci := &OpticalLineSupervisionTestResult{}
281 omci.MsgLayerType = LayerTypeTestResult
282 return decodingLayerDecoder(omci, data, p)
283 }
284}
285
286func decodeTestResultExtended(data []byte, p gopacket.PacketBuilder) error {
287 // Peek at Managed Entity Type
288 if len(data) < 8 {
289 p.SetTruncated()
290 return errors.New("frame too small")
291 }
292 classID := binary.BigEndian.Uint16(data)
293
294 // Is it a Managed Entity class we support customized decode of?
295 switch me.ClassID(classID) {
296 default:
297 omci := &TestResultNotification{}
298 omci.MsgLayerType = LayerTypeTestResult
299 omci.Extended = true
300 return decodingLayerDecoder(omci, data, p)
301
302 case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
303 me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
304 omci := &OpticalLineSupervisionTestResult{}
305 omci.MsgLayerType = LayerTypeTestResult
306 omci.Extended = true
307 return decodingLayerDecoder(omci, data, p)
308 }
309}
310
311type TestResultNotification struct {
312 MeBasePacket
313 Payload []byte
314}
315
316func (omci *TestResultNotification) TestResults() []byte {
317 return omci.Payload
318}
319
320func (omci *TestResultNotification) String() string {
321 return fmt.Sprintf("%v, Payload: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
322}
323
324// LayerType returns LayerTypeTestResult
325func (omci *TestResultNotification) LayerType() gopacket.LayerType {
326 return LayerTypeTestResult
327}
328
329// CanDecode returns the set of layer types that this DecodingLayer can decode
330func (omci *TestResultNotification) CanDecode() gopacket.LayerClass {
331 return LayerTypeTestResult
332}
333
334// NextLayerType returns the layer type contained by this DecodingLayer.
335func (omci *TestResultNotification) NextLayerType() gopacket.LayerType {
336 return gopacket.LayerTypePayload
337}
338
339// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
340func (omci *TestResultNotification) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
341 // Common ClassID/EntityID decode in msgBase
342 payloadOffset := 4
343 if omci.Extended {
344 payloadOffset = 6
345 }
346 err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset)
347 if err != nil {
348 return err
349 }
350
351 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
352 me.ParamData{EntityID: omci.EntityInstance})
353 if omciErr.StatusCode() != me.Success {
354 return omciErr.GetError()
355 }
356
357 // ME needs to support Test requests
358 if !me.SupportsMsgType(meDefinition, me.Test) {
359 return me.NewProcessingError("managed entity does not support Test Message-Type")
360 }
361 if omci.Extended {
362 if len(data) < 6 {
363 p.SetTruncated()
364 return errors.New("frame too small")
365 }
366 length := binary.BigEndian.Uint16(data[4:])
367 if len(data) < 6+int(length) {
368 p.SetTruncated()
369 return errors.New("frame too small")
370 }
371 omci.Payload = make([]byte, length)
372 copy(omci.Payload, data[6:])
373 } else {
374 omci.Payload = make([]byte, MaxTestResultsLength)
375 copy(omci.Payload, omci.MeBasePacket.Payload)
376 }
377 return nil
378}
379
380// SerializeTo provides serialization of an Test Result notification message
381func (omci *TestResultNotification) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
382 // Basic (common) OMCI Header is 8 octets
383 err := omci.MeBasePacket.SerializeTo(b)
384 if err != nil {
385 return err
386 }
387
388 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
389 me.ParamData{EntityID: omci.EntityInstance})
390 if omciErr.StatusCode() != me.Success {
391 return omciErr.GetError()
392 }
393
394 // ME needs to support Test requests
395 if !me.SupportsMsgType(meDefinition, me.Test) {
396 return me.NewProcessingError("managed entity does not support Test Message-Type")
397 }
398 if omci.Payload == nil {
399 return errors.New("test results payload is missing")
400 }
401
402 payloadOffset := 0
403 maxSize := MaxTestResultsLength
404
405 if omci.Extended {
406 payloadOffset = 2
407 maxSize = MaxExtendedLength - 10 - 4
408 }
409 if len(omci.Payload) > maxSize {
410 msg := fmt.Sprintf("Invalid Test Results payload size. Received %v bytes, max expected %v",
411 len(omci.Payload), maxSize)
412 return errors.New(msg)
413 }
414 bytes, err := b.AppendBytes(len(omci.Payload) + payloadOffset)
415 if err != nil {
416 return err
417 }
418 if omci.Extended {
419 binary.BigEndian.PutUint16(bytes, uint16(len(omci.Payload)))
420 }
421 copy(bytes[payloadOffset:], omci.Payload)
422 return nil
423}
424
425// OpticalLineSupervisionTestResult provides a Optical Specific test results
426// message decode for the associated Managed Entities
427type OpticalLineSupervisionTestResult struct {
428 MeBasePacket
429 PowerFeedVoltageType uint8 // Type = 1
430 PowerFeedVoltage uint16 // value
431 ReceivedOpticalPowerType uint8 // Type = 3
432 ReceivedOpticalPower uint16 // value
433 MeanOpticalLaunchType uint8 // Type = 5
434 MeanOpticalLaunch uint16 // value
435 LaserBiasCurrentType uint8 // Type = 9
436 LaserBiasCurrent uint16 // value
437 TemperatureType uint8 // Type = 12
438 Temperature uint16 // value
439
440 GeneralPurposeBuffer uint16 // Pointer to General Purpose Buffer ME
441}
442
443func (omci *OpticalLineSupervisionTestResult) String() string {
444 return fmt.Sprintf("Optical Line Supervision Test Result")
445}
446
447// LayerType returns LayerTypeTestResult
448func (omci *OpticalLineSupervisionTestResult) LayerType() gopacket.LayerType {
449 return LayerTypeTestResult
450}
451
452// CanDecode returns the set of layer types that this DecodingLayer can decode
453func (omci *OpticalLineSupervisionTestResult) CanDecode() gopacket.LayerClass {
454 return LayerTypeTestResult
455}
456
457// NextLayerType returns the layer type contained by this DecodingLayer.
458func (omci *OpticalLineSupervisionTestResult) NextLayerType() gopacket.LayerType {
459 return gopacket.LayerTypePayload
460}
461
462func (omci *OpticalLineSupervisionTestResult) TestResults() []byte {
463 return omci.MeBasePacket.Payload
464}
465
466// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
467func (omci *OpticalLineSupervisionTestResult) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
468 // Common ClassID/EntityID decode in msgBase
469 payloadOffset := 4
470 if omci.Extended {
471 payloadOffset = 6
472 }
473 err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset+17)
474 if err != nil {
475 return err
476 }
477
478 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
479 me.ParamData{EntityID: omci.EntityInstance})
480 if omciErr.StatusCode() != me.Success {
481 return omciErr.GetError()
482 }
483
484 // ME needs to support Test requests
485 if !me.SupportsMsgType(meDefinition, me.Test) {
486 return me.NewProcessingError("managed entity does not support Test Message-Type")
487 }
488 // Note: Unsupported tests will have a type = 0 and the value should be zero
489 // as well, but that constraint is not enforced at this time.
490 // Type = 1
491 omci.PowerFeedVoltageType = data[payloadOffset]
492 omci.PowerFeedVoltage = binary.BigEndian.Uint16(data[payloadOffset+1:])
493
494 // Type = 3
495 omci.ReceivedOpticalPowerType = data[payloadOffset+3]
496 omci.ReceivedOpticalPower = binary.BigEndian.Uint16(data[payloadOffset+4:])
497
498 // Type = 5
499 omci.MeanOpticalLaunchType = data[payloadOffset+6]
500 omci.MeanOpticalLaunch = binary.BigEndian.Uint16(data[payloadOffset+7:])
501
502 // Type = 9
503 omci.LaserBiasCurrentType = data[payloadOffset+9]
504 omci.LaserBiasCurrent = binary.BigEndian.Uint16(data[payloadOffset+10:])
505
506 // Type = 12
507 omci.TemperatureType = data[payloadOffset+12]
508 omci.Temperature = binary.BigEndian.Uint16(data[payloadOffset+13:])
509
510 omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[payloadOffset+15:])
511 return nil
512}
513
514// SerializeTo provides serialization of an Test Result notification message
515func (omci *OpticalLineSupervisionTestResult) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
516 // Basic (common) OMCI Header is 8 octets, 10
517 err := omci.MeBasePacket.SerializeTo(b)
518 if err != nil {
519 return err
520 }
521 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
522 me.ParamData{EntityID: omci.EntityInstance})
523 if omciErr.StatusCode() != me.Success {
524 return omciErr.GetError()
525 }
526
527 // ME needs to support Test requests
528 if !me.SupportsMsgType(meDefinition, me.Test) {
529 return me.NewProcessingError("managed entity does not support Test Message-Type")
530 }
531 payloadOffset := 0
532
533 if omci.Extended {
534 payloadOffset = 2
535 }
536 bytes, err := b.AppendBytes(payloadOffset + 17)
537 if err != nil {
538 return err
539 }
540
541 if omci.Extended {
542 binary.BigEndian.PutUint16(bytes, 17)
543 }
544 bytes[payloadOffset] = omci.PowerFeedVoltageType
545 binary.BigEndian.PutUint16(bytes[payloadOffset+1:], omci.PowerFeedVoltage)
546 bytes[payloadOffset+3] = omci.ReceivedOpticalPowerType
547 binary.BigEndian.PutUint16(bytes[payloadOffset+4:], omci.ReceivedOpticalPower)
548 bytes[payloadOffset+6] = omci.MeanOpticalLaunchType
549 binary.BigEndian.PutUint16(bytes[payloadOffset+7:], omci.MeanOpticalLaunch)
550 bytes[payloadOffset+9] = omci.LaserBiasCurrentType
551 binary.BigEndian.PutUint16(bytes[payloadOffset+10:], omci.LaserBiasCurrent)
552 bytes[payloadOffset+12] = omci.TemperatureType
553 binary.BigEndian.PutUint16(bytes[payloadOffset+13:], omci.Temperature)
554 binary.BigEndian.PutUint16(bytes[payloadOffset+15:], omci.GeneralPurposeBuffer)
555 return nil
556}