blob: 222d11f69335ff353cc764695241c0e55dc555a5 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Jonathan Hart20d8e512014-10-16 11:05:52 -070019package org.onlab.onos.sdnip.bgp;
20
21import java.util.concurrent.CountDownLatch;
22
23import org.jboss.netty.buffer.ChannelBuffer;
24import org.jboss.netty.channel.Channel;
25import org.jboss.netty.channel.ChannelHandlerContext;
26import org.jboss.netty.handler.codec.frame.FrameDecoder;
27import org.onlab.packet.IpAddress;
28
29/**
30 * Class for handling the decoding of the BGP messages at the remote
31 * BGP peer session.
32 */
33class TestBgpPeerFrameDecoder extends FrameDecoder {
34 int remoteBgpVersion; // 1 octet
35 long remoteAs; // 2 octets
36 long remoteHoldtime; // 2 octets
37 IpAddress remoteBgpIdentifier; // 4 octets -> IPv4 address
38
39 final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
40 final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
41
42 @Override
43 protected Object decode(ChannelHandlerContext ctx,
44 Channel channel,
45 ChannelBuffer buf) throws Exception {
46 // Test for minimum length of the BGP message
47 if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
48 // No enough data received
49 return null;
50 }
51
52 //
53 // Mark the current buffer position in case we haven't received
54 // the whole message.
55 //
56 buf.markReaderIndex();
57
58 //
59 // Read and check the BGP message Marker field: it must be all ones
60 //
61 byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
62 buf.readBytes(marker);
63 for (int i = 0; i < marker.length; i++) {
64 if (marker[i] != (byte) 0xff) {
65 // ERROR: Connection Not Synchronized. Close the channel.
66 ctx.getChannel().close();
67 return null;
68 }
69 }
70
71 //
72 // Read and check the BGP message Length field
73 //
74 int length = buf.readUnsignedShort();
75 if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
76 (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
77 // ERROR: Bad Message Length. Close the channel.
78 ctx.getChannel().close();
79 return null;
80 }
81
82 //
83 // Test whether the rest of the message is received:
84 // So far we have read the Marker (16 octets) and the
85 // Length (2 octets) fields.
86 //
87 int remainingMessageLen =
88 length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
89 if (buf.readableBytes() < remainingMessageLen) {
90 // No enough data received
91 buf.resetReaderIndex();
92 return null;
93 }
94
95 //
96 // Read the BGP message Type field, and process based on that type
97 //
98 int type = buf.readUnsignedByte();
99 remainingMessageLen--; // Adjust after reading the type
100 ChannelBuffer message = buf.readBytes(remainingMessageLen);
101
102 //
103 // Process the remaining of the message based on the message type
104 //
105 switch (type) {
106 case BgpConstants.BGP_TYPE_OPEN:
107 processBgpOpen(ctx, message);
108 break;
109 case BgpConstants.BGP_TYPE_UPDATE:
110 // NOTE: Not used as part of the test, because ONOS does not
111 // originate UPDATE messages.
112 break;
113 case BgpConstants.BGP_TYPE_NOTIFICATION:
114 // NOTE: Not used as part of the testing (yet)
115 break;
116 case BgpConstants.BGP_TYPE_KEEPALIVE:
117 processBgpKeepalive(ctx, message);
118 break;
119 default:
120 // ERROR: Bad Message Type. Close the channel.
121 ctx.getChannel().close();
122 return null;
123 }
124
125 return null;
126 }
127
128 /**
129 * Processes BGP OPEN message.
130 *
131 * @param ctx the Channel Handler Context.
132 * @param message the message to process.
133 */
134 private void processBgpOpen(ChannelHandlerContext ctx,
135 ChannelBuffer message) {
136 int minLength =
137 BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
138 if (message.readableBytes() < minLength) {
139 // ERROR: Bad Message Length. Close the channel.
140 ctx.getChannel().close();
141 return;
142 }
143
144 //
145 // Parse the OPEN message
146 //
147 remoteBgpVersion = message.readUnsignedByte();
148 remoteAs = message.readUnsignedShort();
149 remoteHoldtime = message.readUnsignedShort();
150 remoteBgpIdentifier = IpAddress.valueOf((int) message.readUnsignedInt());
151 // Optional Parameters
152 int optParamLen = message.readUnsignedByte();
153 if (message.readableBytes() < optParamLen) {
154 // ERROR: Bad Message Length. Close the channel.
155 ctx.getChannel().close();
156 return;
157 }
158 message.readBytes(optParamLen); // NOTE: data ignored
159
160 // BGP OPEN message successfully received
161 receivedOpenMessageLatch.countDown();
162 }
163
164 /**
165 * Processes BGP KEEPALIVE message.
166 *
167 * @param ctx the Channel Handler Context.
168 * @param message the message to process.
169 */
170 private void processBgpKeepalive(ChannelHandlerContext ctx,
171 ChannelBuffer message) {
172 if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
173 BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
174 // ERROR: Bad Message Length. Close the channel.
175 ctx.getChannel().close();
176 return;
177 }
178 // BGP KEEPALIVE message successfully received
179 receivedKeepaliveMessageLatch.countDown();
180 }
181}