blob: 1c0ae167f521350ad1764c8e58eb5782dc1cbd2a [file] [log] [blame]
/*
* Copyright 2016-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.ospf.protocol.ospfpacket.types;
import com.google.common.base.MoreObjects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.exceptions.OspfErrorType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.util.OspfPacketType;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* Defines an OSPF Hello Message, and the fields and methods to access it.
* Hello packets are OSPF packet type 1. These packets are sent
* periodically on all interfaces in order to establish and
* maintain neighbor relationships.
*/
public class HelloPacket extends OspfPacketHeader {
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version # | 1 | Packet length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Router ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Area ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | AuType |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Authentication |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Authentication |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Network Mask |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| HelloInterval | Options | Rtr Pri |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RouterDeadInterval |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Designated Router |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Backup Designated Router |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Neighbor |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ... |
Hello Message Format
REFERENCE : RFC 2328
*/
private static final Logger log = LoggerFactory.getLogger(HelloPacket.class);
private Ip4Address networkMask;
private int options;
private int helloInterval;
private int routerPriority;
private int routerDeadInterval;
private Ip4Address bdr;
private Ip4Address dr;
private List<Ip4Address> neighborAddress = new ArrayList<>();
/**
* Creates an instance of Hello packet.
*/
public HelloPacket() {
}
/**
* Creates an instance of Hello packet.
*
* @param ospfHeader OSPF header instance.
*/
public HelloPacket(OspfPacketHeader ospfHeader) {
populateHeader(ospfHeader);
}
/**
* Gets network mask.
*
* @return network mask
*/
public Ip4Address networkMask() {
return networkMask;
}
/**
* Sets network mask.
*
* @param networkMask network mask
*/
public void setNetworkMask(Ip4Address networkMask) {
this.networkMask = networkMask;
}
/**
* Gets BDRs IP address.
*
* @return BDRs IP address
*/
public Ip4Address bdr() {
return bdr;
}
/**
* Sets BDR IP address.
*
* @param bdr BDR IP address
*/
public void setBdr(Ip4Address bdr) {
this.bdr = bdr;
}
/**
* Gets DRs IP address.
*
* @return DRs IP address
*/
public Ip4Address dr() {
return dr;
}
/**
* Sets DRs IP address.
*
* @param dr DRs IP address
*/
public void setDr(Ip4Address dr) {
this.dr = dr;
}
/**
* Adds neighbor to map.
*
* @param neighborID neighbors id
*/
public void addNeighbor(Ip4Address neighborID) {
if (!neighborAddress.contains(neighborID)) {
neighborAddress.add(neighborID);
}
}
/**
* Checks neighbor is in map or not.
*
* @param neighborID neighbors id
* @return true if neighbor exist else false
*/
public boolean containsNeighbour(Ip4Address neighborID) {
return (neighborAddress.contains(neighborID)) ? true : false;
}
/**
* Gets options value.
*
* @return options value
*/
public int options() {
return options;
}
/**
* Sets options value.
*
* @param options options value
*/
public void setOptions(int options) {
this.options = options;
}
/**
* Gets router priority.
*
* @return routerPriority
*/
public int routerPriority() {
return routerPriority;
}
/**
* Sets router priority.
*
* @param routerPriority router priority
*/
public void setRouterPriority(int routerPriority) {
this.routerPriority = routerPriority;
}
/**
* Gets hello interval.
*
* @return hello Interval
*/
public int helloInterval() {
return helloInterval;
}
/**
* Sets hello Interval.
*
* @param helloInterval hello Interval
*/
public void setHelloInterval(int helloInterval) {
this.helloInterval = helloInterval;
}
/**
* Gets router dead interval.
*
* @return router dead interval
*/
public int routerDeadInterval() {
return routerDeadInterval;
}
/**
* Sets router dead interval.
*
* @param routerDeadInterval router dead interval
*/
public void setRouterDeadInterval(int routerDeadInterval) {
this.routerDeadInterval = routerDeadInterval;
}
@Override
public OspfPacketType ospfMessageType() {
return OspfPacketType.HELLO;
}
@Override
public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
try {
byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
this.setNetworkMask(Ip4Address.valueOf(tempByteArray));
this.setHelloInterval(channelBuffer.readShort());
this.setOptions(channelBuffer.readByte());
this.setRouterPriority(channelBuffer.readByte() & 0xff);
this.setRouterDeadInterval(channelBuffer.readInt());
tempByteArray = new byte[OspfUtil.FOUR_BYTES];
channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
this.setDr(Ip4Address.valueOf(tempByteArray));
tempByteArray = new byte[OspfUtil.FOUR_BYTES];
channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
this.setBdr(Ip4Address.valueOf(tempByteArray));
while (channelBuffer.readableBytes() > 0) {
tempByteArray = new byte[OspfUtil.FOUR_BYTES];
channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
this.addNeighbor(Ip4Address.valueOf(tempByteArray));
}
} catch (Exception e) {
log.debug("Error::HelloPacket:: {}", e.getMessage());
throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
}
}
@Override
public byte[] asBytes() {
byte[] helloMessage = null;
byte[] helloHeader = getHelloHeaderAsByteArray();
byte[] helloBody = getHelloBodyAsByteArray();
helloMessage = Bytes.concat(helloHeader, helloBody);
log.debug("HelloPacket::asBytes::Hello asBytes:: {}", helloMessage);
return helloMessage;
}
/**
* Gets hello header as byte array.
*
* @return hello header
*/
public byte[] getHelloHeaderAsByteArray() {
List<Byte> headerLst = new ArrayList<>();
try {
headerLst.add((byte) this.ospfVersion());
headerLst.add((byte) this.ospfType());
headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.ospfPacLength())));
headerLst.addAll(Bytes.asList(this.routerId().toOctets()));
headerLst.addAll(Bytes.asList(this.areaId().toOctets()));
headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.checksum())));
headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.authType())));
//Authentication is 0 always. Total 8 bytes consist of zero
byte[] auth = new byte[OspfUtil.EIGHT_BYTES];
headerLst.addAll(Bytes.asList(auth));
} catch (Exception e) {
log.debug("Error::getHelloHeaderAsByteArray {}", e.getMessage());
return Bytes.toArray(headerLst);
}
return Bytes.toArray(headerLst);
}
/**
* Gets hello body as byte array.
*
* @return hello body as byte array
*/
public byte[] getHelloBodyAsByteArray() {
List<Byte> bodyLst = new ArrayList<>();
try {
bodyLst.addAll(Bytes.asList(this.networkMask().toOctets()));
bodyLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.helloInterval())));
bodyLst.add((byte) this.options());
bodyLst.add((byte) this.routerPriority());
bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.routerDeadInterval())));
bodyLst.addAll(Bytes.asList(this.dr().toOctets()));
bodyLst.addAll(Bytes.asList(this.bdr().toOctets()));
for (Ip4Address neighbour : neighborAddress) {
bodyLst.addAll(Bytes.asList(neighbour.toOctets()));
}
} catch (Exception e) {
log.debug("Error::getHelloBodyAsByteArray {}", e.getMessage());
return Bytes.toArray(bodyLst);
}
return Bytes.toArray(bodyLst);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.omitNullValues()
.add("networkMask", networkMask)
.add("options", options)
.add("helloInterval", helloInterval)
.add("routerPriority", routerPriority)
.add("routerDeadInterval", routerDeadInterval)
.add("bdr", bdr)
.add("dr", dr)
.toString();
}
}