blob: 50c5dacefdfd153fa73704208a67f215b82d2131 [file] [log] [blame]
Niraj Dubeya8287192021-03-23 19:54:17 +05301/*
2 * Copyright 2021-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.onlab.packet.bmp;
18
19import com.google.common.base.MoreObjects;
20import org.onlab.packet.BasePacket;
21import org.onlab.packet.Deserializer;
22import org.slf4j.Logger;
23
24import java.net.InetAddress;
25import java.net.UnknownHostException;
26import java.nio.ByteBuffer;
27
28import static org.onlab.packet.PacketUtils.checkInput;
29import static org.slf4j.LoggerFactory.getLogger;
30
31/**
32 * The per-peer header follows the common header for most BMP messages.
33 * The rest of the data in a BMP message is dependent on the Message
34 * Type field in the common header.
35 * <p>
36 * Peer Type (1 byte): Identifies the type of peer. Currently, three
37 * types of peers are identified:
38 * <p>
39 * * Peer Type = 0: Global Instance Peer
40 * * Peer Type = 1: RD Instance Peer
41 * * Peer Type = 2: Local Instance Peer
42 * <p>
43 * o Peer Flags (1 byte): These flags provide more information about
44 * the peer. The flags are defined as follows:
45 * <p>
46 * 0 1 2 3 4 5 6 7
47 * +-+-+-+-+-+-+-+-+
48 * |V|L|A| Reserved|
49 * +-+-+-+-+-+-+-+-+
50 * <p>
51 * * The V flag indicates that the Peer address is an IPv6 address.
52 * For IPv4 peers, this is set to 0.
53 * <p>
54 * The L flag, if set to 1, indicates that the message reflects
55 * the post-policy Adj-RIB-In (i.e., its path attributes reflect
56 * the application of inbound policy). It is set to 0 if the
57 * message reflects the pre-policy Adj-RIB-In. Locally sourced
58 * routes also carry an L flag of 1. See Section 5 for further
59 * detail. This flag has no significance when used with route
60 * mirroring messages.
61 * <p>
62 * * The A flag, if set to 1, indicates that the message is
63 * formatted using the legacy 2-byte AS_PATH format. If set to 0,
64 * the message is formatted using the 4-byte AS_PATH format
65 * [RFC6793]. A BMP speaker MAY choose to propagate the AS_PATH
66 * information as received from its peer, or it MAY choose to
67 * reformat all AS_PATH information into a 4-byte format
68 * regardless of how it was received from the peer. In the latter
69 * case, AS4_PATH or AS4_AGGREGATOR path attributes SHOULD NOT be
70 * sent in the BMP UPDATE message. This flag has no significance
71 * when used with route mirroring messages.
72 * <p>
73 * The remaining bits are reserved for future use. They MUST be
74 * transmitted as 0 and their values MUST be ignored on receipt.
75 * <p>
76 * Peer Distinguisher (8 bytes): Routers today can have multiple
77 * instances (example: Layer 3 Virtual Private Networks (L3VPNs)
78 * [RFC4364]). This field is present to distinguish peers that
79 * belong to one address domain from the other.
80 * <p>
81 * If the peer is a "Global Instance Peer", this field is zero-
82 * filled. If the peer is a "RD Instance Peer", it is set to the
83 * route distinguisher of the particular instance the peer belongs
84 * to. If the peer is a "Local Instance Peer", it is set to a
85 * unique, locally defined value. In all cases, the effect is that
86 * the combination of the Peer Type and Peer Distinguisher is
87 * sufficient to disambiguate peers for which other identifying
88 * information might overlap.
89 * <p>
90 * Peer Address: The remote IP address associated with the TCP
91 * session over which the encapsulated PDU was received. It is 4
92 * bytes long if an IPv4 address is carried in this field (with the
93 * 12 most significant bytes zero-filled) and 16 bytes long if an
94 * IPv6 address is carried in this field.
95 * <p>
96 * Peer AS: The Autonomous System number of the peer from which the
97 * encapsulated PDU was received. If a 16-bit AS number is stored in
98 * this field [RFC6793], it should be padded with zeroes in the 16
99 * most significant bits.
100 * <p>
101 * Timestamp: The time when the encapsulated routes were received
102 * (one may also think of this as the time when they were installed
103 * in the Adj-RIB-In), expressed in seconds and microseconds since
104 * midnight (zero hour), January 1, 1970 (UTC). If zero, the time is
105 * unavailable. Precision of the timestamp is implementation-
106 * dependent.
107 * <p>
108 * 4.3. Initiation Message
109 * <p>
110 * The initiation message provides a means for the monitored router to
111 * inform the monitoring station of its vendor, software version, and so
112 * on. An initiation message MUST be sent as the first message after
113 * the TCP session comes up. An initiation message MAY be sent at any
114 * point thereafter, if warranted by a change on the monitored router.
115 * <p>
116 * The initiation message consists of the common BMP header followed by
117 * two or more Information TLVs containing information
118 * about the monitored router. The sysDescr and sysName Information
119 * TLVs MUST be sent, any others are optional. The string TLV MAY be
120 * included multiple times.
121 */
122public class BmpPeer extends BasePacket {
123
124 /*
125 0 1 2 3
126 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
127 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 | Peer Type | Peer Flags |
129 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130 | Peer Distinguisher (present based on peer type) |
131 | |
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 | Peer Address (16 bytes) |
134 ~ ~
135 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 | Peer AS |
137 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 | Peer BGP ID |
139 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140 | Timestamp (seconds) |
141 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 | Timestamp (microseconds) |
143 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144 */
145 public static final short PEER_HEADER_MINIMUM_LENGTH = 42;
146
147 public static final short PEER_DISTINGUISHER = 8;
148 public static final short IPV4_ADDRSZ = 4;
149 public static final short IPV6_ADDRSZ = 16;
150
151 protected byte type;
152
153 protected byte flags;
154
155 protected byte[] peerDistinguisher;
156
157 protected InetAddress peerAddress;
158
159 protected int peerAs;
160
161 protected int peerBgpId;
162
163 protected long seconds;
164
165 protected long microseconds;
166
167 private static Logger log = getLogger(BmpPeer.class);
168
169
170 /**
171 * Returns Peer Type.
172 *
173 * @return the peer type
174 */
175 public byte getType() {
176 return type;
177 }
178
179 /**
180 * Returns Peer Flag.
181 *
182 * @return the peer flag
183 */
184 public byte getFlag() {
185 return flags;
186 }
187
188 /**
189 * Returns Peer Distinguisher.
190 *
191 * @return the peer distingusiher
192 */
193 public byte[] getPeerDistinguisher() {
194 return peerDistinguisher;
195 }
196
197 /**
198 * Returns Peer IP Address.
199 *
200 * @return the peer ip address
201 */
202 public InetAddress getIntAddress() {
203 return peerAddress;
204 }
205
206 /**
207 * Returns Peer Autonomous System number.
208 *
209 * @return the peer AS number
210 */
211 public int getPeerAs() {
212 return peerAs;
213 }
214
215 /**
216 * Returns Peer Bgp Id.
217 *
218 * @return the bgp id
219 */
220 public int getPeerBgpId() {
221 return peerBgpId;
222 }
223
224 /**
225 * Returns timestamp in sec.
226 *
227 * @return the timestamp in sec
228 */
229 public long getSeconds() {
230 return seconds;
231 }
232
233 /**
234 * Returns timestamp in micro second.
235 *
236 * @return the timestamp in micro second
237 */
238 public long getMicroseconds() {
239 return microseconds;
240 }
241
242
243 @Override
244 public byte[] serialize() {
245 final byte[] data = new byte[PEER_HEADER_MINIMUM_LENGTH];
246 final ByteBuffer bb = ByteBuffer.wrap(data);
247
248 bb.put(this.type);
249 bb.put(this.flags);
250 bb.put(this.peerDistinguisher);
251 bb.put(this.peerAddress.getAddress());
252 bb.putInt(this.peerAs);
253 bb.putInt(this.peerBgpId);
254 bb.putLong(this.seconds);
255 bb.putLong(this.microseconds);
256
257 return data;
258 }
259
260 public static Deserializer<BmpPeer> deserializer() {
261 return (data, offset, length) -> {
262 checkInput(data, offset, length, PEER_HEADER_MINIMUM_LENGTH);
263
264 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
265 BmpPeer bmpPeer = new BmpPeer();
266
267 bmpPeer.type = bb.get();
268 bmpPeer.flags = bb.get();
269 bmpPeer.peerDistinguisher = new byte[PEER_DISTINGUISHER];
270 bb.get(bmpPeer.peerDistinguisher, 0, PEER_DISTINGUISHER);
271
272 if ((bmpPeer.flags & 0x80) != 0x00) {
273 bmpPeer.peerAddress = toInetAddress(IPV6_ADDRSZ, bb);
274 } else {
275 bb.position(bb.position() + (IPV6_ADDRSZ - IPV4_ADDRSZ));
276 bmpPeer.peerAddress = toInetAddress(IPV4_ADDRSZ, bb);
277 }
278
279 bmpPeer.peerAs = bb.getInt();
280 bmpPeer.peerBgpId = bb.getInt();
281 bmpPeer.seconds = bb.getInt();
282 bmpPeer.microseconds = bb.getInt();
283
284 return bmpPeer;
285 };
286 }
287
288 private static InetAddress toInetAddress(int length, ByteBuffer bb) {
289 byte[] address = new byte[length];
290 bb.get(address, 0, length);
291 InetAddress ipAddress = null;
292 try {
293 ipAddress = InetAddress.getByAddress(address);
294 } catch (UnknownHostException e) {
295 log.error("InetAddress conversion failed");
296 }
297
298 return ipAddress;
299 }
300
301 @Override
302 public String toString() {
303
304 return MoreObjects.toStringHelper(getClass())
305 .add("flags", flags)
306 .add("type", type)
307 .add("peerAddress", peerAddress.getHostAddress())
308 .add("peerAs", peerAs)
309 .add("seconds", seconds)
310 .add("microseconds", microseconds)
311 .toString();
312 }
313
314}