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