blob: 5405ae28ae9810782a4503a41adb87ec972b334a [file] [log] [blame]
karthik197797fc7d92024-03-22 19:01:58 +05301/*
2 * Copyright 2024-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 org.onosproject.bgpmonitoring.type;
18
19import com.google.common.base.MoreObjects;
20import org.onlab.packet.DeserializationException;
21import org.onlab.packet.Deserializer;
22
23import java.nio.ByteBuffer;
24import java.util.function.BiPredicate;
25import java.util.Arrays;
26import java.util.Map;
27import java.util.Optional;
28import java.util.concurrent.ConcurrentHashMap;
29
30import org.onosproject.bgpmonitoring.BmpMessage;
31import org.onosproject.bgpmonitoring.BmpVersion;
32import org.onosproject.bgpmonitoring.BmpPacket;
33import org.onosproject.bgpmonitoring.BmpParseException;
34
35import static com.google.common.base.Preconditions.checkState;
36
37/**
38 * The following common header appears in all BMP messages. The rest of
39 * the data in a BMP message is dependent on the Message Type field in
40 * the common header.
41 * <p>
42 * Version (1 byte): Indicates the BMP version. This is set to '3'
43 * for all messages defined in this specification. ('1' and '2' were
44 * used by draft versions of this document.) Version 0 is reserved
45 * and MUST NOT be sent.
46 * <p>
47 * Message Length (4 bytes): Length of the message in bytes
48 * (including headers, data, and encapsulated messages, if any).
49 * <p>
50 * Message Type (1 byte): This identifies the type of the BMP
51 * message. A BMP implementation MUST ignore unrecognized message
52 * types upon receipt.
53 * <p>
54 * Type = 0: Route Monitoring
55 * Type = 1: Statistics Report
56 * Type = 2: Peer Down Notification
57 * Type = 3: Peer Up Notification
58 * Type = 4: Initiation Message
59 * Type = 5: Termination Message
60 * Type = 6: Route Mirroring Message
61 */
62public final class BmpHeader extends BmpPacket {
63
64 /*
65
66 0 1 2 3
67 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
68 +-+-+-+-+-+-+-+-+
69 | Version |
70 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 | Message Length |
72 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 | Msg. Type |
74 +---------------+
75
76 */
77
78
79 public static final int DEFAULT_HEADER_LENGTH = 6;
80 public static final int DEFAULT_PACKET_MINIMUM_LENGTH = 4;
81
82 private BmpVersion version;
83
84 private BmpType type;
85
86 private int length;
87
88 private BmpMessage message;
89
90
91 public enum BmpType {
92
93 ROUTE_MONITORING(0, BmpRouteMirroring.deserializer()),
94
95 STATISTICS_REPORT(1, BmpStatsReport.deserializer()),
96
97 PEER_DOWN_NOTIFICATION(2, BmpPeerDownNotification.deserializer()),
98
99 PEER_UP_NOTIFICATION(3, BmpPeerUpNotification.deserializer()),
100
101 INITIATION_MESSAGE(4, BmpInitiationMessage.deserializer()),
102
103 TERMINATION_MESSAGE(5, BmpTerminationMessage.deserializer()),
104
105 ROUTE_MIRRORING_MESSAGE(6, BmpRouteMirroring.deserializer());
106
107 private final int value;
108 private final Deserializer<BmpMessage> deserializer;
109
110 /**
111 * Assign value with the value val as the types of BMP message.
112 *
113 * @param val type of BMP message
114 * @param deserializer deserializer
115 */
116 BmpType(int val, Deserializer deserializer) {
117 this.value = val;
118 this.deserializer = deserializer;
119 }
120
121
122 /**
123 * Returns value as type of BMP message.
124 *
125 * @return value type of BMP message
126 */
127 public int getType() {
128 return value;
129 }
130
131 private static Map<Integer, BmpType> parser = new ConcurrentHashMap<>();
132
133 static {
134 Arrays.stream(BmpType.values()).forEach(type -> parser.put(type.value, type));
135 }
136
137 public static BmpType getType(int type) throws DeserializationException {
138 if (type > 6) {
139 throw new DeserializationException("Invalid trap type");
140 }
141 return Optional.of(type)
142 .filter(id -> parser.containsKey(id))
143 .map(id -> parser.get(id))
144 .orElse(ROUTE_MONITORING);
145 }
146
147 public Deserializer<BmpMessage> getDecoder() {
148 return this.deserializer;
149 }
150
151 }
152
153
154 private BmpHeader(Builder builder) {
155 this.version = builder.version;
156 this.length = builder.length;
157 this.type = builder.type;
158 this.message = builder.message;
159 }
160
161
162 /**
163 * Returns message length.
164 *
165 * @return message length
166 */
167 @Override
168 public int getLength() {
169 return this.length;
170 }
171
172 /**
173 * Returns message version.
174 *
175 * @return message version
176 */
177 @Override
178 public BmpVersion getVersion() {
179 return this.version;
180 }
181
182 /**
183 * Returns message type.
184 *
185 * @return message type
186 */
187 @Override
188 public String getType() {
189 return this.type.name();
190 }
191
192 /**
193 * Returns message type.
194 *
195 * @return message type
196 */
197 @Override
198 public BmpMessage getMessage() {
199 return this.message;
200 }
201
202
203 /**
204 * Read from channel buffer and Returns BMP header.
205 *
206 * @return Deserializer Deserializer
207 */
208 public static Deserializer<BmpHeader> deserializer() {
209 return (data, offset, length) -> {
210 BiPredicate<ByteBuffer, Integer> isValidBuffer = (b, l)
211 -> b.hasRemaining() && b.remaining() >= l;
212
213 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
214
215 if (!isValidBuffer.test(bb, DEFAULT_HEADER_LENGTH)) {
216 throw new BmpParseException("Invalid bmp header buffer size.");
217 }
218 Builder builder = new Builder()
219 .version(BmpVersion.getVersion((int) bb.get()))
220 .length(bb.getInt())
221 .type(BmpType.getType((int) bb.get()));
222
223 if (bb.remaining() != (builder.length - DEFAULT_HEADER_LENGTH)) {
224 throw new BmpParseException("Invalid bmp header buffer size.");
225 }
226
227 byte[] msgBytes = new byte[bb.remaining()];
228 bb.get(msgBytes);
229 return builder.message(builder.type.getDecoder()
230 .deserialize(msgBytes, 0, (builder.length - DEFAULT_HEADER_LENGTH)))
231 .build();
232
233 };
234 }
235
236
237 @Override
238 public String toString() {
239 return MoreObjects.toStringHelper(getClass())
240 .add("version", version)
241 .add("type", type)
242 .add("length", length)
243 .toString();
244 }
245
246 /**
247 * Builder for BMP header.
248 */
249 private static class Builder {
250
251 private BmpVersion version;
252
253 private BmpType type;
254
255 private int length;
256
257 private BmpMessage message;
258
259
260 /**
261 * Setter bmp version.
262 *
263 * @param version bmp version.
264 * @return this class builder.
265 */
266 public Builder version(BmpVersion version) {
267 this.version = version;
268 return this;
269 }
270
271
272 /**
273 * Setter bmp header length.
274 *
275 * @param length bmp header length.
276 * @return this class builder.
277 */
278 public Builder length(int length) {
279 this.length = length;
280 return this;
281 }
282
283 /**
284 * Setter bmp message type.
285 *
286 * @param type bmp message type.
287 * @return this class builder.
288 */
289 public Builder type(BmpType type) {
290 this.type = type;
291 return this;
292 }
293
294
295 /**
296 * Setter bmp message.
297 *
298 * @param message bmp message.
299 * @return this class builder.
300 */
301 public Builder message(BmpMessage message) {
302 this.message = message;
303 return this;
304 }
305
306
307 /**
308 * Checks arguments for bmp header.
309 */
310 private void checkArguments() {
311 checkState(length != 0, "Invalid bmp header length.");
312 checkState(type != null, "Invalid bmp message type.");
313 checkState(message != null, "Invalid bmp message.");
314 }
315
316 /**
317 * Builds BMP header.
318 *
319 * @return BMP header.
320 */
321 public BmpHeader build() {
322 checkArguments();
323 return new BmpHeader(this);
324 }
325 }
326}