blob: 4cd2813b4e56ba4ebd0c53185ae260f31e9fd74a [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-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 Hart41349e92015-02-09 14:14:02 -080016package org.onosproject.routing.bgp;
Jonathan Hartab63aac2014-10-16 08:52:55 -070017
18import org.jboss.netty.buffer.ChannelBuffer;
19import org.jboss.netty.buffer.ChannelBuffers;
20import org.jboss.netty.channel.Channel;
21import org.jboss.netty.channel.ChannelHandlerContext;
22import org.jboss.netty.handler.codec.frame.FrameDecoder;
Jonathan Hartab63aac2014-10-16 08:52:55 -070023import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26/**
27 * Class for handling the decoding of the BGP messages.
28 */
29class BgpFrameDecoder extends FrameDecoder {
30 private static final Logger log =
31 LoggerFactory.getLogger(BgpFrameDecoder.class);
32
33 private final BgpSession bgpSession;
34
35 /**
36 * Constructor for a given BGP Session.
37 *
38 * @param bgpSession the BGP session state to use.
39 */
40 BgpFrameDecoder(BgpSession bgpSession) {
41 this.bgpSession = bgpSession;
42 }
43
44 @Override
45 protected Object decode(ChannelHandlerContext ctx,
46 Channel channel,
47 ChannelBuffer buf) throws Exception {
48 //
49 // NOTE: If we close the channel during the decoding, we might still
50 // see some incoming messages while the channel closing is completed.
51 //
52 if (bgpSession.isClosed()) {
53 return null;
54 }
55
56 log.trace("BGP Peer: decode(): remoteAddr = {} localAddr = {} " +
57 "messageSize = {}",
58 ctx.getChannel().getRemoteAddress(),
59 ctx.getChannel().getLocalAddress(),
60 buf.readableBytes());
61
62 // Test for minimum length of the BGP message
63 if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
64 // No enough data received
65 return null;
66 }
67
68 //
69 // Mark the current buffer position in case we haven't received
70 // the whole message.
71 //
72 buf.markReaderIndex();
73
74 //
75 // Read and check the BGP message Marker field: it must be all ones
76 // (See RFC 4271, Section 4.1)
77 //
78 byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
79 buf.readBytes(marker);
80 for (int i = 0; i < marker.length; i++) {
81 if (marker[i] != (byte) 0xff) {
82 log.debug("BGP RX Error: invalid marker {} at position {}",
83 marker[i], i);
84 //
85 // ERROR: Connection Not Synchronized
86 //
87 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -080088 int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
Jonathan Hartab63aac2014-10-16 08:52:55 -070089 int errorSubcode =
Jonathan Hart41349e92015-02-09 14:14:02 -080090 BgpConstants.Notifications.MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
Jonathan Hartab63aac2014-10-16 08:52:55 -070091 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -080092 BgpNotification.prepareBgpNotification(errorCode,
93 errorSubcode,
94 null);
Jonathan Hartab63aac2014-10-16 08:52:55 -070095 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -080096 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -070097 return null;
98 }
99 }
100
101 //
102 // Read and check the BGP message Length field
103 //
104 int length = buf.readUnsignedShort();
105 if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
106 (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
107 log.debug("BGP RX Error: invalid Length field {}. " +
108 "Must be between {} and {}",
109 length,
110 BgpConstants.BGP_HEADER_LENGTH,
111 BgpConstants.BGP_MESSAGE_MAX_LENGTH);
112 //
113 // ERROR: Bad Message Length
114 //
115 // Send NOTIFICATION and close the connection
116 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800117 BgpNotification.prepareBgpNotificationBadMessageLength(length);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700118 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -0800119 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700120 return null;
121 }
122
123 //
124 // Test whether the rest of the message is received:
125 // So far we have read the Marker (16 octets) and the
126 // Length (2 octets) fields.
127 //
128 int remainingMessageLen =
129 length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
130 if (buf.readableBytes() < remainingMessageLen) {
131 // No enough data received
132 buf.resetReaderIndex();
133 return null;
134 }
135
136 //
137 // Read the BGP message Type field, and process based on that type
138 //
139 int type = buf.readUnsignedByte();
140 remainingMessageLen--; // Adjust after reading the type
141 ChannelBuffer message = buf.readBytes(remainingMessageLen);
142
143 //
144 // Process the remaining of the message based on the message type
145 //
146 switch (type) {
147 case BgpConstants.BGP_TYPE_OPEN:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800148 BgpOpen.processBgpOpen(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700149 break;
150 case BgpConstants.BGP_TYPE_UPDATE:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800151 BgpUpdate.processBgpUpdate(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700152 break;
153 case BgpConstants.BGP_TYPE_NOTIFICATION:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800154 BgpNotification.processBgpNotification(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700155 break;
156 case BgpConstants.BGP_TYPE_KEEPALIVE:
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800157 BgpKeepalive.processBgpKeepalive(bgpSession, ctx, message);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700158 break;
159 default:
160 //
161 // ERROR: Bad Message Type
162 //
163 // Send NOTIFICATION and close the connection
Jonathan Hart41349e92015-02-09 14:14:02 -0800164 int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
165 int errorSubcode = BgpConstants.Notifications.MessageHeaderError.BAD_MESSAGE_TYPE;
Jonathan Hartab63aac2014-10-16 08:52:55 -0700166 ChannelBuffer data = ChannelBuffers.buffer(1);
167 data.writeByte(type);
168 ChannelBuffer txMessage =
Pavlin Radoslavov80f3e182014-12-15 10:46:18 -0800169 BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
170 data);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700171 ctx.getChannel().write(txMessage);
Jonathan Hartff071a22014-12-03 12:10:00 -0800172 bgpSession.closeSession(ctx);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700173 return null;
174 }
175 return null;
176 }
177}