blob: 3602f26e58373de0e404e25228888097285a0655 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Jonathan Hart20d8e512014-10-16 11:05:52 -070019package org.onlab.onos.sdnip.bgp;
20
21import java.util.Collection;
22
23import org.jboss.netty.buffer.ChannelBuffer;
24import org.jboss.netty.buffer.ChannelBuffers;
25import org.jboss.netty.channel.ChannelHandlerContext;
26import org.jboss.netty.channel.ChannelStateEvent;
27import org.jboss.netty.channel.SimpleChannelHandler;
28import org.onlab.packet.IpAddress;
29import org.onlab.packet.IpPrefix;
30
31/**
32 * Class for handling the remote BGP Peer session.
33 */
34class TestBgpPeerChannelHandler extends SimpleChannelHandler {
35 static final long PEER_AS = 65001;
36 static final int PEER_HOLDTIME = 120; // 120 seconds
37 final IpAddress bgpId; // The BGP ID
38 final long localPref; // Local preference for routes
39 final long multiExitDisc = 20; // MED value
40
41 ChannelHandlerContext savedCtx;
42
43 /**
44 * Constructor for given BGP ID.
45 *
46 * @param bgpId the BGP ID to use
47 * @param localPref the local preference for the routes to use
48 */
49 TestBgpPeerChannelHandler(IpAddress bgpId,
50 long localPref) {
51 this.bgpId = bgpId;
52 this.localPref = localPref;
53 }
54
55 /**
56 * Closes the channel.
57 */
58 void closeChannel() {
59 savedCtx.getChannel().close();
60 }
61
62 @Override
63 public void channelConnected(ChannelHandlerContext ctx,
64 ChannelStateEvent channelEvent) {
65 this.savedCtx = ctx;
66 // Prepare and transmit BGP OPEN message
67 ChannelBuffer message = prepareBgpOpen();
68 ctx.getChannel().write(message);
69
70 // Prepare and transmit BGP KEEPALIVE message
71 message = prepareBgpKeepalive();
72 ctx.getChannel().write(message);
73 }
74
75 @Override
76 public void channelDisconnected(ChannelHandlerContext ctx,
77 ChannelStateEvent channelEvent) {
78 // Nothing to do
79 }
80
81 /**
82 * Prepares BGP OPEN message.
83 *
84 * @return the message to transmit (BGP header included)
85 */
86 ChannelBuffer prepareBgpOpen() {
87 ChannelBuffer message =
88 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
89 message.writeByte(BgpConstants.BGP_VERSION);
90 message.writeShort((int) PEER_AS);
91 message.writeShort(PEER_HOLDTIME);
92 message.writeInt(bgpId.toInt());
93 message.writeByte(0); // No Optional Parameters
94 return prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN, message);
95 }
96
97 /**
98 * Prepares BGP UPDATE message.
99 *
100 * @param nextHopRouter the next-hop router address for the routes to add
101 * @param addedRoutes the routes to add
102 * @param withdrawnRoutes the routes to withdraw
103 * @return the message to transmit (BGP header included)
104 */
105 ChannelBuffer prepareBgpUpdate(IpAddress nextHopRouter,
106 Collection<IpPrefix> addedRoutes,
107 Collection<IpPrefix> withdrawnRoutes) {
108 int attrFlags;
109 ChannelBuffer message =
110 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
111 ChannelBuffer pathAttributes =
112 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
113
114 // Encode the Withdrawn Routes
115 ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
116 message.writeShort(encodedPrefixes.readableBytes());
117 message.writeBytes(encodedPrefixes);
118
119 // Encode the Path Attributes
120 // ORIGIN: IGP
121 attrFlags = 0x40; // Transitive flag
122 pathAttributes.writeByte(attrFlags);
123 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
124 pathAttributes.writeByte(1); // Data length
125 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
126 // AS_PATH: Two Path Segments of 3 ASes each
127 attrFlags = 0x40; // Transitive flag
128 pathAttributes.writeByte(attrFlags);
129 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
130 pathAttributes.writeByte(16); // Data length
131 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
132 pathAttributes.writeByte(pathSegmentType1);
133 pathAttributes.writeByte(3); // Three ASes
134 pathAttributes.writeShort(65010); // AS=65010
135 pathAttributes.writeShort(65020); // AS=65020
136 pathAttributes.writeShort(65030); // AS=65030
137 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
138 pathAttributes.writeByte(pathSegmentType2);
139 pathAttributes.writeByte(3); // Three ASes
140 pathAttributes.writeShort(65041); // AS=65041
141 pathAttributes.writeShort(65042); // AS=65042
142 pathAttributes.writeShort(65043); // AS=65043
143 // NEXT_HOP: nextHopRouter
144 attrFlags = 0x40; // Transitive flag
145 pathAttributes.writeByte(attrFlags);
146 pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
147 pathAttributes.writeByte(4); // Data length
148 pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
149 // LOCAL_PREF: localPref
150 attrFlags = 0x40; // Transitive flag
151 pathAttributes.writeByte(attrFlags);
152 pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
153 pathAttributes.writeByte(4); // Data length
154 pathAttributes.writeInt((int) localPref); // Preference value
155 // MULTI_EXIT_DISC: multiExitDisc
156 attrFlags = 0x80; // Optional
157 // Non-Transitive flag
158 pathAttributes.writeByte(attrFlags);
159 pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
160 pathAttributes.writeByte(4); // Data length
161 pathAttributes.writeInt((int) multiExitDisc); // Preference value
162 // The NLRI prefixes
163 encodedPrefixes = encodePackedPrefixes(addedRoutes);
164
165 // Write the Path Attributes, beginning with its length
166 message.writeShort(pathAttributes.readableBytes());
167 message.writeBytes(pathAttributes);
168 message.writeBytes(encodedPrefixes);
169
170 return prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE, message);
171 }
172
173 /**
174 * Encodes a collection of IPv4 network prefixes in a packed format.
175 * <p>
176 * The IPv4 prefixes are encoded in the form:
177 * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
178 * and Prefix is the IPv4 prefix (padded with trailing bits to the end
179 * of an octet).
180 *
181 * @param prefixes the prefixes to encode
182 * @return the buffer with the encoded prefixes
183 */
184 private ChannelBuffer encodePackedPrefixes(Collection<IpPrefix> prefixes) {
185 ChannelBuffer message =
186 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
187
188 // Write each of the prefixes
189 for (IpPrefix prefix : prefixes) {
190 int prefixBitlen = prefix.prefixLength();
191 int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
192 message.writeByte(prefixBitlen);
193
194 IpAddress address = prefix.toIpAddress();
195 long value = address.toInt() & 0xffffffffL;
196 for (int i = 0; i < IpAddress.INET_LEN; i++) {
197 if (prefixBytelen-- == 0) {
198 break;
199 }
200 long nextByte =
201 (value >> ((IpAddress.INET_LEN - i - 1) * 8)) & 0xff;
202 message.writeByte((int) nextByte);
203 }
204 }
205
206 return message;
207 }
208
209 /**
210 * Prepares BGP KEEPALIVE message.
211 *
212 * @return the message to transmit (BGP header included)
213 */
214 ChannelBuffer prepareBgpKeepalive() {
215 ChannelBuffer message =
216 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
217 return prepareBgpMessage(BgpConstants.BGP_TYPE_KEEPALIVE, message);
218 }
219
220 /**
221 * Prepares BGP NOTIFICATION message.
222 *
223 * @param errorCode the BGP NOTIFICATION Error Code
224 * @param errorSubcode the BGP NOTIFICATION Error Subcode if applicable,
225 * otherwise BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC
226 * @param payload the BGP NOTIFICATION Data if applicable, otherwise null
227 * @return the message to transmit (BGP header included)
228 */
229 ChannelBuffer prepareBgpNotification(int errorCode, int errorSubcode,
230 ChannelBuffer data) {
231 ChannelBuffer message =
232 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
233 // Prepare the NOTIFICATION message payload
234 message.writeByte(errorCode);
235 message.writeByte(errorSubcode);
236 if (data != null) {
237 message.writeBytes(data);
238 }
239 return prepareBgpMessage(BgpConstants.BGP_TYPE_NOTIFICATION, message);
240 }
241
242 /**
243 * Prepares BGP message.
244 *
245 * @param type the BGP message type
246 * @param payload the message payload to transmit (BGP header excluded)
247 * @return the message to transmit (BGP header included)
248 */
249 private ChannelBuffer prepareBgpMessage(int type, ChannelBuffer payload) {
250 ChannelBuffer message =
251 ChannelBuffers.buffer(BgpConstants.BGP_HEADER_LENGTH +
252 payload.readableBytes());
253
254 // Write the marker
255 for (int i = 0; i < BgpConstants.BGP_HEADER_MARKER_LENGTH; i++) {
256 message.writeByte(0xff);
257 }
258
259 // Write the rest of the BGP header
260 message.writeShort(BgpConstants.BGP_HEADER_LENGTH +
261 payload.readableBytes());
262 message.writeByte(type);
263
264 // Write the payload
265 message.writeBytes(payload);
266 return message;
267 }
268}