blob: 7aa6bec68206d5fd094ef955eb2b88a1e64921fe [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
25 "github.com/google/gopacket"
26 "github.com/google/gopacket/layers"
27)
28
29// TOAMSetRequest is a structure for SET request of TOAM message
30type TOAMSetRequest struct {
31 layers.BaseLayer
32 Opcode uint8
33 Flags uint16
34 OAMPDUCode uint8
35 OUId []byte // Organizationally Unique Identifier: 2a:ea:15 (Tibit Communications)
36 TOMIOpcode uint8
37 CTBranch uint8
38 CTType uint16
39 CTLength uint8
40 CTInstance uint32
41 OCBranch uint8
42 OCType uint16
43 OCLength uint8
44 OCInstance uint32
45 VcBranch uint8
46 VcLeaf uint16
47 VcLength uint8
48 ECLength uint8
49 ECValue []byte
50 ECList []ECValueSet
51 EndBranch uint8
52}
53
54// ECValueSet is a structure for Vc-EC object
55type ECValueSet struct {
56 Length uint8
57 Value []byte
58}
59
60// String returns the string expression of TOAMSetRequest
61func (d *TOAMSetRequest) String() string {
62 message := fmt.Sprintf("Opcode:%x, Flags:%x, OAMPDUCode:%x, OUId:%v", d.Opcode, d.Flags, d.OAMPDUCode, hex.EncodeToString(d.OUId))
63 message = fmt.Sprintf("%s, TOMIOpcode:%x", message, d.TOMIOpcode)
64 message = fmt.Sprintf("%s, CTBranch:%x, CTType:%x, CTLength:%x, CTInstance:%x", message, d.CTBranch, d.CTType, d.CTLength, d.CTInstance)
65 message = fmt.Sprintf("%s, OCBranch:%x, OCType:%x, OCLength:%x, OCInstance:%x", message, d.OCBranch, d.OCType, d.OCLength, d.OCInstance)
66 message = fmt.Sprintf("%s, VcBranch:%x, VcLeaf:%x, VcLength:%x", message, d.VcBranch, d.VcLeaf, d.VcLength)
67 message = fmt.Sprintf("%s, ECLength:%x, ECValue:%v, EndBranch:%x", message, d.ECLength, hex.EncodeToString(d.ECValue), d.EndBranch)
68 return message
69}
70
71// Len returns the length of TOAMSetRequest
72func (d *TOAMSetRequest) Len() int {
73 if d.VcLength != 0x80 {
74 return 22 + int(d.CTLength) + int(d.OCLength) + int(d.VcLength)
75 }
76 return 22 + int(d.CTLength) + int(d.OCLength)
77
78}
79
80// LayerType returns the ethernet type of TOAMSetRequest
81func (d *TOAMSetRequest) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
82
83// SerializeTo serializes a data structure to byte arrays
84func (d *TOAMSetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
85 plen := int(d.Len())
86 data, err := b.PrependBytes(plen)
87 if err != nil {
88 return err
89 }
90
91 i := 0
92 data[i] = byte(d.Opcode)
93 i++
94 binary.BigEndian.PutUint16(data[i:i+2], d.Flags)
95 i += 2
96 data[i] = byte(d.OAMPDUCode)
97 i++
98 copy(data[i:i+len(d.OUId)], d.OUId)
99 i += len(d.OUId)
100 data[i] = byte(d.TOMIOpcode)
101 i++
102 data[i] = byte(d.CTBranch)
103 i++
104 binary.BigEndian.PutUint16(data[i:i+2], d.CTType)
105 i += 2
106 data[i] = byte(d.CTLength)
107 i++
108 binary.BigEndian.PutUint32(data[i:i+4], d.CTInstance)
109 i += 4
110 data[i] = byte(d.OCBranch)
111 i++
112 binary.BigEndian.PutUint16(data[i:i+2], d.OCType)
113 i += 2
114 data[i] = byte(d.OCLength)
115 i++
116 binary.BigEndian.PutUint32(data[i:i+4], d.OCInstance)
117 i += 4
118 data[i] = byte(d.VcBranch)
119 i++
120 binary.BigEndian.PutUint16(data[i:i+2], d.VcLeaf)
121 i += 2
122 data[i] = byte(d.VcLength)
123 i++
124 if d.VcLength != 0x80 {
125 // EC
126 data[i] = byte(d.ECLength)
127 i++
128 copy(data[i:i+int(d.ECLength)], d.ECValue)
129 i += int(d.ECLength)
130 }
131 if d.ECList != nil {
132 for _, ecSet := range d.ECList {
133 data[i] = byte(ecSet.Length)
134 i++
135 copy(data[i:i+int(ecSet.Length)], ecSet.Value)
136 i += int(ecSet.Length)
137 }
138 }
139
140 data[i] = byte(d.EndBranch)
141
142 return nil
143}
144
145// TOAMSetResponse is a structure for SET response of TOAM message
146type TOAMSetResponse struct {
147 layers.BaseLayer
148 Opcode uint8
149 Flags uint16
150 OAMPDUCode uint8
151 OUId []byte // Organizationally Unique Identifier: 2a:ea:15 (Tibit Communications)
152 TOMIOpcode uint8
153 CTBranch uint8
154 CTType uint16
155 CTLength uint8
156 CTInstance uint32
157 OCBranch uint8
158 OCType uint16
159 OCLength uint8
160 OCInstance uint32
161 VcBranch uint8
162 VcLeaf uint16
163 VcTOMIResCode uint8
164 EndBranch uint8
165}
166
167// String returns the string expression of TOAMSetResponse
168func (d *TOAMSetResponse) String() string {
169 message := fmt.Sprintf("Opcode:%x, Flags:%x, OAMPDUCode:%x, OUId:%v", d.Opcode, d.Flags, d.OAMPDUCode, hex.EncodeToString(d.OUId))
170 message = fmt.Sprintf("%s, TOMIOpcode:%x", message, d.TOMIOpcode)
171 message = fmt.Sprintf("%s, CTBranch:%x, CTType:%x, CTLength:%x, CTInstance:%x", message, d.CTBranch, d.CTType, d.CTLength, d.CTInstance)
172 message = fmt.Sprintf("%s, OCBranch:%x, OCType:%x, OCLength:%x, OCInstance:%x", message, d.OCBranch, d.OCType, d.OCLength, d.OCInstance)
173 message = fmt.Sprintf("%s, VcBranch:%x, VcLeaf:%x, VcTOMIResCode:%x, EndBranch:%x", message, d.VcBranch, d.VcLeaf, d.VcTOMIResCode, d.EndBranch)
174 return message
175}
176
177// Len returns the length of TOAMSetResponse
178func (d *TOAMSetResponse) Len() int {
179 return 34 + int(d.CTLength) + int(d.OCLength)
180}
181
182// LayerType returns the ethernet type of TOAMSetResponse
183func (d *TOAMSetResponse) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
184
185// Decode decodes byte arrays to a data structure
186func (d *TOAMSetResponse) Decode(data []byte) error {
187 i := 0
188 d.Opcode = data[i]
189 i++
190 d.Flags = binary.BigEndian.Uint16(data[i : i+2])
191 i += 2
192 d.OAMPDUCode = data[i]
193 i++
194 d.OUId = data[i : i+3]
195 i += len(d.OUId)
196 d.TOMIOpcode = data[i]
197 i++
198 d.CTBranch = data[i]
199 i++
200 d.CTType = binary.BigEndian.Uint16(data[i : i+2])
201 i += 2
202 d.CTLength = data[i]
203 i++
204 d.CTInstance = binary.BigEndian.Uint32(data[i : i+4])
205 i += 4
206 d.OCBranch = data[i]
207 i++
208 d.OCType = binary.BigEndian.Uint16(data[i : i+2])
209 i += 2
210 d.OCLength = data[i]
211 i++
212 d.OCInstance = binary.BigEndian.Uint32(data[i : i+4])
213 i += 4
214 d.VcBranch = data[i]
215 i++
216 d.VcLeaf = binary.BigEndian.Uint16(data[i : i+2])
217 i += 2
218 d.VcTOMIResCode = data[i]
219 i++
220 d.EndBranch = data[i]
221
222 return nil
223}