blob: d6c9d30b8dfdebeb6be035ac9296f255babb0b48 [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 Hartab63aac2014-10-16 08:52:55 -070018
19import org.jboss.netty.buffer.ChannelBuffer;
20import org.jboss.netty.buffer.ChannelBuffers;
21import org.jboss.netty.channel.Channel;
22import org.jboss.netty.channel.ChannelHandlerContext;
23import org.jboss.netty.handler.codec.frame.FrameDecoder;
Jonathan Hartab63aac2014-10-16 08:52:55 -070024import org.slf4j.Logger;
25import org.slf4j.LoggerFactory;
26
27/**
28 * Class for handling the decoding of the BGP messages.
29 */
30class BgpFrameDecoder extends FrameDecoder {
31 private static final Logger log =
32 LoggerFactory.getLogger(BgpFrameDecoder.class);
33
34 private final BgpSession bgpSession;
35
36 /**
37 * Constructor for a given BGP Session.
38 *
39 * @param bgpSession the BGP session state to use.
40 */
41 BgpFrameDecoder(BgpSession bgpSession) {
42 this.bgpSession = bgpSession;
43 }
44
45 @Override
46 protected Object decode(ChannelHandlerContext ctx,
47 Channel channel,
48 ChannelBuffer buf) throws Exception {
49 //
50 // NOTE: If we close the channel during the decoding, we might still
51 // see some incoming messages while the channel closing is completed.
52 //
53 if (bgpSession.isClosed()) {
54 return null;
55 }
56
57 log.trace("BGP Peer: decode(): remoteAddr = {} localAddr = {} " +
58 "messageSize = {}",
59 ctx.getChannel().getRemoteAddress(),
60 ctx.getChannel().getLocalAddress(),
61 buf.readableBytes());
62
63 // Test for minimum length of the BGP message
64 if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
65 // No enough data received
66 return null;
67 }
68
69 //
70 // Mark the current buffer position in case we haven't received
71 // the whole message.
72 //
73 buf.markReaderIndex();
74
75 //
76 // Read and check the BGP message Marker field: it must be all ones
77 // (See RFC 4271, Section 4.1)
78 //
79 byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
80 buf.readBytes(marker);
81 for (int i = 0; i < marker.length; i++) {
82 if (marker[i] != (byte) 0xff) {
83 log.debug("BGP RX Error: invalid marker {} at position {}",
84 marker[i], i);
85 //
86 // ERROR: Connection Not Synchronized
87 //
88 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -080089 int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
Jonathan Hartab63aac2014-10-16 08:52:55 -070090 int errorSubcode =
Jonathan Hart41349e92015-02-09 14:14:02 -080091 BgpConstants.Notifications.MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
Jonathan Hartab63aac2014-10-16 08:52:55 -070092 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080093 BgpNotification.prepareBgpNotification(errorCode,
94 errorSubcode,
95 null);
Jonathan Hartab63aac2014-10-16 08:52:55 -070096 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -080097 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -070098 return null;
99 }
100 }
101
102 //
103 // Read and check the BGP message Length field
104 //
105 int length = buf.readUnsignedShort();
106 if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
107 (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
108 log.debug("BGP RX Error: invalid Length field {}. " +
109 "Must be between {} and {}",
110 length,
111 BgpConstants.BGP_HEADER_LENGTH,
112 BgpConstants.BGP_MESSAGE_MAX_LENGTH);
113 //
114 // ERROR: Bad Message Length
115 //
116 // Send NOTIFICATION and close the connection
117 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800118 BgpNotification.prepareBgpNotificationBadMessageLength(length);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700119 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -0800120 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700121 return null;
122 }
123
124 //
125 // Test whether the rest of the message is received:
126 // So far we have read the Marker (16 octets) and the
127 // Length (2 octets) fields.
128 //
129 int remainingMessageLen =
130 length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
131 if (buf.readableBytes() < remainingMessageLen) {
132 // No enough data received
133 buf.resetReaderIndex();
134 return null;
135 }
136
137 //
138 // Read the BGP message Type field, and process based on that type
139 //
140 int type = buf.readUnsignedByte();
141 remainingMessageLen--; // Adjust after reading the type
142 ChannelBuffer message = buf.readBytes(remainingMessageLen);
143
144 //
145 // Process the remaining of the message based on the message type
146 //
147 switch (type) {
148 case BgpConstants.BGP_TYPE_OPEN:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800149 BgpOpen.processBgpOpen(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700150 break;
151 case BgpConstants.BGP_TYPE_UPDATE:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800152 BgpUpdate.processBgpUpdate(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700153 break;
154 case BgpConstants.BGP_TYPE_NOTIFICATION:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800155 BgpNotification.processBgpNotification(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700156 break;
157 case BgpConstants.BGP_TYPE_KEEPALIVE:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800158 BgpKeepalive.processBgpKeepalive(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700159 break;
160 default:
161 //
162 // ERROR: Bad Message Type
163 //
164 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -0800165 int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
166 int errorSubcode = BgpConstants.Notifications.MessageHeaderError.BAD_MESSAGE_TYPE;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700167 ChannelBuffer data = ChannelBuffers.buffer(1);
168 data.writeByte(type);
169 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800170 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
171 data);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700172 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -0800173 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700174 return null;
175 }
176 return null;
177 }
178}