Added packet handling functions for PIM, Specifically
PIM Hello and PIM Join/Prune messages along with
respective PIM encoded address types
Change-Id: Iaef2e3581e27fa910ad355043bcb3e175238706a
diff --git a/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java b/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java
new file mode 100644
index 0000000..d454f1a
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 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.onlab.packet.pim;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.Deserializer;
+import org.onlab.packet.IPacket;
+import org.onlab.packet.IpAddress;
+
+import java.nio.ByteBuffer;
+import java.util.Random;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+public class PIMHello extends BasePacket {
+
+ private IpAddress nbrIpAddress;
+
+ private int holdtime = 105;
+ private int genid = 0;
+ private int priority = 1;
+ private boolean priorityPresent = false;
+
+ public static final int MINIMUM_OPTION_LEN_BYTES = 4;
+
+ /**
+ * PIM Option types.
+ */
+ public enum Option {
+ HOLDTIME (1, 2),
+ PRUNEDELAY(2, 4),
+ PRIORITY (19, 4),
+ GENID (20, 4),
+ ADDRLIST (24, 0);
+
+ private final int optType;
+ private final int optLen;
+
+ Option(int ot, int ol) {
+ this.optType = ot;
+ this.optLen = ol;
+ }
+
+ public int optType() {
+ return this.optType;
+ }
+
+ public int optLen() {
+ return this.optLen;
+ }
+ }
+
+ /**
+ * Add the holdtime to the packet.
+ *
+ * @param holdtime the holdtime in seconds
+ */
+ public void addHoldtime(int holdtime) {
+ this.holdtime = holdtime;
+ }
+
+ /**
+ * Add the hello priority.
+ *
+ * @param priority default is 1, the higher the better
+ */
+ public void addPriority(int priority) {
+ this.priority = priority;
+ this.priorityPresent = true;
+ }
+
+ /**
+ * Add a Gen ID.
+ *
+ * @param genid a random generated number, changes only after reset.
+ */
+ public void addGenId(int genid) {
+ if (genid == 0) {
+ this.addGenId();
+ } else {
+ this.genid = genid;
+ }
+ }
+
+ /**
+ * Add the genid. Let this function figure out the number.
+ */
+ public void addGenId() {
+ Random rand = new Random();
+ this.genid = rand.nextInt();
+ }
+
+ /**
+ * Sets all payloads parent packet if applicable, then serializes this
+ * packet and all payloads.
+ *
+ * @return a byte[] containing this packet and payloads
+ */
+ @Override
+ public byte[] serialize() {
+
+ // TODO: Figure out a better way to calculate buffer size
+ int size = Option.PRIORITY.optLen() + 4 +
+ Option.GENID.optLen() + 4 +
+ Option.HOLDTIME.optLen() + 4;
+
+ byte[] data = new byte[size]; // Come up with something better
+ ByteBuffer bb = ByteBuffer.wrap(data);
+
+ // Add the priority
+ bb.putShort((short) Option.PRIORITY.optType);
+ bb.putShort((short) Option.PRIORITY.optLen);
+ bb.putInt(this.priority);
+
+ // Add the genid
+ bb.putShort((short) Option.GENID.optType);
+ bb.putShort((short) Option.GENID.optLen);
+ bb.putInt(this.genid);
+
+ // Add the holdtime
+ bb.putShort((short) Option.HOLDTIME.optType);
+ bb.putShort((short) Option.HOLDTIME.optLen);
+ bb.putShort((short) this.holdtime);
+ return data;
+ }
+
+ /**
+ * XXX: This is deprecated, DO NOT USE, use the deserializer() function instead.
+ */
+ // @Override
+ public IPacket deserialize(final byte[] data, final int offset,
+ final int length) {
+ //
+ return null;
+ }
+
+ /**
+ * Deserialize this hello message.
+ *
+ * @return a deserialized hello message.
+ */
+ public static Deserializer<PIMHello> deserializer() {
+ return (data, offset, length) -> {
+ checkInput(data, offset, length, MINIMUM_OPTION_LEN_BYTES);
+ final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+
+ PIMHello hello = new PIMHello();
+ while (bb.hasRemaining()) {
+ int optType = bb.getShort();
+ int optLen = bb.getShort();
+
+ // Check that we have enough buffer for the next option.
+ checkInput(data, bb.position(), bb.limit() - bb.position(), optLen);
+ if (optType == Option.GENID.optType) {
+ hello.addGenId(bb.getInt());
+ } else if (optType == Option.PRIORITY.optType) {
+ hello.addPriority(bb.getInt());
+ } else if (optType == Option.HOLDTIME.optType) {
+ hello.addHoldtime((int) bb.getShort());
+ }
+ }
+
+ return hello;
+ };
+ }
+}