blob: b4ff40d2319f3e29f26ba99bb48f16052477bd09 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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.channel.Channel;
20import org.jboss.netty.channel.ChannelHandlerContext;
21import org.jboss.netty.handler.codec.frame.FrameDecoder;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080022import org.onlab.packet.Ip4Address;
Jonathan Hart20d8e512014-10-16 11:05:52 -070023
Jonathan Hart41349e92015-02-09 14:14:02 -080024import java.util.concurrent.CountDownLatch;
25
Jonathan Hart20d8e512014-10-16 11:05:52 -070026/**
27 * Class for handling the decoding of the BGP messages at the remote
28 * BGP peer session.
29 */
30class TestBgpPeerFrameDecoder extends FrameDecoder {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080031 final BgpSessionInfo remoteInfo = new BgpSessionInfo();
Jonathan Hart20d8e512014-10-16 11:05:52 -070032
33 final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
34 final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
35
36 @Override
37 protected Object decode(ChannelHandlerContext ctx,
38 Channel channel,
39 ChannelBuffer buf) throws Exception {
40 // Test for minimum length of the BGP message
41 if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
42 // No enough data received
43 return null;
44 }
45
46 //
47 // Mark the current buffer position in case we haven't received
48 // the whole message.
49 //
50 buf.markReaderIndex();
51
52 //
53 // Read and check the BGP message Marker field: it must be all ones
54 //
55 byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
56 buf.readBytes(marker);
57 for (int i = 0; i < marker.length; i++) {
58 if (marker[i] != (byte) 0xff) {
59 // ERROR: Connection Not Synchronized. Close the channel.
60 ctx.getChannel().close();
61 return null;
62 }
63 }
64
65 //
66 // Read and check the BGP message Length field
67 //
68 int length = buf.readUnsignedShort();
69 if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
70 (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
71 // ERROR: Bad Message Length. Close the channel.
72 ctx.getChannel().close();
73 return null;
74 }
75
76 //
77 // Test whether the rest of the message is received:
78 // So far we have read the Marker (16 octets) and the
79 // Length (2 octets) fields.
80 //
81 int remainingMessageLen =
82 length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
83 if (buf.readableBytes() < remainingMessageLen) {
84 // No enough data received
85 buf.resetReaderIndex();
86 return null;
87 }
88
89 //
90 // Read the BGP message Type field, and process based on that type
91 //
92 int type = buf.readUnsignedByte();
93 remainingMessageLen--; // Adjust after reading the type
94 ChannelBuffer message = buf.readBytes(remainingMessageLen);
95
96 //
97 // Process the remaining of the message based on the message type
98 //
99 switch (type) {
100 case BgpConstants.BGP_TYPE_OPEN:
101 processBgpOpen(ctx, message);
102 break;
103 case BgpConstants.BGP_TYPE_UPDATE:
104 // NOTE: Not used as part of the test, because ONOS does not
105 // originate UPDATE messages.
106 break;
107 case BgpConstants.BGP_TYPE_NOTIFICATION:
108 // NOTE: Not used as part of the testing (yet)
109 break;
110 case BgpConstants.BGP_TYPE_KEEPALIVE:
111 processBgpKeepalive(ctx, message);
112 break;
113 default:
114 // ERROR: Bad Message Type. Close the channel.
115 ctx.getChannel().close();
116 return null;
117 }
118
119 return null;
120 }
121
122 /**
123 * Processes BGP OPEN message.
124 *
125 * @param ctx the Channel Handler Context.
126 * @param message the message to process.
127 */
128 private void processBgpOpen(ChannelHandlerContext ctx,
129 ChannelBuffer message) {
130 int minLength =
131 BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
132 if (message.readableBytes() < minLength) {
133 // ERROR: Bad Message Length. Close the channel.
134 ctx.getChannel().close();
135 return;
136 }
137
138 //
139 // Parse the OPEN message
140 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800141 remoteInfo.setBgpVersion(message.readUnsignedByte());
142 remoteInfo.setAsNumber(message.readUnsignedShort());
143 remoteInfo.setHoldtime(message.readUnsignedShort());
144 remoteInfo.setBgpId(Ip4Address.valueOf((int) message.readUnsignedInt()));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700145 // Optional Parameters
146 int optParamLen = message.readUnsignedByte();
147 if (message.readableBytes() < optParamLen) {
148 // ERROR: Bad Message Length. Close the channel.
149 ctx.getChannel().close();
150 return;
151 }
152 message.readBytes(optParamLen); // NOTE: data ignored
153
154 // BGP OPEN message successfully received
155 receivedOpenMessageLatch.countDown();
156 }
157
158 /**
159 * Processes BGP KEEPALIVE message.
160 *
161 * @param ctx the Channel Handler Context.
162 * @param message the message to process.
163 */
164 private void processBgpKeepalive(ChannelHandlerContext ctx,
165 ChannelBuffer message) {
166 if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
167 BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
168 // ERROR: Bad Message Length. Close the channel.
169 ctx.getChannel().close();
170 return;
171 }
172 // BGP KEEPALIVE message successfully received
173 receivedKeepaliveMessageLatch.countDown();
174 }
175}