blob: 7a69a5b9cc3372365a35836c95ed1b9a78a3ace4 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* 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.isis.controller.impl;
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.onlab.packet.MacAddress;
import org.onosproject.isis.controller.IsisMessage;
import org.onosproject.isis.io.isispacket.IsisMessageReader;
import org.onosproject.isis.io.util.IsisConstants;
import org.onosproject.isis.io.util.IsisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import java.util.List;
/**
* Decodes an ISIS message from a Channel, for use in a netty pipeline.
*/
public class IsisMessageDecoder extends FrameDecoder {
private static final Logger log = LoggerFactory.getLogger(IsisMessageDecoder.class);
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
log.debug("IsisMessageDecoder::Message received <:> length {}", buffer.readableBytes());
if (!channel.isConnected()) {
log.info("Channel is not connected.");
return null;
}
IsisMessageReader messageReader = new IsisMessageReader();
List<IsisMessage> isisMessageList = new LinkedList<>();
int dataLength = buffer.readableBytes();
while (buffer.readableBytes() >= IsisConstants.MINIMUM_FRAME_LEN) {
ChannelBuffer payload = buffer.readBytes(IsisConstants.MINIMUM_FRAME_LEN);
ChannelBuffer ethernetHeader = payload.readBytes(IsisUtil.ETHER_HEADER_LEN);
//Read the Source MAC address from ethernet header at the 6th position
MacAddress sourceMac = getSourceMac(ethernetHeader);
//Strip 17 byte ethernet header and get the ISIS data buffer
ChannelBuffer isisDataBuffer = payload.readBytes(payload.readableBytes());
int readableBytes = isisDataBuffer.readableBytes();
IsisMessage message = messageReader.readFromBuffer(isisDataBuffer);
//Last 7 bytes is metadata. ie. interface MAC address and interface index.
if (message != null) {
if (isisDataBuffer.readableBytes() >= IsisConstants.METADATA_LEN) {
//Sets the source MAC
message.setSourceMac(sourceMac);
isisDataBuffer.readerIndex(readableBytes - IsisConstants.METADATA_LEN);
log.debug("IsisMessageDecoder::Reading metadata <:> length {}", isisDataBuffer.readableBytes());
byte[] macBytes = new byte[IsisUtil.SIX_BYTES];
isisDataBuffer.readBytes(macBytes, 0, IsisUtil.SIX_BYTES);
MacAddress macAddress = MacAddress.valueOf(macBytes);
int interfaceIndex = isisDataBuffer.readByte();
message.setInterfaceMac(macAddress);
message.setInterfaceIndex(interfaceIndex);
}
isisMessageList.add(message);
}
}
return (!isisMessageList.isEmpty()) ? isisMessageList : null;
}
/**
* Gets the source MAC address from the ethernet header.
*
* @param ethHeader ethernet header bytes
* @return MAC address of the source router
*/
private MacAddress getSourceMac(ChannelBuffer ethHeader) {
//Source MAC is at position 6 to 11 (6 bytes)
ethHeader.skipBytes(IsisUtil.SIX_BYTES);
MacAddress sourceMac = MacAddress.valueOf(ethHeader.readBytes(IsisUtil.SIX_BYTES).array());
return sourceMac;
}
}