ONOS-2739 - OSPF Basic Packet Structures , which includes encoding and decoding
Change-Id: I33b48593ec38d28bdff215ce3a608a6d085a9077
diff --git a/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/ospfpacket/types/HelloPacket.java b/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/ospfpacket/types/HelloPacket.java
new file mode 100644
index 0000000..cf0d6aa
--- /dev/null
+++ b/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/ospfpacket/types/HelloPacket.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2016 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();
+ }
+}
\ No newline at end of file