IPAddress into IntentFramework Fixed & SDN-IP SetupBGPPaths

Change-Id: Ie25571ad9c9c834e476a5010e29175c9fb6cd3fb
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/ISdnIpService.java b/src/main/java/net/onrc/onos/apps/sdnip/ISdnIpService.java
index 040afe6..21ee3d3 100644
--- a/src/main/java/net/onrc/onos/apps/sdnip/ISdnIpService.java
+++ b/src/main/java/net/onrc/onos/apps/sdnip/ISdnIpService.java
@@ -45,4 +45,9 @@
      * update
      */
     public void newRibUpdate(RibUpdate update);
+
+    /**
+     * Start SDN-IP Routing.
+     */
+    public void beginRoutingNew();
 }
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
index 5db148c..4dff135 100644
--- a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
+++ b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
@@ -29,12 +29,17 @@
 import net.onrc.onos.apps.proxyarp.IArpRequester;
 import net.onrc.onos.apps.proxyarp.IProxyArpService;
 import net.onrc.onos.apps.sdnip.RibUpdate.Operation;
-import net.onrc.onos.apps.sdnip.web.SdnIpWebRoutable;
+import net.onrc.onos.apps.sdnip.web.SdnIpWebRoutableNew;
+import net.onrc.onos.core.intent.IntentOperation;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.ShortestPathIntent;
+import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
 import net.onrc.onos.core.linkdiscovery.ILinkDiscovery.LDUpdate;
 import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
 import net.onrc.onos.core.main.config.IConfigInfoService;
 import net.onrc.onos.core.packet.Ethernet;
 import net.onrc.onos.core.packet.IPv4;
+import net.onrc.onos.core.registry.IControllerRegistryService;
 import net.onrc.onos.core.util.CallerId;
 import net.onrc.onos.core.util.DataPath;
 import net.onrc.onos.core.util.Dpid;
@@ -94,6 +99,12 @@
     private static final String DEFAULT_CONFIG_FILENAME = "config.json";
     private String currentConfigFilename = DEFAULT_CONFIG_FILENAME;
 
+    /* ShortestPath Intent Variables */
+    private final String callerId = "SdnIp";
+    private IControllerRegistryService controllerRegistryService;
+    private IPathCalcRuntimeService pathRuntime;
+    /* Shortest Intent Path Variables */
+
     private static final short ARP_PRIORITY = 20;
 
     // The fields below are unused after the move to FlowManager.
@@ -254,6 +265,8 @@
                 = new ArrayList<Class<? extends IFloodlightService>>();
         l.add(IFloodlightProviderService.class);
         l.add(IRestApiService.class);
+        l.add(IControllerRegistryService.class);
+        l.add(IPathCalcRuntimeService.class);
         return l;
     }
 
@@ -272,6 +285,8 @@
         restApi = context.getServiceImpl(IRestApiService.class);
         proxyArp = context.getServiceImpl(IProxyArpService.class);
 
+        controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
+        pathRuntime = context.getServiceImpl(IPathCalcRuntimeService.class);
         linkUpdates = new ArrayList<LDUpdate>();
         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
         topologyChangeDetectorTask = new SingletonTask(executor, new TopologyChangeDetector());
@@ -320,7 +335,8 @@
 
     @Override
     public void startUp(FloodlightModuleContext context) {
-        restApi.addRestletRoutable(new SdnIpWebRoutable());
+        //restApi.addRestletRoutable(new SdnIpWebRoutable());
+        restApi.addRestletRoutable(new SdnIpWebRoutableNew());
         floodlightProvider.addOFSwitchListener(this);
 
         // Retrieve the RIB from BGPd during startup
@@ -802,7 +818,66 @@
         }
     }
 
