blob: 05fb5b438acbf16b88fc8b1fe3044f5bd3a570ac [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.sdnip.bgp;
Jonathan Hart20d8e512014-10-16 11:05:52 -070017
18import java.util.Collection;
19
20import org.jboss.netty.buffer.ChannelBuffer;
21import org.jboss.netty.buffer.ChannelBuffers;
22import org.jboss.netty.channel.ChannelHandlerContext;
23import org.jboss.netty.channel.ChannelStateEvent;
24import org.jboss.netty.channel.SimpleChannelHandler;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080025import org.onlab.packet.Ip4Address;
26import org.onlab.packet.Ip4Prefix;
Jonathan Hart20d8e512014-10-16 11:05:52 -070027
28/**
29 * Class for handling the remote BGP Peer session.
30 */
31class TestBgpPeerChannelHandler extends SimpleChannelHandler {
32 static final long PEER_AS = 65001;
33 static final int PEER_HOLDTIME = 120; // 120 seconds
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080034 final Ip4Address bgpId; // The BGP ID
Jonathan Hart20d8e512014-10-16 11:05:52 -070035 ChannelHandlerContext savedCtx;
36
37 /**
38 * Constructor for given BGP ID.
39 *
40 * @param bgpId the BGP ID to use
Jonathan Hart20d8e512014-10-16 11:05:52 -070041 */
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080042 TestBgpPeerChannelHandler(Ip4Address bgpId) {
Jonathan Hart20d8e512014-10-16 11:05:52 -070043 this.bgpId = bgpId;
Jonathan Hart20d8e512014-10-16 11:05:52 -070044 }
45
46 /**
47 * Closes the channel.
48 */
49 void closeChannel() {
50 savedCtx.getChannel().close();
51 }
52
53 @Override
54 public void channelConnected(ChannelHandlerContext ctx,
55 ChannelStateEvent channelEvent) {
56 this.savedCtx = ctx;
57 // Prepare and transmit BGP OPEN message
58 ChannelBuffer message = prepareBgpOpen();
59 ctx.getChannel().write(message);
60
61 // Prepare and transmit BGP KEEPALIVE message
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080062 message = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hart20d8e512014-10-16 11:05:52 -070063 ctx.getChannel().write(message);
64 }
65
66 @Override
67 public void channelDisconnected(ChannelHandlerContext ctx,
68 ChannelStateEvent channelEvent) {
69 // Nothing to do
70 }
71
72 /**
73 * Prepares BGP OPEN message.
74 *
75 * @return the message to transmit (BGP header included)
76 */
77 ChannelBuffer prepareBgpOpen() {
78 ChannelBuffer message =
79 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
80 message.writeByte(BgpConstants.BGP_VERSION);
81 message.writeShort((int) PEER_AS);
82 message.writeShort(PEER_HOLDTIME);
83 message.writeInt(bgpId.toInt());
84 message.writeByte(0); // No Optional Parameters
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080085 return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN,
86 message);
Jonathan Hart20d8e512014-10-16 11:05:52 -070087 }
88
89 /**
90 * Prepares BGP UPDATE message.
91 *
92 * @param nextHopRouter the next-hop router address for the routes to add
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080093 * @param localPref the local preference for the routes to use
94 * @param multiExitDisc the MED value
95 * @param asPath the AS path for the routes to add
Jonathan Hart20d8e512014-10-16 11:05:52 -070096 * @param addedRoutes the routes to add
97 * @param withdrawnRoutes the routes to withdraw
98 * @return the message to transmit (BGP header included)
99 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800100 ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800101 long localPref,
102 long multiExitDisc,
103 BgpRouteEntry.AsPath asPath,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800104 Collection<Ip4Prefix> addedRoutes,
105 Collection<Ip4Prefix> withdrawnRoutes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700106 int attrFlags;
107 ChannelBuffer message =
108 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
109 ChannelBuffer pathAttributes =
110 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
111
112 // Encode the Withdrawn Routes
113 ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
114 message.writeShort(encodedPrefixes.readableBytes());
115 message.writeBytes(encodedPrefixes);
116
117 // Encode the Path Attributes
118 // ORIGIN: IGP
119 attrFlags = 0x40; // Transitive flag
120 pathAttributes.writeByte(attrFlags);
121 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
122 pathAttributes.writeByte(1); // Data length
123 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800124
125 // AS_PATH: asPath
Jonathan Hart20d8e512014-10-16 11:05:52 -0700126 attrFlags = 0x40; // Transitive flag
127 pathAttributes.writeByte(attrFlags);
128 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800129 ChannelBuffer encodedAsPath = encodeAsPath(asPath);
130 pathAttributes.writeByte(encodedAsPath.readableBytes()); // Data length
131 pathAttributes.writeBytes(encodedAsPath);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700132 // NEXT_HOP: nextHopRouter
133 attrFlags = 0x40; // Transitive flag
134 pathAttributes.writeByte(attrFlags);
135 pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
136 pathAttributes.writeByte(4); // Data length
137 pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
138 // LOCAL_PREF: localPref
139 attrFlags = 0x40; // Transitive flag
140 pathAttributes.writeByte(attrFlags);
141 pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
142 pathAttributes.writeByte(4); // Data length
143 pathAttributes.writeInt((int) localPref); // Preference value
144 // MULTI_EXIT_DISC: multiExitDisc
145 attrFlags = 0x80; // Optional
146 // Non-Transitive flag
147 pathAttributes.writeByte(attrFlags);
148 pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
149 pathAttributes.writeByte(4); // Data length
150 pathAttributes.writeInt((int) multiExitDisc); // Preference value
151 // The NLRI prefixes
152 encodedPrefixes = encodePackedPrefixes(addedRoutes);
153
154 // Write the Path Attributes, beginning with its length
155 message.writeShort(pathAttributes.readableBytes());
156 message.writeBytes(pathAttributes);
157 message.writeBytes(encodedPrefixes);
158
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800159 return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE,
160 message);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700161 }
162
163 /**
164 * Encodes a collection of IPv4 network prefixes in a packed format.
165 * <p>
166 * The IPv4 prefixes are encoded in the form:
167 * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
168 * and Prefix is the IPv4 prefix (padded with trailing bits to the end
169 * of an octet).
170 *
171 * @param prefixes the prefixes to encode
172 * @return the buffer with the encoded prefixes
173 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800174 private ChannelBuffer encodePackedPrefixes(Collection<Ip4Prefix> prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700175 ChannelBuffer message =
176 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
177
178 // Write each of the prefixes
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800179 for (Ip4Prefix prefix : prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700180 int prefixBitlen = prefix.prefixLength();
181 int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
182 message.writeByte(prefixBitlen);
183
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800184 Ip4Address address = prefix.address();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700185 long value = address.toInt() & 0xffffffffL;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800186 for (int i = 0; i < Ip4Address.BYTE_LENGTH; i++) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700187 if (prefixBytelen-- == 0) {
188 break;
189 }
190 long nextByte =
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800191 (value >> ((Ip4Address.BYTE_LENGTH - i - 1) * 8)) & 0xff;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700192 message.writeByte((int) nextByte);
193 }
194 }
195
196 return message;
197 }
198
199 /**
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800200 * Encodes an AS path.
201 *
202 * @param asPath the AS path to encode
203 * @return the buffer with the encoded AS path
204 */
205 private ChannelBuffer encodeAsPath(BgpRouteEntry.AsPath asPath) {
206 ChannelBuffer message =
207 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
208
209 for (BgpRouteEntry.PathSegment pathSegment : asPath.getPathSegments()) {
210 message.writeByte(pathSegment.getType());
211 message.writeByte(pathSegment.getSegmentAsNumbers().size());
212 for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
213 message.writeShort(asNumber.intValue());
214 }
215 }
216
217 return message;
218 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700219}