blob: 403efa4db229f4f60e7f65383656b86f9adbf5e7 [file] [log] [blame]
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package omci
18
19import (
20 "encoding/hex"
21 "github.com/cboling/omci"
22 me "github.com/cboling/omci/generated"
23 "github.com/google/gopacket"
24 omcisim "github.com/opencord/omci-sim"
25 log "github.com/sirupsen/logrus"
26)
27
28var omciLogger = log.WithFields(log.Fields{
29 "module": "OMCI",
30})
31
32const galEthernetEID = uint16(1)
33const maxGemPayloadSize = uint16(48)
34const gemEID = uint16(1)
35
36type txFrameCreator func() ([]byte, error)
37type rxFrameParser func(gopacket.Packet) error
38
39type ServiceStep struct {
40 MakeTxFrame txFrameCreator
41 RxHandler rxFrameParser
42}
43
44func serialize(msgType omci.MessageType, request gopacket.SerializableLayer, tid uint16) ([]byte, error) {
45 omciLayer := &omci.OMCI{
46 TransactionID: tid,
47 MessageType: msgType,
48 }
49 var options gopacket.SerializeOptions
50 options.FixLengths = true
51
52 buffer := gopacket.NewSerializeBuffer()
53 err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
54 if err != nil {
55 return nil, err
56 }
57 return buffer.Bytes(), nil
58}
59
60func hexEncode(omciPkt []byte) ([]byte, error) {
61 dst := make([]byte, hex.EncodedLen(len(omciPkt)))
62 hex.Encode(dst, omciPkt)
63 return dst, nil
64}
65
66func DecodeOmci(payload []byte) (omci.MessageType, gopacket.Packet) {
67 // Perform base OMCI decode (common to all requests)
68 packet := gopacket.NewPacket(payload, omci.LayerTypeOMCI, gopacket.NoCopy)
69
70 if omciLayer := packet.Layer(omci.LayerTypeOMCI); omciLayer != nil {
71
72 omciObj, omciOk := omciLayer.(*omci.OMCI)
73 if !omciOk {
74 panic("Not Expected") // TODO: Do something better or delete...
75 }
76 if byte(omciObj.MessageType) & ^me.AK == 0 {
77 // Not a response, silently discard
78 return 0, nil
79 }
80 return omciObj.MessageType, packet
81 }
82
83 // FIXME
84 // if we can't properly decode the packet, try using shad helper method
85 // most likely this won't be necessary once we move omci-sim to use cboling/omci
86 // to generate packets
87 _, _, msgType, _, _, _, err := omcisim.ParsePkt(payload)
88 if err != nil {
89 return 0, nil
90 }
91 if msgType == omcisim.MibReset {
92 return omci.MibResetResponseType, nil
93 }
94 if msgType == omcisim.MibUpload {
95 return omci.MibUploadResponseType, nil
96 }
97 if msgType == omcisim.MibUploadNext {
98 return omci.MibUploadNextResponseType, nil
99 }
100 if msgType == omcisim.Create {
101 return omci.CreateResponseType, nil
102 }
103 if msgType == omcisim.Set {
104 return omci.SetResponseType, nil
105 }
106
107 omciLogger.Warnf("omci-sim returns msgType: %d", msgType)
108
109 return 0, nil
110}
111
112func CreateMibResetRequest(tid uint16) ([]byte, error) {
113
114 request := &omci.MibResetRequest{
115 MeBasePacket: omci.MeBasePacket{
116 EntityClass: me.OnuDataClassId,
117 },
118 }
119 pkt, err := serialize(omci.MibResetRequestType, request, tid)
120 if err != nil {
121 omciLogger.WithFields(log.Fields{
122 "Err": err,
123 }).Fatalf("Cannot serialize MibResetRequest")
124 return nil, err
125 }
126 return hexEncode(pkt)
127}
128
129func CreateMibUploadRequest(tid uint16) ([]byte, error) {
130 request := &omci.MibUploadRequest{
131 MeBasePacket: omci.MeBasePacket{
132 EntityClass: me.OnuDataClassId,
133 // Default Instance ID is 0
134 },
135 }
136 pkt, err := serialize(omci.MibUploadRequestType, request, tid)
137 if err != nil {
138 omciLogger.WithFields(log.Fields{
139 "Err": err,
140 }).Fatalf("Cannot serialize MibUploadRequest")
141 return nil, err
142 }
143 return hexEncode(pkt)
144}
145
146func CreateMibUploadNextRequest(tid uint16, seqNumber uint16) ([]byte, error) {
147
148 request := &omci.MibUploadNextRequest{
149 MeBasePacket: omci.MeBasePacket{
150 EntityClass: me.OnuDataClassId,
151 // Default Instance ID is 0
152 },
153 CommandSequenceNumber: seqNumber,
154 }
155 pkt, err := serialize(omci.MibUploadNextRequestType, request, tid)
156
157 if err != nil {
158 omciLogger.WithFields(log.Fields{
159 "Err": err,
160 }).Fatalf("Cannot serialize MibUploadNextRequest")
161 return nil, err
162 }
163 return hexEncode(pkt)
164}
165
Scott Bakerb90c4312020-03-12 21:33:25 -0700166// Return true if msg is an Omci Test Request
167func IsTestRequest(payload []byte) (bool, error) {
168 _, _, msgType, _, _, _, err := omcisim.ParsePkt(payload)
169 if err != nil {
170 return false, err
171 }
172
173 return ((msgType & 0x1F) == 18), nil
174}
175
176func BuildTestResult(payload []byte) ([]byte, error) {
177 transactionId, deviceId, _, class, instance, _, err := omcisim.ParsePkt(payload)
178
179 if err != nil {
180 return []byte{}, err
181 }
182
183 resp := make([]byte, 26)
184 resp[0] = byte(transactionId >> 8)
185 resp[1] = byte(transactionId & 0xFF)
186 resp[2] = 27 // Upper nibble 0x0 is fixed (0000), Lower nibbles defines msg type (TestResult=27)
187 resp[3] = deviceId
188 resp[4] = byte(class >> 8)
189 resp[5] = byte(class & 0xFF)
190 resp[6] = byte(instance >> 8)
191 resp[7] = byte(instance & 0xFF)
192 resp[8] = 0 // high byte of contents length
193 resp[9] = 17 // low byte of contents length
194 // Each of these is a 1-byte code
195 // follow by a 2-byte (high, low) value
196 resp[10] = 1 // power feed voltage
197 resp[11] = 0
198 resp[12] = 123 // feed voltage 123 mV, 20 mv res --> 6mv
199 resp[13] = 3 // received optical power
200 resp[14] = 1
201 resp[15] = 200 // 456 decibel-microwatts, 0.002 dB res --> 0.912 db-mw
202 resp[16] = 5 // mean optical launch power
203 resp[17] = 3
204 resp[18] = 21 // 789 uA, 2uA res --> 394uA
205 resp[19] = 9 // laser bias current
206 resp[20] = 38
207 resp[21] = 148 // 9876 deg C, 1/256 resolution --> 38.57 Deg C
208 resp[22] = 12 // temperature
209
210 return resp, nil
211}
212
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700213// TODO understand and refactor
214
215func CreateGalEnetRequest(tid uint16) ([]byte, error) {
216 params := me.ParamData{
217 EntityID: galEthernetEID,
218 Attributes: me.AttributeValueMap{"MaximumGemPayloadSize": maxGemPayloadSize},
219 }
220 meDef, _ := me.NewGalEthernetProfile(params)
221 pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
222 if err != nil {
223 omciLogger.WithField("err", err).Fatalf("Can't generate GalEnetRequest")
224 }
225 return hexEncode(pkt)
226}
227
228func CreateEnableUniRequest(tid uint16, uniId uint16, enabled bool, isPtp bool) ([]byte, error) {
229
230 var _enabled uint8
231 if enabled {
232 _enabled = uint8(1)
233 } else {
234 _enabled = uint8(0)
235 }
236
237 data := me.ParamData{
238 EntityID: uniId,
239 Attributes: me.AttributeValueMap{
240 "AdministrativeState": _enabled,
241 },
242 }
243 var medef *me.ManagedEntity
244 var omciErr me.OmciErrors
245
246 if isPtp {
247 medef, omciErr = me.NewPhysicalPathTerminationPointEthernetUni(data)
248 } else {
249 medef, omciErr = me.NewVirtualEthernetInterfacePoint(data)
250 }
251 if omciErr != nil {
252 return nil, omciErr.GetError()
253 }
254 pkt, err := omci.GenFrame(medef, omci.SetRequestType, omci.TransactionID(tid))
255 if err != nil {
256 omciLogger.WithField("err", err).Fatalf("Can't generate EnableUniRequest")
257 }
258 return hexEncode(pkt)
259}
260
261func CreateGemPortRequest(tid uint16) ([]byte, error) {
262 params := me.ParamData{
263 EntityID: gemEID,
264 Attributes: me.AttributeValueMap{
265 "PortId": 1,
266 "TContPointer": 1,
267 "Direction": 0,
268 "TrafficManagementPointerForUpstream": 0,
269 "TrafficDescriptorProfilePointerForUpstream": 0,
270 "UniCounter": 0,
271 "PriorityQueuePointerForDownStream": 0,
272 "EncryptionState": 0,
273 "TrafficDescriptorProfilePointerForDownstream": 0,
274 "EncryptionKeyRing": 0,
275 },
276 }
277 meDef, _ := me.NewGemPortNetworkCtp(params)
278 pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
279 if err != nil {
280 omciLogger.WithField("err", err).Fatalf("Can't generate GemPortRequest")
281 }
282 return hexEncode(pkt)
283}
284
285// END TODO