+    @Override
+    public void beginRoutingNew() {
+            setupBgpPathsNew();
+
+        //setupFullMesh();
+
+        //Suppress link discovery on external-facing router ports
+
+        for (Interface intf : interfaces.values()) {
+            linkDiscoveryService.addToSuppressLLDPs(intf.getDpid(), intf.getPort());
+        }
+
+        bgpUpdatesExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                doUpdatesThread();
+            }
+        });
+    }
+
     /**
+     * Setup the Paths to the BGP Daemon.
+     *
+     * Run a loop for all of the bgpPeers
+     * Push flow from BGPd to the peer
+     * Push flow from peer to BGPd
+     * Parameters to pass to the intent are as follows:
+     *     String id,
+     *     long srcSwitch, long srcPort, long srcMac, int srcIP,
+     *     long dstSwitch, long dstPort, long dstMac, int dstIP
+     */
+    private void setupBgpPathsNew() {
+        IntentOperationList operations = new IntentOperationList();
+        for (BgpPeer bgpPeer : bgpPeers.values()) {
+            Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
+            //Inet4Address.
+            int srcIP = InetAddresses.coerceToInteger(peerInterface.getIpAddress());
+            int dstIP = InetAddresses.coerceToInteger(bgpPeer.getIpAddress());
+            String fwdIntentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
+            String bwdIntentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
+            SwitchPort srcPort =
+                new SwitchPort(bgpdAttachmentPoint.dpid(),
+                               bgpdAttachmentPoint.port());
+            SwitchPort dstPort =
+                new SwitchPort(new Dpid(peerInterface.getDpid()),
+                               new Port(peerInterface.getSwitchPort().port()));
+            ShortestPathIntent fwdIntent = new ShortestPathIntent(fwdIntentId,
+                    srcPort.dpid().value(), srcPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, srcIP,
+                    dstPort.dpid().value(), dstPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, dstIP);
+            ShortestPathIntent bwdIntent = new ShortestPathIntent(bwdIntentId,
+                    srcPort.dpid().value(), srcPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, dstIP,
+                    dstPort.dpid().value(), dstPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, srcIP);
+            IntentOperation.Operator operator = IntentOperation.Operator.ADD;
+            operations.add(operator, fwdIntent);
+            operations.add(operator, bwdIntent);
+        }
+        pathRuntime.executeIntentOperations(operations);
+    }
+
+    /*
      * Proactively install all BGP traffic paths from BGP host attachment point
      * in SDN network to all the virtual gateways to BGP peers in other networks.
      */
@@ -822,13 +897,13 @@
             flowPath.setFlowPathFlags(new FlowPathFlags(0));
 
             Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
-
             // Create the Flow Path Match condition(s)
             FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
             flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPV4);
 
             // Match both source address and dest address
             IPv4Net dstIPv4Net = new IPv4Net(bgpPeer.getIpAddress().getHostAddress() + "/32");
+
             flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
 
             IPv4Net srcIPv4Net = new IPv4Net(peerInterface.getIpAddress().getHostAddress() + "/32");
@@ -900,13 +975,13 @@
             DataPath reverseDataPath = new DataPath();
 
             SwitchPort reverseDstPort =
-                new SwitchPort(bgpdAttachmentPoint.dpid(),
-                               bgpdAttachmentPoint.port());
+                    new SwitchPort(bgpdAttachmentPoint.dpid(),
+                            bgpdAttachmentPoint.port());
             reverseDataPath.setDstPort(reverseDstPort);
 
             SwitchPort reverseSrcPort =
