blob: a4ec1b4dda917443cd6dca446b31b37e6b7c7f28 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present 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 */
Jonathan Hart41349e92015-02-09 14:14:02 -080016package org.onosproject.routing.bgp;
Jonathan Hart20d8e512014-10-16 11:05:52 -070017
18import org.jboss.netty.buffer.ChannelBuffer;
19import org.jboss.netty.buffer.ChannelBuffers;
20import org.jboss.netty.channel.ChannelHandlerContext;
21import org.jboss.netty.channel.ChannelStateEvent;
22import org.jboss.netty.channel.SimpleChannelHandler;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080023import org.onlab.packet.Ip4Address;
24import org.onlab.packet.Ip4Prefix;
Jonathan Hart20d8e512014-10-16 11:05:52 -070025
Jonathan Hart41349e92015-02-09 14:14:02 -080026import java.util.Collection;
27
Jonathan Hart20d8e512014-10-16 11:05:52 -070028/**
29 * Class for handling the remote BGP Peer session.
30 */
31class TestBgpPeerChannelHandler extends SimpleChannelHandler {
32 static final long PEER_AS = 65001;
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080033 static final long PEER_AS4 = 0x12345678;
Jonathan Hart20d8e512014-10-16 11:05:52 -070034 static final int PEER_HOLDTIME = 120; // 120 seconds
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080035
36 final BgpSessionInfo localInfo = new BgpSessionInfo();
Jonathan Hart20d8e512014-10-16 11:05:52 -070037 ChannelHandlerContext savedCtx;
38
39 /**
40 * Constructor for given BGP ID.
41 *
42 * @param bgpId the BGP ID to use
Jonathan Hart20d8e512014-10-16 11:05:52 -070043 */
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080044 TestBgpPeerChannelHandler(Ip4Address bgpId) {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080045 this.localInfo.setBgpVersion(BgpConstants.BGP_VERSION);
46 this.localInfo.setBgpId(bgpId);
47 this.localInfo.setAsNumber(PEER_AS);
48 this.localInfo.setHoldtime(PEER_HOLDTIME);
Jonathan Hart20d8e512014-10-16 11:05:52 -070049 }
50
51 /**
52 * Closes the channel.
53 */
54 void closeChannel() {
55 savedCtx.getChannel().close();
56 }
57
58 @Override
59 public void channelConnected(ChannelHandlerContext ctx,
60 ChannelStateEvent channelEvent) {
61 this.savedCtx = ctx;
62 // Prepare and transmit BGP OPEN message
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080063 ChannelBuffer message = BgpOpen.prepareBgpOpen(localInfo);
Jonathan Hart20d8e512014-10-16 11:05:52 -070064 ctx.getChannel().write(message);
65
66 // Prepare and transmit BGP KEEPALIVE message
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080067 message = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hart20d8e512014-10-16 11:05:52 -070068 ctx.getChannel().write(message);
69 }
70
71 @Override
72 public void channelDisconnected(ChannelHandlerContext ctx,
73 ChannelStateEvent channelEvent) {
74 // Nothing to do
75 }
76
77 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -070078 * Prepares BGP UPDATE message.
79 *
80 * @param nextHopRouter the next-hop router address for the routes to add
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080081 * @param localPref the local preference for the routes to use
82 * @param multiExitDisc the MED value
83 * @param asPath the AS path for the routes to add
Jonathan Hart20d8e512014-10-16 11:05:52 -070084 * @param addedRoutes the routes to add
85 * @param withdrawnRoutes the routes to withdraw
86 * @return the message to transmit (BGP header included)
87 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080088 ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080089 long localPref,
90 long multiExitDisc,
91 BgpRouteEntry.AsPath asPath,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080092 Collection<Ip4Prefix> addedRoutes,
93 Collection<Ip4Prefix> withdrawnRoutes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -070094 int attrFlags;
95 ChannelBuffer message =
96 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
97 ChannelBuffer pathAttributes =
98 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
99
100 // Encode the Withdrawn Routes
101 ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
102 message.writeShort(encodedPrefixes.readableBytes());
103 message.writeBytes(encodedPrefixes);
104
105 // Encode the Path Attributes
106 // ORIGIN: IGP
107 attrFlags = 0x40; // Transitive flag
108 pathAttributes.writeByte(attrFlags);
109 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
110 pathAttributes.writeByte(1); // Data length
111 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800112
113 // AS_PATH: asPath
Jonathan Hart20d8e512014-10-16 11:05:52 -0700114 attrFlags = 0x40; // Transitive flag
115 pathAttributes.writeByte(attrFlags);
116 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800117 ChannelBuffer encodedAsPath = encodeAsPath(asPath);
118 pathAttributes.writeByte(encodedAsPath.readableBytes()); // Data length
119 pathAttributes.writeBytes(encodedAsPath);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700120 // NEXT_HOP: nextHopRouter
121 attrFlags = 0x40; // Transitive flag
122 pathAttributes.writeByte(attrFlags);
123 pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
124 pathAttributes.writeByte(4); // Data length
125 pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
126 // LOCAL_PREF: localPref
127 attrFlags = 0x40; // Transitive flag
128 pathAttributes.writeByte(attrFlags);
129 pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
130 pathAttributes.writeByte(4); // Data length
131 pathAttributes.writeInt((int) localPref); // Preference value
132 // MULTI_EXIT_DISC: multiExitDisc
133 attrFlags = 0x80; // Optional
134 // Non-Transitive flag
135 pathAttributes.writeByte(attrFlags);
136 pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
137 pathAttributes.writeByte(4); // Data length
138 pathAttributes.writeInt((int) multiExitDisc); // Preference value
139 // The NLRI prefixes
140 encodedPrefixes = encodePackedPrefixes(addedRoutes);
141
142 // Write the Path Attributes, beginning with its length
143 message.writeShort(pathAttributes.readableBytes());
144 message.writeBytes(pathAttributes);
145 message.writeBytes(encodedPrefixes);
146
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800147 return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE,
148 message);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700149 }
150
151 /**
152 * Encodes a collection of IPv4 network prefixes in a packed format.
153 * <p>
154 * The IPv4 prefixes are encoded in the form:
155 * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
156 * and Prefix is the IPv4 prefix (padded with trailing bits to the end
157 * of an octet).
158 *
159 * @param prefixes the prefixes to encode
160 * @return the buffer with the encoded prefixes
161 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800162 private ChannelBuffer encodePackedPrefixes(Collection<Ip4Prefix> prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700163 ChannelBuffer message =
164 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
165
166 // Write each of the prefixes
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800167 for (Ip4Prefix prefix : prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700168 int prefixBitlen = prefix.prefixLength();
169 int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
170 message.writeByte(prefixBitlen);
171
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800172 Ip4Address address = prefix.address();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700173 long value = address.toInt() & 0xffffffffL;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800174 for (int i = 0; i < Ip4Address.BYTE_LENGTH; i++) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700175 if (prefixBytelen-- == 0) {
176 break;
177 }
178 long nextByte =
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800179 (value >> ((Ip4Address.BYTE_LENGTH - i - 1) * 8)) & 0xff;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700180 message.writeByte((int) nextByte);
181 }
182 }
183
184 return message;
185 }
186
187 /**
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800188 * Encodes an AS path.
189 *
190 * @param asPath the AS path to encode
191 * @return the buffer with the encoded AS path
192 */
193 private ChannelBuffer encodeAsPath(BgpRouteEntry.AsPath asPath) {
194 ChannelBuffer message =
195 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
196
197 for (BgpRouteEntry.PathSegment pathSegment : asPath.getPathSegments()) {
198 message.writeByte(pathSegment.getType());
199 message.writeByte(pathSegment.getSegmentAsNumbers().size());
200 for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
201 message.writeShort(asNumber.intValue());
202 }
203 }
204
205 return message;
206 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700207}