blob: 6d7a9f816c5a53a9e4ef42fcfde3ece3bfafca8a [file] [log] [blame]
Takahiro Suzukid7bf8202020-12-17 20:21:59 +09001/*
2 * Copyright 2020-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 l2oam
18
19import (
20 "encoding/binary"
21 "encoding/hex"
22 "fmt"
23
24 "github.com/google/gopacket"
25 "github.com/google/gopacket/layers"
26)
27
28// OampduTlvTypeLocalInfo means that TLV type is "Local Information"
29var OampduTlvTypeLocalInfo uint8 = 0x01
30
31// OampduTlvTypeRemoteInfo means that TLV type is "Remote Information"
32var OampduTlvTypeRemoteInfo uint8 = 0x02
33
34// OampduTlvTypeOrganizationSpecificInfo means that TLV type is "Organization Specific Information"
35var OampduTlvTypeOrganizationSpecificInfo uint8 = 0xfe
36
37// GeneateKeepAlive1 generates "OAMPDU Information(first)"
38func GeneateKeepAlive1(isOnuPkgA bool) gopacket.SerializableLayer {
39 var osiLength uint8
40 var osiValue []byte
41 if isOnuPkgA {
42 osiLength = 7
43 osiValue = []byte{0x00, 0x10, 0x00, 0x00, 0x23}
44 } else {
45 osiLength = 8
46 osiValue = []byte{0x90, 0x82, 0x60, 0x02, 0x01, 0x01}
47 }
48 tibitData := &OAMPDUInformation{
49 // IEEE 1904.2
50 Opcode: 0x03,
51 // OAM Protocol
52 Flags: 0x0008,
53 Code: 0x00,
54 // Local Information TLV
55 LIType: OampduTlvTypeLocalInfo,
56 LILength: 16,
57 LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
58 // Organization Specific Information TLV
59 OSIType: OampduTlvTypeOrganizationSpecificInfo,
60 OSILength: osiLength,
61 OSIValue: osiValue,
62 }
63
64 return tibitData
65}
66
67// GeneateKeepAlive2 generates "OAMPDU Information(second)"
68func GeneateKeepAlive2(riValue []byte, isOnuPkgA bool) gopacket.SerializableLayer {
69 var osiLength uint8
70 var osiValue []byte
71 if isOnuPkgA {
72 osiLength = 7
73 osiValue = []byte{0x00, 0x10, 0x00, 0x00, 0x23}
74 } else {
75 osiLength = 8
76 osiValue = []byte{0x90, 0x82, 0x60, 0x02, 0x01, 0x01}
77 }
78 tibitData := &OAMPDUInformation{
79 // IEEE 1904.2
80 Opcode: 0x03,
81 // OAM Protocol
82 Flags: 0x0030,
83 Code: 0x00,
84 // Local Information TLV
85 LIType: OampduTlvTypeLocalInfo,
86 LILength: 16,
87 LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
88 // Remote Information TLV
89 RIType: OampduTlvTypeRemoteInfo,
90 RILength: 16,
91 RIValue: riValue,
92 // Organization Specific Information TLV
93 OSIType: OampduTlvTypeOrganizationSpecificInfo,
94 OSILength: osiLength,
95 OSIValue: osiValue,
96 }
97
98 return tibitData
99
100}
101
102// GeneateKeepAlive3 generates "OAMPDU Information(third)"
103func GeneateKeepAlive3(riValue []byte) gopacket.SerializableLayer {
104 tibitData := &OAMPDUInformation{
105 // IEEE 1904.2
106 Opcode: 0x03,
107 // OAM Protocol
108 Flags: 0x0050,
109 Code: 0x00,
110 // Local Information TLV
111 LIType: OampduTlvTypeLocalInfo,
112 LILength: 16,
113 LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
114 // Remote Information TLV
115 RIType: OampduTlvTypeRemoteInfo,
116 RILength: 16,
117 RIValue: riValue,
118 }
119
120 return tibitData
121
122}
123
124// OAMPDUInformation is a structure for "OAMPDU Information" message
125type OAMPDUInformation struct {
126 layers.BaseLayer
127 Opcode uint8
128 Flags uint16
129 Code uint8
130 LIType uint8
131 LILength uint8
132 LIValue []byte
133 RIType uint8
134 RILength uint8
135 RIValue []byte
136 OSIType uint8
137 OSILength uint8
138 OSIValue []byte
139}
140
141// String returns the string expression of OAMPDUInformation
142func (d *OAMPDUInformation) String() string {
143 message := fmt.Sprintf("Opcode:%v, Flags:%v, Code:%v", d.Opcode, d.Flags, d.Code)
144 message = fmt.Sprintf("%s, LIType:%v, LILength:%v, LIValue:%v", message, d.LIType, d.LILength, hex.EncodeToString(d.LIValue))
145 message = fmt.Sprintf("%s, RIType:%v, RILength:%v, RIValue:%v", message, d.RIType, d.RILength, hex.EncodeToString(d.RIValue))
146 message = fmt.Sprintf("%s, OSIType:%v, OSILength:%v, OSIValue:%v", message, d.OSIType, d.OSILength, hex.EncodeToString(d.OSIValue))
147 return message
148}
149
150// Len returns the length of OAMPDUInformation
151func (d *OAMPDUInformation) Len() int {
152 len := (1) + (3) + int(d.LILength) + int(d.RILength) + int(d.OSILength)
153 return len
154}
155
156// LayerType returns the ethernet type of OAMPDUInformation
157func (d *OAMPDUInformation) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
158
159// SerializeTo serializes a data structure to byte arrays
160func (d *OAMPDUInformation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
161 plen := int(d.Len())
162 data, err := b.PrependBytes(plen)
163 if err != nil {
164 return err
165 }
166
167 i := 0
168 data[i] = byte(d.Opcode)
169 i++
170 binary.BigEndian.PutUint16(data[i:i+2], d.Flags)
171 i = i + 2
172 data[i] = byte(d.Code)
173 i++
174
175 if d.LILength != 0 {
176 data[i] = byte(d.LIType)
177 data[i+1] = byte(d.LILength)
178 copy(data[i+2:i+int(d.LILength)], d.LIValue)
179 i = i + int(d.LILength)
180 }
181
182 if d.RILength != 0 {
183 data[i] = byte(d.RIType)
184 data[i+1] = byte(d.RILength)
185 copy(data[i+2:i+int(d.RILength)], d.RIValue)
186 i = i + int(d.RILength)
187 }
188
189 if d.OSILength != 0 {
190 data[i] = byte(d.OSIType)
191 data[i+1] = byte(d.OSILength)
192 copy(data[i+2:i+int(d.OSILength)], d.OSIValue)
193 //i = i + int(d.OSILength)
194 }
195
196 return nil
197}
198
199// Decode decodes byte arrays to a data structure
200func (d *OAMPDUInformation) Decode(data []byte) error {
201 i := 0
202 d.Opcode = data[i]
203 i++
204
205 d.Flags = binary.BigEndian.Uint16(data[i : i+2])
206 i = i + 2
207 d.Code = data[i]
208 i++
209
210 for {
211 if len(data) <= i {
212 break
213 }
214 tlvType := data[i]
215 tlvLength := data[i+1]
216 if tlvLength == 0 {
217 break
218 }
219 tlvValue := data[i+2 : i+int(tlvLength)]
220 i = i + int(tlvLength)
221
222 switch tlvType {
223 case OampduTlvTypeLocalInfo:
224 d.LIType = tlvType
225 d.LILength = tlvLength
226 d.LIValue = tlvValue
227 case OampduTlvTypeRemoteInfo:
228 d.RIType = tlvType
229 d.RILength = tlvLength
230 d.RIValue = tlvValue
231 case OampduTlvTypeOrganizationSpecificInfo:
232 d.OSIType = tlvType
233 d.OSILength = tlvLength
234 d.OSIValue = tlvValue
235 default:
236 return fmt.Errorf("tlvType Error: %v", tlvType)
237 }
238 }
239
240 return nil
241}
242
243// IsOnuPkgA returns true if message type of OAMPDUInformation is PkgA
244func (d *OAMPDUInformation) IsOnuPkgA() bool {
245 if d.OSILength == 0 {
246 // return true if OSILength is 0, this means the message is KeepAlive3
247 return true
248 } else if d.OSILength == 7 {
249 return (d.OSIValue[0] == 0x00 && d.OSIValue[1] == 0x10 && d.OSIValue[2] == 0x00)
250 }
251 return false
252}
253
254// IsOnuPkgB returns true if message type of OAMPDUInformation is PkgA
255func (d *OAMPDUInformation) IsOnuPkgB() bool {
256 if d.OSILength == 0 {
257 // return true if OSILength is 0, this means the message is KeepAlive3
258 return true
259 } else if d.OSILength == 7 {
260 return (d.OSIValue[0] == 0x90 && d.OSIValue[1] == 0x82 && d.OSIValue[2] == 0x60)
261 }
262 return false
263}