-                new SwitchPort(new Dpid(peerInterface.getDpid()),
-                               new Port(peerInterface.getSwitchPort().port()));
+                    new SwitchPort(new Dpid(peerInterface.getDpid()),
+                            new Port(peerInterface.getSwitchPort().port()));
             reverseDataPath.setSrcPort(reverseSrcPort);
             flowPath.setDataPath(reverseDataPath);
 
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpSetup.java b/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpSetup.java
new file mode 100644
index 0000000..d1c4605
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpSetup.java
@@ -0,0 +1,20 @@
+package net.onrc.onos.apps.sdnip.web;
+
+import net.onrc.onos.apps.sdnip.ISdnIpService;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+/**
+ * REST call to start SDN-IP routing.
+ */
+public class SdnIpSetup extends ServerResource {
+    @Get("json")
+    public String sdnipSetupMethod() {
+        ISdnIpService sdnIp = (ISdnIpService) getContext()
+                              .getAttributes().get(ISdnIpService.class.getCanonicalName());
+        sdnIp.beginRoutingNew();
+        return "SdnIp SetupBgpPaths Succeeded";
+    }
+
+}
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpWebRoutableNew.java b/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpWebRoutableNew.java
new file mode 100644
index 0000000..250b4da
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/sdnip/web/SdnIpWebRoutableNew.java
@@ -0,0 +1,26 @@
+
+package net.onrc.onos.apps.sdnip.web;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+/**
+ * REST URL router for SDN-IP REST calls.
+ */
+public class SdnIpWebRoutableNew implements RestletRoutable {
+
+    @Override
+    public Restlet getRestlet(Context context) {
+        Router router = new Router(context);
+        router.attach("/beginRouting/json", SdnIpSetup.class);
+        return router;
+    }
+
+    @Override
+    public String basePath() {
+        return "/wm/bgpNew";
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/intent/FlowEntry.java b/src/main/java/net/onrc/onos/core/intent/FlowEntry.java
index 94cf88a..022cecf 100644
--- a/src/main/java/net/onrc/onos/core/intent/FlowEntry.java
+++ b/src/main/java/net/onrc/onos/core/intent/FlowEntry.java
@@ -23,11 +23,14 @@
     protected int idleTimeout = 0;
     protected long flowEntryId;
 
+// CHECKSTYLE:OFF suppress the warning about too many parameters
     public FlowEntry(long sw, long srcPort, long dstPort,
                      MACAddress srcMac, MACAddress dstMac,
+                     int srcIpAddress, int dstIpAddress,
                      Operator operator) {
+// CHECKSTYLE:ON
         this.sw = sw;
-        this.match = new Match(sw, srcPort, srcMac, dstMac);
+        this.match = new Match(sw, srcPort, srcMac, dstMac, srcIpAddress, dstIpAddress);
         this.actions = new HashSet<Action>();
         this.actions.add(new ForwardAction(dstPort));
         this.operator = operator;
diff --git a/src/main/java/net/onrc/onos/core/intent/Match.java b/src/main/java/net/onrc/onos/core/intent/Match.java
index f7a2167..d4e0ce2 100644
--- a/src/main/java/net/onrc/onos/core/intent/Match.java
+++ b/src/main/java/net/onrc/onos/core/intent/Match.java
@@ -1,38 +1,69 @@
 package net.onrc.onos.core.intent;
 
-import java.util.Arrays;
+
+import java.util.Objects;
 
 import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.packet.Ethernet;
 //import net.onrc.onos.core.topology.Port;
 //import net.onrc.onos.core.topology.Switch;
 import net.onrc.onos.core.util.FlowEntryMatch;
+import net.onrc.onos.core.util.IPv4;
+import net.onrc.onos.core.util.IPv4Net;
 
 /**
  * @author Brian O'Connor <bocon@onlab.us>
  */
 
 public class Match {
+    private static final short IPV4_PREFIX_LEN = 32;
     protected long sw;
     protected MACAddress srcMac;
     protected MACAddress dstMac;
+    protected int srcIp;
+    protected int dstIp;
     protected long srcPort;
 
     public Match(long sw, long srcPort,
                  MACAddress srcMac, MACAddress dstMac) {
+        this(sw, srcPort, srcMac, dstMac, ShortestPathIntent.EMPTYIPADDRESS, ShortestPathIntent.EMPTYIPADDRESS);
+    }
+
+    public Match(long sw, long srcPort, MACAddress srcMac, MACAddress dstMac,
+                 int srcIp, int dstIp) {
+
         this.sw = sw;
         this.srcPort = srcPort;
         this.srcMac = srcMac;
         this.dstMac = dstMac;
+        this.srcIp = srcIp;
+        this.dstIp = dstIp;
     }
 
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof Match) {
             Match other = (Match) obj;
-            return this.sw == other.sw &&
-                    this.srcMac.equals(other.srcMac) &&
-                    this.dstMac.equals(other.dstMac) &&
-                    this.srcPort == other.srcPort;
+            if (this.sw != other.sw) {
+                return false;
+            }
+            if (!Objects.equals(srcMac, other.srcMac)) {
+                return false;
+            }
+            if (!Objects.equals(dstMac, other.dstMac)) {
+                return false;
+            }
+            if (srcIp != other.srcIp) {
+                return false;
+            }
+
+            if (dstIp != other.dstIp) {
+                return false;
+            }
+            if (this.srcPort != other.srcPort) {
+                return false;
+            }
+            return true;
         } else {
             return false;
         }
@@ -40,24 +71,35 @@
 
     public FlowEntryMatch getFlowEntryMatch() {
         FlowEntryMatch match = new FlowEntryMatch();
-        match.enableSrcMac(srcMac);
-        match.enableDstMac(dstMac);
+        if (srcMac != null) {
+            match.enableSrcMac(srcMac);
+        }
+        if (dstMac != null) {
+            match.enableDstMac(dstMac);
+        }
+        if (srcIp != ShortestPathIntent.EMPTYIPADDRESS) {
+            match.enableEthernetFrameType(Ethernet.TYPE_IPV4);
+            IPv4 srcIPv4 = new IPv4(srcIp);
+            IPv4Net srcIP = new IPv4Net(srcIPv4, IPV4_PREFIX_LEN);
+            match.enableSrcIPv4Net(srcIP);
+        }
+        if (dstIp != ShortestPathIntent.EMPTYIPADDRESS) {
+            match.enableEthernetFrameType(Ethernet.TYPE_IPV4);
+            IPv4 dstIPv4 = new IPv4(dstIp);
+            IPv4Net dstIP = new IPv4Net(dstIPv4, IPV4_PREFIX_LEN);
+            match.enableDstIPv4Net(dstIP);
+        }
         match.enableInPort(new net.onrc.onos.core.util.Port((short) srcPort));
         return match;
     }
 
     @Override
     public String toString() {
-        return "Sw:" + sw + " (" + srcPort + "," + srcMac + "," + dstMac + ")";
+        return "Sw:" + sw + " (" + srcPort + "," + srcMac + "," + dstMac + "," + srcIp + "," + dstIp + ")";
     }
 
     @Override
     public int hashCode() {
-        long[] nums = new long[4];
-        nums[0] = sw;
-        nums[1] = srcPort;
-        nums[2] = srcMac.toLong();
-        nums[3] = dstMac.toLong();
-        return Arrays.hashCode(nums);
+        return  Objects.hash(sw, srcPort, srcMac, dstMac, srcIp, dstIp);
     }
 }
diff --git a/src/main/java/net/onrc/onos/core/intent/ShortestPathIntent.java b/src/main/java/net/onrc/onos/core/intent/ShortestPathIntent.java
index 3c8d345..1d5606f 100644
--- a/src/main/java/net/onrc/onos/core/intent/ShortestPathIntent.java
+++ b/src/main/java/net/onrc/onos/core/intent/ShortestPathIntent.java
@@ -7,12 +7,16 @@
  * @author Toshio Koide (t-koide@onlab.us)
  */
 public class ShortestPathIntent extends Intent {
+    public static final long EMPTYMACADDRESS = 0;
+    public static final int EMPTYIPADDRESS = 0;
     protected long srcSwitchDpid;
     protected long srcPortNumber;
     protected long srcMacAddress;
     protected long dstSwitchDpid;
     protected long dstPortNumber;
     protected long dstMacAddress;
+    protected int srcIpAddress;
+    protected int dstIpAddress;
     protected String pathIntentId = null;
     protected int idleTimeout;
     protected int hardTimeout;
@@ -39,13 +43,24 @@
     public ShortestPathIntent(String id,
                               long srcSwitch, long srcPort, long srcMac,
                               long dstSwitch, long dstPort, long dstMac) {
+        //super(id);
+        this(id, srcSwitch, srcPort, srcMac, EMPTYIPADDRESS, dstSwitch, dstPort, dstMac, EMPTYIPADDRESS);
+    }
+
+    // CHECKSTYLE:OFF suppress the warning about too many parameters
+    public ShortestPathIntent(String id,
+                              long srcSwitch, long srcPort, long srcMac, int srcIp,
+                              long dstSwitch, long dstPort, long dstMac, int dstIp ) {
+    // CHECKSTYLE:ON
         super(id);
-        srcSwitchDpid = srcSwitch;
-        srcPortNumber = srcPort;
-        srcMacAddress = srcMac;
-        dstSwitchDpid = dstSwitch;
-        dstPortNumber = dstPort;
-        dstMacAddress = dstMac;
+        this.srcSwitchDpid = srcSwitch;
+        this.srcPortNumber = srcPort;
+        this.srcMacAddress = srcMac;
+        this.dstSwitchDpid = dstSwitch;
+        this.dstPortNumber = dstPort;
+        this.dstMacAddress = dstMac;
+        this.srcIpAddress = srcIp;
+        this.dstIpAddress = dstIp;
     }
 
     /**
@@ -164,9 +179,17 @@
 
     @Override
     public String toString() {
-        return String.format("id:%s, state:%s, srcDpid:%s, srcPort:%d, srcMac:%s, dstDpid:%s, dstPort:%d, dstMac:%s",
+        return String.format("id:%s, state:%s, srcDpid:%s, srcPort:%d, srcMac:%s, srcIP:%s, dstDpid:%s, dstPort:%d, dstMac:%s, dstIP:%s",
                 getId(), getState(),
-                new Dpid(srcSwitchDpid), srcPortNumber, MACAddress.valueOf(srcMacAddress),
-                new Dpid(dstSwitchDpid), dstPortNumber, MACAddress.valueOf(dstMacAddress));
+                new Dpid(srcSwitchDpid), srcPortNumber, MACAddress.valueOf(srcMacAddress), Integer.toString(srcIpAddress),
+                new Dpid(dstSwitchDpid), dstPortNumber, MACAddress.valueOf(dstMacAddress), Integer.toString(dstIpAddress));
+    }
+
+    public int getSrcIp() {
+        return srcIpAddress;
+    }
+
+    public int getDstIp() {
+        return dstIpAddress;
     }
 }
diff --git a/src/main/java/net/onrc/onos/core/intent/runtime/PlanCalcRuntime.java b/src/main/java/net/onrc/onos/core/intent/runtime/PlanCalcRuntime.java
index ddff381..7d2c33d 100644
--- a/src/main/java/net/onrc/onos/core/intent/runtime/PlanCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/core/intent/runtime/PlanCalcRuntime.java
@@ -19,10 +19,10 @@
 import net.onrc.onos.core.intent.PathIntent;
 import net.onrc.onos.core.intent.ShortestPathIntent;
 import net.onrc.onos.core.topology.LinkEvent;
-//import net.onrc.onos.core.topology.Topology;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+//import net.onrc.onos.core.topology.Topology;
 
 /**
  * @author Brian O'Connor <bocon@onlab.us>
@@ -62,14 +62,32 @@
             MACAddress srcMac, dstMac;
             int idleTimeout = 0, hardTimeout = 0, firstSwitchIdleTimeout = 0, firstSwitchHardTimeout = 0;
             Long cookieId = null;
+            int srcIP, dstIP;
             if (parent instanceof ShortestPathIntent) {
                 ShortestPathIntent pathIntent = (ShortestPathIntent) parent;
-//              Switch srcSwitch = graph.getSwitch(pathIntent.getSrcSwitchDpid());
-//              srcPort = srcSwitch.getPort(pathIntent.getSrcPortNumber());
                 srcPort = pathIntent.getSrcPortNumber();
-                srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
-                dstMac = MACAddress.valueOf(pathIntent.getDstMac());
 //              Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
+
+                // srcMacAddress
+                if (pathIntent.getSrcMac() != ShortestPathIntent.EMPTYMACADDRESS) {
+                    srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
+                } else {
+                    srcMac = null;
+                }
+
+                // dstMacAddress
+                if (pathIntent.getDstMac() != ShortestPathIntent.EMPTYMACADDRESS) {
+                    dstMac = MACAddress.valueOf(pathIntent.getSrcMac());
+                } else {
+                    dstMac = null;
+                }
+
+                // srcIp
+                srcIP = pathIntent.getSrcIp();
+                // dstIp
+                dstIP = pathIntent.getDstIp();
+
+                // Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
                 lastDstSw = pathIntent.getDstSwitchDpid();
                 firstSrcSw = pathIntent.getSrcSwitchDpid();
 //              lastDstPort = dstSwitch.getPort(pathIntent.getDstPortNumber());
@@ -97,7 +115,8 @@
                 long sw = linkEvent.getSrc().getDpid();
 //              dstPort = link.getSrcPort();
                 dstPort = linkEvent.getSrc().getNumber();
-                FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac, i.operator);
+                FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac,
+                                             srcIP, dstIP, i.operator);
                 if (sw != firstSrcSw) {
                     fe.setIdleTimeout(idleTimeout);
                     fe.setHardTimeout(hardTimeout);
@@ -110,14 +129,15 @@
                     fe.setFlowEntryId(cookieId);
                 }
                 entries.add(fe);
-//              srcPort = link.getDstPort();
+                //              srcPort = link.getDstPort();
                 srcPort = linkEvent.getDst().getNumber();
             }
             if (lastDstSw >= 0 && lastDstPort >= 0) {
                 //Switch sw = lastDstPort.getSwitch();
                 long sw = lastDstSw;
                 dstPort = lastDstPort;
-                FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac, i.operator);
+                FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac,
+                                             srcIP, dstIP, i.operator);
                 if (cookieId != null) {
                     log.trace("cookieId is set: {}", cookieId);
                     fe.setFlowEntryId(cookieId);
diff --git a/src/main/java/net/onrc/onos/core/util/IPv4.java b/src/main/java/net/onrc/onos/core/util/IPv4.java
index 047e8c6..2ba88c5 100644
--- a/src/main/java/net/onrc/onos/core/util/IPv4.java
+++ b/src/main/java/net/onrc/onos/core/util/IPv4.java
@@ -80,4 +80,21 @@
                 ((this.value >> 8) & 0xFF) + "." +
                 (this.value & 0xFF);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof IPv4)) {
+            return false;
+        }
+        IPv4 other = (IPv4) o;
+        if (this.value != other.value) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.value;
+    }
 }
diff --git a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
index c37f3ad..a01cfc4 100644
--- a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
@@ -53,7 +53,6 @@
 import net.onrc.onos.core.util.Switch;
 // import net.onrc.onos.core.util.SwitchPort;
 
-
 import com.esotericsoftware.kryo.Kryo;
 
 /**