Added configuration for PIM interfaces.

Now the PIM application requires PIM Interface configuration for each interface
that will have PIM enabled (no longer uses all ONOS interfaces). The
interface-specific PIM parameters can be tuned.

Change-Id: Ibc284fdbe1b3aa4da48097b3e92470bce4f349a7
diff --git a/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java b/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java
index 7d05d92..2372e1a 100644
--- a/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java
@@ -23,29 +23,43 @@
 import static org.onlab.packet.PacketUtils.checkBufferLength;
 import static org.onlab.packet.PacketUtils.checkInput;
 
+/**
+ * PIM HELLO option.
+ */
 public class PIMHelloOption {
 
-    /**
+    /*
      * PIM Option types.
      */
     public static final short OPT_HOLDTIME = 1;
-    public static final short OPT_PRUNEDELAY = 2;
-    public static final short OPT_PRIORITY = 19;
-    public static final short OPT_GENID = 20;
-    public static final short OPT_ADDRLIST = 24;
-
+    public static final short HOLDTIME_LENGTH = 2;
     public static final short DEFAULT_HOLDTIME = 105;
-    public static final int DEFAULT_PRUNEDELAY = 2000; // 2,000 ms
+
+    public static final short OPT_PRUNEDELAY = 2;
+    public static final short PRUNEDELAY_LENGTH = 4;
+    public static final short DEFAULT_PRUNEDELAY = 500; // 500 ms
+    public static final short DEFAULT_OVERRIDEINTERVAL = 2500; // 2500 ms
+
+    public static final short OPT_PRIORITY = 19;
+    public static final short PRIORITY_LENGTH = 4;
     public static final int DEFAULT_PRIORITY = 1;
+
+    public static final short OPT_GENID = 20;
+    public static final short GENID_LENGTH = 4;
     public static final int DEFAULT_GENID = 0;
 
+    public static final short OPT_ADDRLIST = 24;
+
     public static final int MINIMUM_OPTION_LEN_BYTES = 4;
 
     // Values for this particular hello option.
-    private short optType;
-    private short optLength;
+    private short optType = 0;
+    private short optLength = 0;
     private byte[] optValue;
 
+    /**
+     * Constructs a new hello option with no fields set.
+     */
     public PIMHelloOption() {
     }
 
@@ -59,25 +73,25 @@
         this.optType = type;
         switch (type) {
             case OPT_HOLDTIME:
-                this.optLength = 2;
+                this.optLength = HOLDTIME_LENGTH;
                 this.optValue = new byte[optLength];
                 ByteBuffer.wrap(this.optValue).putShort(PIMHelloOption.DEFAULT_HOLDTIME);
                 break;
 
             case OPT_PRUNEDELAY:
-                this.optLength = 4;
+                this.optLength = PRUNEDELAY_LENGTH;
                 this.optValue = new byte[this.optLength];
                 ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRUNEDELAY);
                 break;
 
             case OPT_PRIORITY:
-                this.optLength = 4;
+                this.optLength = PRIORITY_LENGTH;
                 this.optValue = new byte[this.optLength];
                 ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRIORITY);
                 break;
 
             case OPT_GENID:
-                this.optLength = 4;
+                this.optLength = GENID_LENGTH;
                 this.optValue = new byte[this.optLength];
                 ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_GENID);
                 break;
@@ -109,17 +123,85 @@
         return this.optLength;
     }
 
-    public void setValue(ByteBuffer bb) throws DeserializationException {
+    public void setValue(ByteBuffer bb) {
         this.optValue = new byte[this.optLength];
         bb.get(this.optValue, 0, this.optLength);
     }
 
+    public void setValue(byte[] value) {
+        this.optValue = value;
+    }
+
     public byte[] getValue() {
         return this.optValue;
     }
 
+    /**
+     * Creates a new PIM Hello option with the specified values.
+     *
+     * @param type hello option type
+     * @param length option length
+     * @param value option value
+     * @return new PIM Hello option
+     */
+    public static PIMHelloOption create(short type, short length, ByteBuffer value) {
+        PIMHelloOption option = new PIMHelloOption();
+        option.setOptType(type);
+        option.setOptLength(length);
+        value.rewind();
+        option.setValue(value);
+        return option;
+    }
+
+    /**
+     * Creates a new priority option.
+     *
+     * @param priority priority
+     * @return priority option
+     */
+    public static PIMHelloOption createPriority(int priority) {
+        return create(OPT_PRIORITY, PRIORITY_LENGTH,
+                ByteBuffer.allocate(PRIORITY_LENGTH).putInt(priority));
+    }
+
+    /**
+     * Creates a new hold time option.
+     *
+     * @param holdTime hold time
+     * @return hold time option
+     */
+    public static PIMHelloOption createHoldTime(short holdTime) {
+        return create(OPT_HOLDTIME, HOLDTIME_LENGTH,
+                ByteBuffer.allocate(HOLDTIME_LENGTH).putShort(holdTime));
+    }
+
+    /**
+     * Creates a new generation ID option with a particular generation ID.
+     *
+     * @param genId generation ID value
+     * @return generation ID option
+     */
+    public static PIMHelloOption createGenID(int genId) {
+        return create(OPT_GENID, GENID_LENGTH,
+                ByteBuffer.allocate(GENID_LENGTH).putInt(genId));
+    }
+
+    /**
+     * Creates a new LAN Prune Delay option.
+     *
+     * @param propagationDelay prune delay
+     * @param overrideInterval override interval
+     * @return prune delay option
+     */
+    public static PIMHelloOption createPruneDelay(short propagationDelay, short overrideInterval) {
+        return create(OPT_PRUNEDELAY, PRUNEDELAY_LENGTH,
+                ByteBuffer.allocate(PRUNEDELAY_LENGTH)
+                        .putShort(propagationDelay)
+                        .putShort(overrideInterval));
+    }
+
     public static PIMHelloOption deserialize(ByteBuffer bb) throws DeserializationException {
-        checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4);
+        checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), MINIMUM_OPTION_LEN_BYTES);
 
         PIMHelloOption opt = new PIMHelloOption();
         opt.setOptType(bb.getShort());
@@ -132,7 +214,7 @@
     }
 
     public byte[] serialize() {
-        int len = 4 + this.optLength;
+        int len = MINIMUM_OPTION_LEN_BYTES + this.optLength;
         ByteBuffer bb = ByteBuffer.allocate(len);
         bb.putShort(this.optType);
         bb.putShort(this.optLength);