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