blob: ab104bc3431c3a6cbee801a83db155d0804bfc3a [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// GenerateDiscoverySOLICIT generates "Discovery: SOLICIT" message
29func GenerateDiscoverySOLICIT() gopacket.SerializableLayer {
30
31 tibitData := &DiscoverySolicit{
32 // IEEE 1904.2
33 Opcode: 0xfd,
34 DiscoveryType: 0x01,
35 // Vendor-specific
36 VendorType: 0xfe,
37 Length: 37,
38 // Vendor ID
39 VendorIDType: 0xfd,
40 VendorIDLength: 3,
41 VendorID: []byte{0x2a, 0xea, 0x15},
42 // Controller Priority
43 CPType: 0x05,
44 CPLength: 1,
45 CPValue: []byte{128},
46 //NetworkID
47 NWType: 0x06,
48 NWLength: 16,
49 NWValue: []byte("tibitcom.com"),
50 //Device Type
51 DVType: 0x07,
52 DVLength: 1,
53 DVValue: []byte{1},
54 //Supported CLient Protocols
55 SCPType: 0x08,
56 SCPLength: 1,
57 SCPValue: []byte{0x03},
58 //Padding
59 PadType: 0xff,
60 PadLength: 1,
61 PadValue: []byte{0},
62 }
63
64 return tibitData
65}
66
67// DiscoverySolicit is a structure for Discovery message
68type DiscoverySolicit struct {
69 layers.BaseLayer
70 Opcode uint8
71 DiscoveryType uint8
72 VendorType uint8
73 Length uint16 // length of after this data without Padding
74 VendorIDType uint8
75 VendorIDLength uint16
76 VendorID []byte
77 CPType uint8
78 CPLength uint16
79 CPValue []byte
80 NWType uint8
81 NWLength uint16
82 NWValue []byte
83 DVType uint8
84 DVLength uint16
85 DVValue []byte
86 SCPType uint8
87 SCPLength uint16
88 SCPValue []byte
89 PadType uint8
90 PadLength uint16
91 PadValue []byte
92}
93
94// String returns the string expression of DiscoverySolicit
95func (d *DiscoverySolicit) String() string {
96 message := fmt.Sprintf("Opcode:%v, DiscoveryType:%v, VendorType:%v, Length:%v", d.Opcode, d.DiscoveryType, d.VendorType, d.Length)
97 message = fmt.Sprintf("%s, VendorIDType:%v, VendorIDLength:%v, VendorID:%v", message, d.VendorIDType, d.VendorIDLength, hex.EncodeToString(d.VendorID))
98 message = fmt.Sprintf("%s, CPType:%v, CPLength:%v, CPValue:%v", message, d.CPType, d.CPLength, hex.EncodeToString(d.CPValue))
99 message = fmt.Sprintf("%s, NWType:%v, NWLength:%v, NWValue:%v", message, d.NWType, d.NWLength, hex.EncodeToString(d.NWValue))
100 message = fmt.Sprintf("%s, DVType:%v, DVLength:%v, DVValue:%v", message, d.DVType, d.DVLength, hex.EncodeToString(d.DVValue))
101 message = fmt.Sprintf("%s, SCPType:%v, SCPLength:%v, SCPValue:%v", message, d.SCPType, d.SCPLength, hex.EncodeToString(d.SCPValue))
102 return message
103}
104
105// Len returns the length of DiscoverySolicit
106func (d *DiscoverySolicit) Len() int {
107 len := (2) + (3) + int(d.Length) + (int(d.PadLength) + 3)
108 return len
109}
110
111// LayerType returns the ethernet type of DiscoverySolicit
112func (d *DiscoverySolicit) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
113
114// SerializeTo serializes a data structure to byte arrays
115func (d *DiscoverySolicit) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
116 plen := int(d.Len())
117 data, err := b.PrependBytes(plen)
118 if err != nil {
119 return err
120 }
121
122 i := 0
123 data[i] = byte(d.Opcode)
124 i++
125 data[i] = byte(d.DiscoveryType)
126 i++
127 data[i] = byte(d.VendorType)
128 i++
129 binary.BigEndian.PutUint16(data[i:i+2], d.Length)
130 i = i + 2
131
132 data[i] = byte(d.VendorIDType)
133 i++
134 binary.BigEndian.PutUint16(data[i:i+2], d.VendorIDLength)
135 i = i + 2
136 copy(data[i:i+int(d.VendorIDLength)], d.VendorID)
137 i = i + int(d.VendorIDLength)
138
139 data[i] = byte(d.CPType)
140 i++
141 binary.BigEndian.PutUint16(data[i:i+2], d.CPLength)
142 i = i + 2
143 copy(data[i:i+int(d.CPLength)], d.CPValue)
144 i = i + int(d.CPLength)
145
146 data[i] = byte(d.NWType)
147 i++
148 binary.BigEndian.PutUint16(data[i:i+2], d.NWLength)
149 i = i + 2
150 copy(data[i:i+int(d.NWLength)], d.NWValue)
151 i = i + int(d.NWLength)
152
153 data[i] = byte(d.DVType)
154 i++
155 binary.BigEndian.PutUint16(data[i:i+2], d.DVLength)
156 i = i + 2
157 copy(data[i:i+int(d.DVLength)], d.DVValue)
158 i = i + int(d.DVLength)
159
160 data[i] = byte(d.SCPType)
161 i++
162 binary.BigEndian.PutUint16(data[i:i+2], d.SCPLength)
163 i = i + 2
164 copy(data[i:i+int(d.SCPLength)], d.SCPValue)
165 i = i + int(d.SCPLength)
166
167 data[i] = byte(d.PadType)
168 i++
169 binary.BigEndian.PutUint16(data[i:i+2], d.PadLength)
170 i = i + 2
171 copy(data[i:i+int(d.PadLength)], d.PadValue)
172
173 return nil
174}
175
176// Decode decodes byte arrays to a data structure
177func (d *DiscoverySolicit) Decode(data []byte) error {
178 i := 0
179 d.Opcode = data[i]
180 i++
181 d.DiscoveryType = data[i]
182 i++
183 d.VendorType = data[i]
184 i++
185 d.Length = binary.BigEndian.Uint16(data[i : i+2])
186 i = i + 2
187
188 d.VendorIDType = data[i]
189 i++
190 d.VendorIDLength = binary.BigEndian.Uint16(data[i : i+2])
191 i = i + 2
192 d.VendorID = data[i : i+int(d.VendorIDLength)]
193 i = i + int(d.VendorIDLength)
194
195 d.CPType = data[i]
196 i++
197 d.CPLength = binary.BigEndian.Uint16(data[i : i+2])
198 i = i + 2
199 d.CPValue = data[i : i+int(d.CPLength)]
200 i = i + int(d.CPLength)
201
202 d.NWType = data[i]
203 i++
204 d.NWLength = binary.BigEndian.Uint16(data[i : i+2])
205 i = i + 2
206 d.NWValue = data[i : i+int(d.NWLength)]
207 i = i + int(d.NWLength)
208
209 d.DVType = data[i]
210 i++
211 d.DVLength = binary.BigEndian.Uint16(data[i : i+2])
212 i = i + 2
213 d.DVValue = data[i : i+int(d.DVLength)]
214 i = i + int(d.DVLength)
215
216 d.SCPType = data[i]
217 i++
218 d.SCPLength = binary.BigEndian.Uint16(data[i : i+2])
219 i = i + 2
220 d.SCPValue = data[i : i+int(d.SCPLength)]
221 i = i + int(d.SCPLength)
222
223 d.PadType = data[i]
224 i++
225 d.PadLength = binary.BigEndian.Uint16(data[i : i+2])
226 i = i + 2
227 d.PadValue = data[i : i+int(d.PadLength)]
228
229 return nil
230}
231
232// DiscoveryHello is a structure for Discovery message
233type DiscoveryHello struct {
234 layers.BaseLayer
235 Opcode uint8
236 DiscoveryType uint8
237 VendorType uint8
238 Length uint16 // length of after this data without Padding
239 VendorIDType uint8
240 VendorIDLength uint16
241 VendorID []byte
242 NWType uint8
243 NWLength uint16
244 NWValue []byte
245 DVType uint8
246 DVLength uint16
247 DVValue []byte
248 SCPType uint8
249 SCPLength uint16
250 SCPValue []byte
251 TunnelType uint8
252 TunnelLength uint16
253 TunnelValue []byte
254 PadType uint8
255 PadLength uint16
256 PadValue []byte
257}
258
259// String returns the string expression of DiscoveryHello
260func (d *DiscoveryHello) String() string {
261 message := fmt.Sprintf("Opcode:%v, DiscoveryType:%v, VendorType:%v, Length:%v", d.Opcode, d.DiscoveryType, d.VendorType, d.Length)
262 message = fmt.Sprintf("%s, VendorIDType:%v, VendorIDLength:%v, VendorID:%v", message, d.VendorIDType, d.VendorIDLength, hex.EncodeToString(d.VendorID))
263 message = fmt.Sprintf("%s, NWType:%v, NWLength:%v, NWValue:%v", message, d.NWType, d.NWLength, hex.EncodeToString(d.NWValue))
264 message = fmt.Sprintf("%s, DVType:%v, DVLength:%v, DVValue:%v", message, d.DVType, d.DVLength, hex.EncodeToString(d.DVValue))
265 message = fmt.Sprintf("%s, SCPType:%v, SCPLength:%v, SCPValue:%v", message, d.SCPType, d.SCPLength, hex.EncodeToString(d.SCPValue))
266 message = fmt.Sprintf("%s, TunnelType:%v, TunnelLength:%v, TunnelValue:%v", message, d.TunnelType, d.TunnelLength, hex.EncodeToString(d.TunnelValue))
267 message = fmt.Sprintf("%s, PadType:%v, PadLength:%v, PadValue:%v", message, d.PadType, d.PadLength, hex.EncodeToString(d.PadValue))
268 return message
269}
270
271// Len returns the length of DiscoveryHello
272func (d *DiscoveryHello) Len() int {
273 len := (2) + (3) + int(d.Length) + (int(d.PadLength) + 3)
274 return len
275}
276
277// LayerType returns the ethernet type of DiscoveryHello
278func (d *DiscoveryHello) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
279
280// SerializeTo serializes a data structure to byte arrays
281func (d *DiscoveryHello) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
282 plen := int(d.Len())
283 data, err := b.PrependBytes(plen)
284 if err != nil {
285 return err
286 }
287
288 i := 0
289 data[i] = byte(d.Opcode)
290 i++
291 data[i] = byte(d.DiscoveryType)
292 i++
293 data[i] = byte(d.VendorType)
294 i++
295 binary.BigEndian.PutUint16(data[i:i+2], d.Length)
296 i = i + 2
297
298 data[i] = byte(d.VendorIDType)
299 i++
300 binary.BigEndian.PutUint16(data[i:i+2], d.VendorIDLength)
301 i = i + 2
302 copy(data[i:i+int(d.VendorIDLength)], d.VendorID)
303 i = i + int(d.VendorIDLength)
304
305 data[i] = byte(d.NWType)
306 i++
307 binary.BigEndian.PutUint16(data[i:i+2], d.NWLength)
308 i = i + 2
309 copy(data[i:i+int(d.NWLength)], d.NWValue)
310 i = i + int(d.NWLength)
311
312 data[i] = byte(d.DVType)
313 i++
314 binary.BigEndian.PutUint16(data[i:i+2], d.DVLength)
315 i = i + 2
316 copy(data[i:i+int(d.DVLength)], d.DVValue)
317 i = i + int(d.DVLength)
318
319 data[i] = byte(d.SCPType)
320 i++
321 binary.BigEndian.PutUint16(data[i:i+2], d.SCPLength)
322 i = i + 2
323 copy(data[i:i+int(d.SCPLength)], d.SCPValue)
324 i = i + int(d.SCPLength)
325
326 data[i] = byte(d.TunnelType)
327 i++
328 binary.BigEndian.PutUint16(data[i:i+2], d.TunnelLength)
329 i = i + 2
330 copy(data[i:i+int(d.TunnelLength)], d.TunnelValue)
331 i = i + int(d.TunnelLength)
332
333 data[i] = byte(d.PadType)
334 i++
335 binary.BigEndian.PutUint16(data[i:i+2], d.PadLength)
336 i = i + 2
337 copy(data[i:i+int(d.PadLength)], d.PadValue)
338
339 return nil
340}
341
342// Decode decodes byte arrays to a data structure
343func (d *DiscoveryHello) Decode(data []byte) error {
344 i := 0
345 d.Opcode = data[i]
346 i++
347 d.DiscoveryType = data[i]
348 i++
349 d.VendorType = data[i]
350 i++
351 d.Length = binary.BigEndian.Uint16(data[i : i+2])
352 i = i + 2
353
354 d.VendorIDType = data[i]
355 i++
356 d.VendorIDLength = binary.BigEndian.Uint16(data[i : i+2])
357 i = i + 2
358 d.VendorID = data[i : i+int(d.VendorIDLength)]
359 i = i + int(d.VendorIDLength)
360
361 d.NWType = data[i]
362 i++
363 d.NWLength = binary.BigEndian.Uint16(data[i : i+2])
364 i = i + 2
365 d.NWValue = data[i : i+int(d.NWLength)]
366 i = i + int(d.NWLength)
367
368 d.DVType = data[i]
369 i++
370 d.DVLength = binary.BigEndian.Uint16(data[i : i+2])
371 i = i + 2
372 d.DVValue = data[i : i+int(d.DVLength)]
373 i = i + int(d.DVLength)
374
375 d.SCPType = data[i]
376 i++
377 d.SCPLength = binary.BigEndian.Uint16(data[i : i+2])
378 i = i + 2
379 d.SCPValue = data[i : i+int(d.SCPLength)]
380 i = i + int(d.SCPLength)
381
382 d.TunnelType = data[i]
383 i++
384 d.TunnelLength = binary.BigEndian.Uint16(data[i : i+2])
385 i = i + 2
386 d.TunnelValue = data[i : i+int(d.TunnelLength)]
387 i = i + int(d.TunnelLength)
388
389 d.PadType = data[i]
390 i++
391 d.PadLength = binary.BigEndian.Uint16(data[i : i+2])
392 i = i + 2
393 d.PadValue = data[i : i+int(d.PadLength)]
394
395 return nil
396}