blob: 5ce646242f1264631c2c974eb886084d2a914a56 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Jonathan Hartf4bd0482017-01-27 15:11:18 -08002 * Copyright 2017-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 Hartf4bd0482017-01-27 15:11:18 -080016
Jonathan Hart41349e92015-02-09 14:14:02 -080017package org.onosproject.routing.bgp;
Jonathan Hart20d8e512014-10-16 11:05:52 -070018
19import org.jboss.netty.buffer.ChannelBuffer;
20import org.jboss.netty.buffer.ChannelBuffers;
21import org.jboss.netty.channel.ChannelHandlerContext;
22import org.jboss.netty.channel.ChannelStateEvent;
23import org.jboss.netty.channel.SimpleChannelHandler;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080024import org.onlab.packet.Ip4Address;
25import org.onlab.packet.Ip4Prefix;
Jonathan Hart20d8e512014-10-16 11:05:52 -070026
Jonathan Hart41349e92015-02-09 14:14:02 -080027import java.util.Collection;
28
Jonathan Hart20d8e512014-10-16 11:05:52 -070029/**
30 * Class for handling the remote BGP Peer session.
31 */
32class TestBgpPeerChannelHandler extends SimpleChannelHandler {
33 static final long PEER_AS = 65001;
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080034 static final long PEER_AS4 = 0x12345678;
Jonathan Hart20d8e512014-10-16 11:05:52 -070035 static final int PEER_HOLDTIME = 120; // 120 seconds
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080036
37 final BgpSessionInfo localInfo = new BgpSessionInfo();
Jonathan Hart20d8e512014-10-16 11:05:52 -070038 ChannelHandlerContext savedCtx;
39
40 /**
41 * Constructor for given BGP ID.
42 *
43 * @param bgpId the BGP ID to use
Jonathan Hart20d8e512014-10-16 11:05:52 -070044 */
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080045 TestBgpPeerChannelHandler(Ip4Address bgpId) {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080046 this.localInfo.setBgpVersion(BgpConstants.BGP_VERSION);
47 this.localInfo.setBgpId(bgpId);
48 this.localInfo.setAsNumber(PEER_AS);
49 this.localInfo.setHoldtime(PEER_HOLDTIME);
Jonathan Hart20d8e512014-10-16 11:05:52 -070050 }
51
52 /**
53 * Closes the channel.
54 */
55 void closeChannel() {
56 savedCtx.getChannel().close();
57 }
58
59 @Override
60 public void channelConnected(ChannelHandlerContext ctx,
61 ChannelStateEvent channelEvent) {
62 this.savedCtx = ctx;
63 // Prepare and transmit BGP OPEN message
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080064 ChannelBuffer message = BgpOpen.prepareBgpOpen(localInfo);
Jonathan Hart20d8e512014-10-16 11:05:52 -070065 ctx.getChannel().write(message);
66
67 // Prepare and transmit BGP KEEPALIVE message
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -080068 message = BgpKeepalive.prepareBgpKeepalive();
Jonathan Hart20d8e512014-10-16 11:05:52 -070069 ctx.getChannel().write(message);
70 }
71
72 @Override
73 public void channelDisconnected(ChannelHandlerContext ctx,
74 ChannelStateEvent channelEvent) {
75 // Nothing to do
76 }
77
78 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -070079 * Prepares BGP UPDATE message.
80 *
81 * @param nextHopRouter the next-hop router address for the routes to add
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080082 * @param localPref the local preference for the routes to use
83 * @param multiExitDisc the MED value
84 * @param asPath the AS path for the routes to add
Jonathan Hart20d8e512014-10-16 11:05:52 -070085 * @param addedRoutes the routes to add
86 * @param withdrawnRoutes the routes to withdraw
87 * @return the message to transmit (BGP header included)
88 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080089 ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080090 long localPref,
91 long multiExitDisc,
92 BgpRouteEntry.AsPath asPath,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080093 Collection<Ip4Prefix> addedRoutes,
94 Collection<Ip4Prefix> withdrawnRoutes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -070095 int attrFlags;
96 ChannelBuffer message =
97 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
98 ChannelBuffer pathAttributes =
99 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
100
101 // Encode the Withdrawn Routes
102 ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
103 message.writeShort(encodedPrefixes.readableBytes());
104 message.writeBytes(encodedPrefixes);
105
106 // Encode the Path Attributes
107 // ORIGIN: IGP
108 attrFlags = 0x40; // Transitive flag
109 pathAttributes.writeByte(attrFlags);
110 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
111 pathAttributes.writeByte(1); // Data length
112 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800113
114 // AS_PATH: asPath
Jonathan Hart20d8e512014-10-16 11:05:52 -0700115 attrFlags = 0x40; // Transitive flag
116 pathAttributes.writeByte(attrFlags);
117 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800118 ChannelBuffer encodedAsPath = encodeAsPath(asPath);
119 pathAttributes.writeByte(encodedAsPath.readableBytes()); // Data length
120 pathAttributes.writeBytes(encodedAsPath);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700121 // NEXT_HOP: nextHopRouter
122 attrFlags = 0x40; // Transitive flag
123 pathAttributes.writeByte(attrFlags);
124 pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
125 pathAttributes.writeByte(4); // Data length
126 pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
127 // LOCAL_PREF: localPref
128 attrFlags = 0x40; // Transitive flag
129 pathAttributes.writeByte(attrFlags);
130 pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
131 pathAttributes.writeByte(4); // Data length
132 pathAttributes.writeInt((int) localPref); // Preference value
133 // MULTI_EXIT_DISC: multiExitDisc
134 attrFlags = 0x80; // Optional
135 // Non-Transitive flag
136 pathAttributes.writeByte(attrFlags);
137 pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
138 pathAttributes.writeByte(4); // Data length
139 pathAttributes.writeInt((int) multiExitDisc); // Preference value
140 // The NLRI prefixes
141 encodedPrefixes = encodePackedPrefixes(addedRoutes);
142
143 // Write the Path Attributes, beginning with its length
144 message.writeShort(pathAttributes.readableBytes());
145 message.writeBytes(pathAttributes);
146 message.writeBytes(encodedPrefixes);
147
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800148 return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE,
149 message);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700150 }
151
152 /**
153 * Encodes a collection of IPv4 network prefixes in a packed format.
154 * <p>
155 * The IPv4 prefixes are encoded in the form:
156 * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
157 * and Prefix is the IPv4 prefix (padded with trailing bits to the end
158 * of an octet).
159 *
160 * @param prefixes the prefixes to encode
161 * @return the buffer with the encoded prefixes
162 */
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800163 private ChannelBuffer encodePackedPrefixes(Collection<Ip4Prefix> prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700164 ChannelBuffer message =
165 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
166
167 // Write each of the prefixes
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800168 for (Ip4Prefix prefix : prefixes) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700169 int prefixBitlen = prefix.prefixLength();
170 int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
171 message.writeByte(prefixBitlen);
172
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800173 Ip4Address address = prefix.address();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700174 long value = address.toInt() & 0xffffffffL;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800175 for (int i = 0; i < Ip4Address.BYTE_LENGTH; i++) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700176 if (prefixBytelen-- == 0) {
177 break;
178 }
179 long nextByte =
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800180 (value >> ((Ip4Address.BYTE_LENGTH - i - 1) * 8)) & 0xff;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700181 message.writeByte((int) nextByte);
182 }
183 }
184
185 return message;
186 }
187
188 /**
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800189 * Encodes an AS path.
190 *
191 * @param asPath the AS path to encode
192 * @return the buffer with the encoded AS path
193 */
194 private ChannelBuffer encodeAsPath(BgpRouteEntry.AsPath asPath) {
195 ChannelBuffer message =
196 ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
197
198 for (BgpRouteEntry.PathSegment pathSegment : asPath.getPathSegments()) {
199 message.writeByte(pathSegment.getType());
200 message.writeByte(pathSegment.getSegmentAsNumbers().size());
201 for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
202 message.writeShort(asNumber.intValue());
203 }
204 }
205
206 return message;
207 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700208}