/* * Copyright 2015-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.bgp; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.CountDownLatch; /** * Class to decode the message received. */ public class BgpPeerFrameDecoderTest extends FrameDecoder { static final byte OPEN_MSG_TYPE = 0x1; static final byte KEEPALIVE_MSG_TYPE = 0x4; static final byte UPDATE_MSG_TYPE = 0x2; static final byte NOTIFICATION_MSG_TYPE = 0x3; static final int MINIMUM_COMMON_HEADER_LENGTH = 19; static final int MINIMUM_OPEN_MSG_LENGTH = 29; static final int MINIMUM_HEADER_MARKER_LENGTH = 16; static final int HEADER_AND_MSG_LEN = 18; protected static final Logger log = LoggerFactory .getLogger(BgpPeerFrameDecoderTest.class); final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1); final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1); final CountDownLatch receivedNotificationMessageLatch = new CountDownLatch(1); @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer cb) throws Exception { if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { log.debug("Error: Packet length is less then minimum length"); return null; } byte[] marker = new byte[MINIMUM_HEADER_MARKER_LENGTH]; cb.readBytes(marker); for (int i = 0; i < marker.length; i++) { if (marker[i] != (byte) 0xff) { log.debug("Error: Marker must be set all ones"); ctx.getChannel().close(); return null; } } short length = cb.readShort(); if (length < MINIMUM_COMMON_HEADER_LENGTH) { log.debug("Error: Bad message length"); ctx.getChannel().close(); return null; } if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) { log.debug("Error: Bad message length"); ctx.getChannel().close(); return null; } byte type = cb.readByte(); int len = length - MINIMUM_COMMON_HEADER_LENGTH; ChannelBuffer message = cb.readBytes(len); switch (type) { case OPEN_MSG_TYPE: processBgpOpen(ctx, message); break; case UPDATE_MSG_TYPE: break; case NOTIFICATION_MSG_TYPE: processBgpNotification(ctx, message); break; case KEEPALIVE_MSG_TYPE: processBgpKeepalive(ctx, message); break; default: ctx.getChannel().close(); return null; } return null; } /** * Processes BGP open message. * * @param ctx Channel handler context * @param message open message */ private void processBgpOpen(ChannelHandlerContext ctx, ChannelBuffer message) { int minLength = MINIMUM_OPEN_MSG_LENGTH - MINIMUM_COMMON_HEADER_LENGTH; if (message.readableBytes() < minLength) { log.debug("Error: Bad message length"); ctx.getChannel().close(); return; } message.readByte(); // read version message.readShort(); // read AS number message.readShort(); // read Hold timer message.readInt(); // read BGP Identifier // Optional Parameters int optParamLen = message.readUnsignedByte(); if (message.readableBytes() < optParamLen) { log.debug("Error: Bad message length"); ctx.getChannel().close(); return; } message.readBytes(optParamLen); // Open message received receivedOpenMessageLatch.countDown(); } /** * Processes BGP keepalive message. * * @param ctx Channel handler context * @param message keepalive message */ private void processBgpKeepalive(ChannelHandlerContext ctx, ChannelBuffer message) { // Keepalive message received receivedKeepaliveMessageLatch.countDown(); } /** * Processes BGP notification message. * * @param ctx Channel handler context * @param message notification message */ private void processBgpNotification(ChannelHandlerContext ctx, ChannelBuffer message) { byte[] data; message.readByte(); //read error code message.readByte(); // read error sub code if (message.readableBytes() > 0) { data = new byte[message.readableBytes()]; message.readBytes(data, 0, message.readableBytes()); } // Notification message received receivedNotificationMessageLatch.countDown(); } }