diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/AsPathTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/AsPathTest.java
new file mode 100644
index 0000000..c14c20b
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/AsPathTest.java
@@ -0,0 +1,169 @@
+package org.onlab.onos.sdnip.bgp;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for the BgpRouteEntry.AsPath class.
+ */
+public class AsPathTest {
+    /**
+     * Generates an AS Path.
+     *
+     * @return a generated AS Path
+     */
+    private BgpRouteEntry.AsPath generateAsPath() {
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+
+        return asPath;
+    }
+
+    /**
+     * Tests valid class constructor.
+     */
+    @Test
+    public void testConstructor() {
+        BgpRouteEntry.AsPath asPath = generateAsPath();
+
+        String expectedString =
+            "AsPath{pathSegments=" +
+            "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
+            "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}";
+        assertThat(asPath.toString(), is(expectedString));
+    }
+
+    /**
+     * Tests invalid class constructor for null Path Segments.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullPathSegments() {
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = null;
+        new BgpRouteEntry.AsPath(pathSegments);
+    }
+
+    /**
+     * Tests getting the fields of an AS Path.
+     */
+    @Test
+    public void testGetFields() {
+        // Create the fields to compare against
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+
+        // Generate the entry to test
+        BgpRouteEntry.AsPath asPath = generateAsPath();
+
+        assertThat(asPath.getPathSegments(), is(pathSegments));
+    }
+
+    /**
+     * Tests getting the AS Path Length.
+     */
+    @Test
+    public void testGetAsPathLength() {
+        BgpRouteEntry.AsPath asPath = generateAsPath();
+        assertThat(asPath.getAsPathLength(), is(4));
+
+        // Create an empty AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        asPath = new BgpRouteEntry.AsPath(pathSegments);
+        assertThat(asPath.getAsPathLength(), is(0));
+    }
+
+    /**
+     * Tests equality of {@link BgpRouteEntry.AsPath}.
+     */
+    @Test
+    public void testEquality() {
+        BgpRouteEntry.AsPath asPath1 = generateAsPath();
+        BgpRouteEntry.AsPath asPath2 = generateAsPath();
+
+        assertThat(asPath1, is(asPath2));
+    }
+
+    /**
+     * Tests non-equality of {@link BgpRouteEntry.AsPath}.
+     */
+    @Test
+    public void testNonEquality() {
+        BgpRouteEntry.AsPath asPath1 = generateAsPath();
+
+        // Setup AS Path 2
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 55);                       // Different
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments);
+
+        assertThat(asPath1, is(not(asPath2)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        BgpRouteEntry.AsPath asPath = generateAsPath();
+
+        String expectedString =
+            "AsPath{pathSegments=" +
+            "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
+            "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}";
+        assertThat(asPath.toString(), is(expectedString));
+    }
+}
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpRouteEntryTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpRouteEntryTest.java
new file mode 100644
index 0000000..52a0214
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpRouteEntryTest.java
@@ -0,0 +1,498 @@
+package org.onlab.onos.sdnip.bgp;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Unit tests for the BgpRouteEntry class.
+ */
+public class BgpRouteEntryTest {
+    private BgpSession bgpSession;
+    private static final IpAddress BGP_SESSION_BGP_ID =
+        IpAddress.valueOf("10.0.0.1");
+    private static final IpAddress BGP_SESSION_IP_ADDRESS =
+        IpAddress.valueOf("20.0.0.1");
+
+    private BgpSession bgpSession2;
+    private static final IpAddress BGP_SESSION_BGP_ID2 =
+        IpAddress.valueOf("10.0.0.2");
+    private static final IpAddress BGP_SESSION_IP_ADDRESS2 =
+        IpAddress.valueOf("20.0.0.1");
+
+    private BgpSession bgpSession3;
+    private static final IpAddress BGP_SESSION_BGP_ID3 =
+        IpAddress.valueOf("10.0.0.1");
+    private static final IpAddress BGP_SESSION_IP_ADDRESS3 =
+        IpAddress.valueOf("20.0.0.2");
+
+    @Before
+    public void setUp() throws Exception {
+        // Mock objects for testing
+        bgpSession = createMock(BgpSession.class);
+        bgpSession2 = createMock(BgpSession.class);
+        bgpSession3 = createMock(BgpSession.class);
+
+        // Setup the BGP Sessions
+        expect(bgpSession.getRemoteBgpId())
+            .andReturn(BGP_SESSION_BGP_ID).anyTimes();
+        expect(bgpSession.getRemoteIp4Address())
+            .andReturn(BGP_SESSION_IP_ADDRESS).anyTimes();
+        //
+        expect(bgpSession2.getRemoteBgpId())
+            .andReturn(BGP_SESSION_BGP_ID2).anyTimes();
+        expect(bgpSession2.getRemoteIp4Address())
+            .andReturn(BGP_SESSION_IP_ADDRESS2).anyTimes();
+        //
+        expect(bgpSession3.getRemoteBgpId())
+            .andReturn(BGP_SESSION_BGP_ID3).anyTimes();
+        expect(bgpSession3.getRemoteIp4Address())
+            .andReturn(BGP_SESSION_IP_ADDRESS3).anyTimes();
+
+        replay(bgpSession);
+        replay(bgpSession2);
+        replay(bgpSession3);
+    }
+
+    /**
+     * Generates a BGP Route Entry.
+     *
+     * @return a generated BGP Route Entry
+     */
+    private BgpRouteEntry generateBgpRouteEntry() {
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 100;
+        long multiExitDisc = 20;
+
+        BgpRouteEntry bgpRouteEntry =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
+
+        return bgpRouteEntry;
+    }
+
+    /**
+     * Tests valid class constructor.
+     */
+    @Test
+    public void testConstructor() {
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+
+        String expectedString =
+            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
+            "bgpId=10.0.0.1, origin=0, asPath=AsPath{pathSegments=" +
+            "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
+            "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}, " +
+            "localPref=100, multiExitDisc=20}";
+        assertThat(bgpRouteEntry.toString(), is(expectedString));
+    }
+
+    /**
+     * Tests invalid class constructor for null BGP Session.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullBgpSession() {
+        BgpSession bgpSessionNull = null;
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 100;
+
+        new BgpRouteEntry(bgpSessionNull, prefix, nextHop, origin, asPath,
+                    localPref);
+    }
+
+    /**
+     * Tests invalid class constructor for null AS Path.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullAsPath() {
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        BgpRouteEntry.AsPath asPath = null;
+        long localPref = 100;
+
+        new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                    localPref);
+    }
+
+    /**
+     * Tests getting the fields of a BGP route entry.
+     */
+    @Test
+    public void testGetFields() {
+        // Create the fields to compare against
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 100;
+        long multiExitDisc = 20;
+
+        // Generate the entry to test
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+
+        assertThat(bgpRouteEntry.prefix(), is(prefix));
+        assertThat(bgpRouteEntry.nextHop(), is(nextHop));
+        assertThat(bgpRouteEntry.getBgpSession(), is(bgpSession));
+        assertThat(bgpRouteEntry.getOrigin(), is(origin));
+        assertThat(bgpRouteEntry.getAsPath(), is(asPath));
+        assertThat(bgpRouteEntry.getLocalPref(), is(localPref));
+        assertThat(bgpRouteEntry.getMultiExitDisc(), is(multiExitDisc));
+    }
+
+    /**
+     * Tests whether a BGP route entry is a local route.
+     */
+    @Test
+    public void testIsLocalRoute() {
+        //
+        // Test non-local route
+        //
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+        assertThat(bgpRouteEntry.isLocalRoute(), is(false));
+
+        //
+        // Test local route with AS Path that begins with AS_SET
+        //
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 100;
+        long multiExitDisc = 20;
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
+        assertThat(bgpRouteEntry.isLocalRoute(), is(true));
+
+        //
+        // Test local route with empty AS Path
+        //
+        pathSegments = new ArrayList<>();
+        asPath = new BgpRouteEntry.AsPath(pathSegments);
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
+        assertThat(bgpRouteEntry.isLocalRoute(), is(true));
+    }
+
+    /**
+     * Tests getting the BGP Neighbor AS number for a route.
+     */
+    @Test
+    public void testGetNeighborAs() {
+        //
+        // Get neighbor AS for non-local route
+        //
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+        assertThat(bgpRouteEntry.getNeighborAs(), is((long) 1));
+
+        //
+        // Get neighbor AS for a local route
+        //
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 100;
+        long multiExitDisc = 20;
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
+        assertThat(bgpRouteEntry.getNeighborAs(), is(BgpConstants.BGP_AS_0));
+    }
+
+    /**
+     * Tests whether a BGP route entry has AS Path loop.
+     */
+    @Test
+    public void testHasAsPathLoop() {
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+
+        // Test for loops: test each AS number in the interval [1, 6]
+        for (int i = 1; i <= 6; i++) {
+            assertThat(bgpRouteEntry.hasAsPathLoop(i), is(true));
+        }
+
+        // Test for non-loops
+        assertThat(bgpRouteEntry.hasAsPathLoop(500), is(false));
+    }
+
+    /**
+     * Tests the BGP Decision Process comparison of BGP routes.
+     */
+    @Test
+    public void testBgpDecisionProcessComparison() {
+        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
+        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
+
+        //
+        // Compare two routes that are same
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
+
+        //
+        // Compare two routes with different LOCAL_PREF
+        //
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 50;                                    // Different
+        long multiExitDisc = 20;
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
+        localPref = bgpRouteEntry1.getLocalPref();              // Restore
+
+        //
+        // Compare two routes with different AS_PATH length
+        //
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments2 = new ArrayList<>();
+        pathSegments2.add(pathSegment1);
+        // Different AS Path
+        BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments2);
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath2,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(false));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
+
+        //
+        // Compare two routes with different ORIGIN
+        //
+        origin = BgpConstants.Update.Origin.EGP;                // Different
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
+        origin = bgpRouteEntry1.getOrigin();                    // Restore
+
+        //
+        // Compare two routes with different MULTI_EXIT_DISC
+        //
+        multiExitDisc = 10;                                     // Different
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
+        multiExitDisc = bgpRouteEntry1.getMultiExitDisc();      // Restore
+
+        //
+        // Compare two routes with different BGP ID
+        //
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession2, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
+
+        //
+        // Compare two routes with different BGP address
+        //
+        bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession3, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+        //
+        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
+        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
+    }
+
+    /**
+     * Tests equality of {@link BgpRouteEntry}.
+     */
+    @Test
+    public void testEquality() {
+        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
+        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
+
+        assertThat(bgpRouteEntry1, is(bgpRouteEntry2));
+    }
+
+    /**
+     * Tests non-equality of {@link BgpRouteEntry}.
+     */
+    @Test
+    public void testNonEquality() {
+        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
+
+        // Setup BGP Route 2
+        IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
+        IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
+        byte origin = BgpConstants.Update.Origin.IGP;
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 1);
+        segmentAsNumbers1.add((long) 2);
+        segmentAsNumbers1.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 4);
+        segmentAsNumbers2.add((long) 5);
+        segmentAsNumbers2.add((long) 6);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+        //
+        long localPref = 500;                                   // Different
+        long multiExitDisc = 20;
+        BgpRouteEntry bgpRouteEntry2 =
+            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
+                              localPref);
+        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
+
+        assertThat(bgpRouteEntry1, is(not(bgpRouteEntry2)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
+
+        String expectedString =
+            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
+            "bgpId=10.0.0.1, origin=0, asPath=AsPath{pathSegments=" +
+            "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
+            "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}, " +
+            "localPref=100, multiExitDisc=20}";
+        assertThat(bgpRouteEntry.toString(), is(expectedString));
+    }
+}
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java
new file mode 100644
index 0000000..99e3be1
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java
@@ -0,0 +1,403 @@
+package org.onlab.onos.sdnip.bgp;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFactory;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.sdnip.RouteListener;
+import org.onlab.onos.sdnip.RouteUpdate;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.util.TestUtils;
+import org.onlab.util.TestUtils.TestUtilsException;
+
+import com.google.common.net.InetAddresses;
+
+/**
+ * Unit tests for the BgpSessionManager class.
+ */
+public class BgpSessionManagerTest {
+    private static final IpAddress IP_LOOPBACK_ID =
+        IpAddress.valueOf("127.0.0.1");
+    private static final IpAddress BGP_PEER1_ID = IpAddress.valueOf("10.0.0.1");
+    private static final long DEFAULT_LOCAL_PREF = 10;
+    private static final long DEFAULT_MULTI_EXIT_DISC = 20;
+
+    // The BGP Session Manager to test
+    private BgpSessionManager bgpSessionManager;
+
+    // Remote Peer state
+    private ClientBootstrap peerBootstrap;
+    private TestBgpPeerChannelHandler peerChannelHandler =
+        new TestBgpPeerChannelHandler(BGP_PEER1_ID, DEFAULT_LOCAL_PREF);
+    private TestBgpPeerFrameDecoder peerFrameDecoder =
+        new TestBgpPeerFrameDecoder();
+
+    // The socket that the Remote Peer should connect to
+    private InetSocketAddress connectToSocket;
+
+    private final DummyRouteListener dummyRouteListener =
+        new DummyRouteListener();
+
+    /**
+     * Dummy implementation for the RouteListener interface.
+     */
+    private class DummyRouteListener implements RouteListener {
+        @Override
+        public void update(RouteUpdate routeUpdate) {
+            // Nothing to do
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        //
+        // Setup the BGP Session Manager to test, and start listening for BGP
+        // connections.
+        //
+        bgpSessionManager = new BgpSessionManager(dummyRouteListener);
+        // NOTE: We use port 0 to bind on any available port
+        bgpSessionManager.startUp(0);
+
+        // Get the port number the BGP Session Manager is listening on
+        Channel serverChannel = TestUtils.getField(bgpSessionManager,
+                                                   "serverChannel");
+        SocketAddress socketAddress = serverChannel.getLocalAddress();
+        InetSocketAddress inetSocketAddress =
+            (InetSocketAddress) socketAddress;
+
+        //
+        // Setup the BGP Peer, i.e., the "remote" BGP router that will
+        // initiate the BGP connection, send BGP UPDATE messages, etc.
+        //
+        ChannelFactory channelFactory =
+            new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),
+                                              Executors.newCachedThreadPool());
+        ChannelPipelineFactory pipelineFactory = new ChannelPipelineFactory() {
+                @Override
+                public ChannelPipeline getPipeline() throws Exception {
+                    // Setup the transmitting pipeline
+                    ChannelPipeline pipeline = Channels.pipeline();
+                    pipeline.addLast("TestBgpPeerFrameDecoder",
+                                     peerFrameDecoder);
+                    pipeline.addLast("TestBgpPeerChannelHandler",
+                                     peerChannelHandler);
+                    return pipeline;
+                }
+            };
+
+        peerBootstrap = new ClientBootstrap(channelFactory);
+        peerBootstrap.setOption("child.keepAlive", true);
+        peerBootstrap.setOption("child.tcpNoDelay", true);
+        peerBootstrap.setPipelineFactory(pipelineFactory);
+
+        InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
+        connectToSocket = new InetSocketAddress(connectToAddress,
+                                                inetSocketAddress.getPort());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        bgpSessionManager.shutDown();
+        bgpSessionManager = null;
+    }
+
+    /**
+     * Gets BGP RIB-IN routes by waiting until they are received.
+     * <p/>
+     * NOTE: We keep checking once a second the number of received routes,
+     * up to 5 seconds.
+     *
+     * @param bgpSession the BGP session that is expected to receive the
+     * routes
+     * @param expectedRoutes the expected number of routes
+     * @return the BGP RIB-IN routes as received within the expected
+     * time interval
+     */
+    private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
+                                                      long expectedRoutes)
+        throws InterruptedException {
+        Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn();
+
+        final int maxChecks = 5;                // Max wait of 5 seconds
+        for (int i = 0; i < maxChecks; i++) {
+            if (bgpRibIn.size() == expectedRoutes) {
+                break;
+            }
+            Thread.sleep(1000);
+            bgpRibIn = bgpSession.getBgpRibIn();
+        }
+
+        return bgpRibIn;
+    }
+
+    /**
+     * Gets BGP merged routes by waiting until they are received.
+     * <p/>
+     * NOTE: We keep checking once a second the number of received routes,
+     * up to 5 seconds.
+     *
+     * @param expectedRoutes the expected number of routes
+     * @return the BGP Session Manager routes as received within the expected
+     * time interval
+     */
+    private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
+        throws InterruptedException {
+        Collection<BgpRouteEntry> bgpRoutes = bgpSessionManager.getBgpRoutes();
+
+        final int maxChecks = 5;                // Max wait of 5 seconds
+        for (int i = 0; i < maxChecks; i++) {
+            if (bgpRoutes.size() == expectedRoutes) {
+                break;
+            }
+            Thread.sleep(1000);
+            bgpRoutes = bgpSessionManager.getBgpRoutes();
+        }
+
+        return bgpRoutes;
+    }
+
+    /**
+     * Tests that the BGP OPEN messages have been exchanged, followed by
+     * KEEPALIVE.
+     * <p>
+     * The BGP Peer opens the sessions and transmits OPEN Message, eventually
+     * followed by KEEPALIVE. The tested BGP listener should respond by
+     * OPEN Message, followed by KEEPALIVE.
+     *
+     * @throws TestUtilsException TestUtils error
+     */
+    @Test
+    public void testExchangedBgpOpenMessages()
+            throws InterruptedException, TestUtilsException {
+        // Initiate the connection
+        peerBootstrap.connect(connectToSocket);
+
+        // Wait until the OPEN message is received
+        peerFrameDecoder.receivedOpenMessageLatch.await(2000,
+                                                        TimeUnit.MILLISECONDS);
+        // Wait until the KEEPALIVE message is received
+        peerFrameDecoder.receivedKeepaliveMessageLatch.await(2000,
+                                                        TimeUnit.MILLISECONDS);
+
+        //
+        // Test the fields from the BGP OPEN message:
+        // BGP version, AS number, BGP ID
+        //
+        assertThat(peerFrameDecoder.remoteBgpVersion,
+                   is(BgpConstants.BGP_VERSION));
+        assertThat(peerFrameDecoder.remoteAs,
+                   is(TestBgpPeerChannelHandler.PEER_AS));
+        assertThat(peerFrameDecoder.remoteBgpIdentifier, is(IP_LOOPBACK_ID));
+
+        //
+        // Test that a BgpSession instance has been created
+        //
+        assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
+        assertThat(bgpSessionManager.getBgpSessions(), hasSize(1));
+        BgpSession bgpSession =
+            bgpSessionManager.getBgpSessions().iterator().next();
+        assertThat(bgpSession, notNullValue());
+        long sessionAs = TestUtils.getField(bgpSession, "localAs");
+        assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
+    }
+
+    /**
+     * Tests that the BGP UPDATE messages have been received and processed.
+     */
+    @Test
+    public void testProcessedBgpUpdateMessages() throws InterruptedException {
+        BgpSession bgpSession;
+        IpAddress nextHopRouter;
+        BgpRouteEntry bgpRouteEntry;
+        ChannelBuffer message;
+        Collection<BgpRouteEntry> bgpRibIn;
+        Collection<BgpRouteEntry> bgpRoutes;
+
+        // Initiate the connection
+        peerBootstrap.connect(connectToSocket);
+
+        // Wait until the OPEN message is received
+        peerFrameDecoder.receivedOpenMessageLatch.await(2000,
+                                                        TimeUnit.MILLISECONDS);
+        // Wait until the KEEPALIVE message is received
+        peerFrameDecoder.receivedKeepaliveMessageLatch.await(2000,
+                                                        TimeUnit.MILLISECONDS);
+
+        // Get the BGP Session handler
+        bgpSession = bgpSessionManager.getBgpSessions().iterator().next();
+
+        // Prepare routes to add/delete
+        nextHopRouter = IpAddress.valueOf("10.20.30.40");
+        Collection<IpPrefix> addedRoutes = new LinkedList<>();
+        Collection<IpPrefix> withdrawnRoutes = new LinkedList<>();
+        addedRoutes.add(IpPrefix.valueOf("0.0.0.0/0"));
+        addedRoutes.add(IpPrefix.valueOf("20.0.0.0/8"));
+        addedRoutes.add(IpPrefix.valueOf("30.0.0.0/16"));
+        addedRoutes.add(IpPrefix.valueOf("40.0.0.0/24"));
+        addedRoutes.add(IpPrefix.valueOf("50.0.0.0/32"));
+        withdrawnRoutes.add(IpPrefix.valueOf("60.0.0.0/8"));
+        withdrawnRoutes.add(IpPrefix.valueOf("70.0.0.0/16"));
+        withdrawnRoutes.add(IpPrefix.valueOf("80.0.0.0/24"));
+        withdrawnRoutes.add(IpPrefix.valueOf("90.0.0.0/32"));
+        // Write the routes
+        message = peerChannelHandler.prepareBgpUpdate(nextHopRouter,
+                                                      addedRoutes,
+                                                      withdrawnRoutes);
+        peerChannelHandler.savedCtx.getChannel().write(message);
+
+        // Check that the routes have been received, processed and stored
+        bgpRibIn = waitForBgpRibIn(bgpSession, 5);
+        assertThat(bgpRibIn, hasSize(5));
+        bgpRoutes = waitForBgpRoutes(5);
+        assertThat(bgpRoutes, hasSize(5));
+
+        // Setup the AS Path
+        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
+        segmentAsNumbers1.add((long) 65010);
+        segmentAsNumbers1.add((long) 65020);
+        segmentAsNumbers1.add((long) 65030);
+        BgpRouteEntry.PathSegment pathSegment1 =
+            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
+        pathSegments.add(pathSegment1);
+        //
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
+        segmentAsNumbers2.add((long) 65041);
+        segmentAsNumbers2.add((long) 65042);
+        segmentAsNumbers2.add((long) 65043);
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
+        pathSegments.add(pathSegment2);
+        //
+        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
+
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("0.0.0.0/0"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("20.0.0.0/8"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("30.0.0.0/16"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("40.0.0.0/24"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("50.0.0.0/32"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+
+        // Delete some routes
+        addedRoutes = new LinkedList<>();
+        withdrawnRoutes = new LinkedList<>();
+        withdrawnRoutes.add(IpPrefix.valueOf("0.0.0.0/0"));
+        withdrawnRoutes.add(IpPrefix.valueOf("50.0.0.0/32"));
+
+        // Write the routes
+        message = peerChannelHandler.prepareBgpUpdate(nextHopRouter,
+                                                      addedRoutes,
+                                                      withdrawnRoutes);
+        peerChannelHandler.savedCtx.getChannel().write(message);
+
+        // Check that the routes have been received, processed and stored
+        bgpRibIn = waitForBgpRibIn(bgpSession, 3);
+        assertThat(bgpRibIn, hasSize(3));
+        bgpRoutes = waitForBgpRoutes(3);
+        assertThat(bgpRoutes, hasSize(3));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("20.0.0.0/8"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("30.0.0.0/16"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+        //
+        bgpRouteEntry =
+            new BgpRouteEntry(bgpSession,
+                              IpPrefix.valueOf("40.0.0.0/24"),
+                              nextHopRouter,
+                              (byte) BgpConstants.Update.Origin.IGP,
+                              asPath,
+                              DEFAULT_LOCAL_PREF);
+        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
+        assertThat(bgpRibIn, hasItem(bgpRouteEntry));
+
+        // Close the channel and test there are no routes
+        peerChannelHandler.closeChannel();
+        bgpRoutes = waitForBgpRoutes(0);
+        assertThat(bgpRoutes, hasSize(0));
+    }
+}
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/PathSegmentTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/PathSegmentTest.java
new file mode 100644
index 0000000..636883e
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/PathSegmentTest.java
@@ -0,0 +1,115 @@
+package org.onlab.onos.sdnip.bgp;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for the BgpRouteEntry.PathSegment class.
+ */
+public class PathSegmentTest {
+    /**
+     * Generates a Path Segment.
+     *
+     * @return a generated PathSegment
+     */
+    private BgpRouteEntry.PathSegment generatePathSegment() {
+        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
+        segmentAsNumbers.add((long) 1);
+        segmentAsNumbers.add((long) 2);
+        segmentAsNumbers.add((long) 3);
+        BgpRouteEntry.PathSegment pathSegment =
+            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
+
+        return pathSegment;
+    }
+
+    /**
+     * Tests valid class constructor.
+     */
+    @Test
+    public void testConstructor() {
+        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
+
+        String expectedString =
+            "PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}";
+        assertThat(pathSegment.toString(), is(expectedString));
+    }
+
+    /**
+     * Tests invalid class constructor for null Segment AS Numbers.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullSegmentAsNumbers() {
+        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers = null;
+        new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
+    }
+
+    /**
+     * Tests getting the fields of a Path Segment.
+     */
+    @Test
+    public void testGetFields() {
+        // Create the fields to compare against
+        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
+        segmentAsNumbers.add((long) 1);
+        segmentAsNumbers.add((long) 2);
+        segmentAsNumbers.add((long) 3);
+
+        // Generate the entry to test
+        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
+
+        assertThat(pathSegment.getType(), is(pathSegmentType));
+        assertThat(pathSegment.getSegmentAsNumbers(), is(segmentAsNumbers));
+    }
+
+    /**
+     * Tests equality of {@link BgpRouteEntry.PathSegment}.
+     */
+    @Test
+    public void testEquality() {
+        BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
+        BgpRouteEntry.PathSegment pathSegment2 = generatePathSegment();
+
+        assertThat(pathSegment1, is(pathSegment2));
+    }
+
+    /**
+     * Tests non-equality of {@link BgpRouteEntry.PathSegment}.
+     */
+    @Test
+    public void testNonEquality() {
+        BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
+
+        // Setup Path Segment 2
+        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
+        segmentAsNumbers.add((long) 1);
+        segmentAsNumbers.add((long) 22);                        // Different
+        segmentAsNumbers.add((long) 3);
+        //
+        BgpRouteEntry.PathSegment pathSegment2 =
+            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
+
+        assertThat(pathSegment1, is(not(pathSegment2)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
+
+        String expectedString =
+            "PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}";
+        assertThat(pathSegment.toString(), is(expectedString));
+    }
+}
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java
new file mode 100644
index 0000000..1b51d52
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java
@@ -0,0 +1,250 @@
+package org.onlab.onos.sdnip.bgp;
+
+import java.util.Collection;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.SimpleChannelHandler;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Class for handling the remote BGP Peer session.
+ */
+class TestBgpPeerChannelHandler extends SimpleChannelHandler {
+    static final long PEER_AS = 65001;
+    static final int PEER_HOLDTIME = 120;       // 120 seconds
+    final IpAddress bgpId;                     // The BGP ID
+    final long localPref;                       // Local preference for routes
+    final long multiExitDisc = 20;              // MED value
+
+    ChannelHandlerContext savedCtx;
+
+    /**
+     * Constructor for given BGP ID.
+     *
+     * @param bgpId the BGP ID to use
+     * @param localPref the local preference for the routes to use
+     */
+    TestBgpPeerChannelHandler(IpAddress bgpId,
+                              long localPref) {
+        this.bgpId = bgpId;
+        this.localPref = localPref;
+    }
+
+    /**
+     * Closes the channel.
+     */
+    void closeChannel() {
+        savedCtx.getChannel().close();
+    }
+
+    @Override
+    public void channelConnected(ChannelHandlerContext ctx,
+                                 ChannelStateEvent channelEvent) {
+        this.savedCtx = ctx;
+        // Prepare and transmit BGP OPEN message
+        ChannelBuffer message = prepareBgpOpen();
+        ctx.getChannel().write(message);
+
+        // Prepare and transmit BGP KEEPALIVE message
+        message = prepareBgpKeepalive();
+        ctx.getChannel().write(message);
+    }
+
+    @Override
+    public void channelDisconnected(ChannelHandlerContext ctx,
+                                    ChannelStateEvent channelEvent) {
+        // Nothing to do
+    }
+
+    /**
+     * Prepares BGP OPEN message.
+     *
+     * @return the message to transmit (BGP header included)
+     */
+    ChannelBuffer prepareBgpOpen() {
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+        message.writeByte(BgpConstants.BGP_VERSION);
+        message.writeShort((int) PEER_AS);
+        message.writeShort(PEER_HOLDTIME);
+        message.writeInt(bgpId.toInt());
+        message.writeByte(0);                   // No Optional Parameters
+        return prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN, message);
+    }
+
+    /**
+     * Prepares BGP UPDATE message.
+     *
+     * @param nextHopRouter the next-hop router address for the routes to add
+     * @param addedRoutes the routes to add
+     * @param withdrawnRoutes the routes to withdraw
+     * @return the message to transmit (BGP header included)
+     */
+    ChannelBuffer prepareBgpUpdate(IpAddress nextHopRouter,
+                                   Collection<IpPrefix> addedRoutes,
+                                   Collection<IpPrefix> withdrawnRoutes) {
+        int attrFlags;
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+        ChannelBuffer pathAttributes =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+
+        // Encode the Withdrawn Routes
+        ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
+        message.writeShort(encodedPrefixes.readableBytes());
+        message.writeBytes(encodedPrefixes);
+
+        // Encode the Path Attributes
+        // ORIGIN: IGP
+        attrFlags = 0x40;                               // Transitive flag
+        pathAttributes.writeByte(attrFlags);
+        pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
+        pathAttributes.writeByte(1);                    // Data length
+        pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
+        // AS_PATH: Two Path Segments of 3 ASes each
+        attrFlags = 0x40;                               // Transitive flag
+        pathAttributes.writeByte(attrFlags);
+        pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
+        pathAttributes.writeByte(16);                   // Data length
+        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+        pathAttributes.writeByte(pathSegmentType1);
+        pathAttributes.writeByte(3);                    // Three ASes
+        pathAttributes.writeShort(65010);               // AS=65010
+        pathAttributes.writeShort(65020);               // AS=65020
+        pathAttributes.writeShort(65030);               // AS=65030
+        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+        pathAttributes.writeByte(pathSegmentType2);
+        pathAttributes.writeByte(3);                    // Three ASes
+        pathAttributes.writeShort(65041);               // AS=65041
+        pathAttributes.writeShort(65042);               // AS=65042
+        pathAttributes.writeShort(65043);               // AS=65043
+        // NEXT_HOP: nextHopRouter
+        attrFlags = 0x40;                               // Transitive flag
+        pathAttributes.writeByte(attrFlags);
+        pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
+        pathAttributes.writeByte(4);                    // Data length
+        pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
+        // LOCAL_PREF: localPref
+        attrFlags = 0x40;                               // Transitive flag
+        pathAttributes.writeByte(attrFlags);
+        pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
+        pathAttributes.writeByte(4);                    // Data length
+        pathAttributes.writeInt((int) localPref);       // Preference value
+        // MULTI_EXIT_DISC: multiExitDisc
+        attrFlags = 0x80;                               // Optional
+                                                        // Non-Transitive flag
+        pathAttributes.writeByte(attrFlags);
+        pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
+        pathAttributes.writeByte(4);                    // Data length
+        pathAttributes.writeInt((int) multiExitDisc);   // Preference value
+        // The NLRI prefixes
+        encodedPrefixes = encodePackedPrefixes(addedRoutes);
+
+        // Write the Path Attributes, beginning with its length
+        message.writeShort(pathAttributes.readableBytes());
+        message.writeBytes(pathAttributes);
+        message.writeBytes(encodedPrefixes);
+
+        return prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE, message);
+    }
+
+    /**
+     * Encodes a collection of IPv4 network prefixes in a packed format.
+     * <p>
+     * The IPv4 prefixes are encoded in the form:
+     * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
+     * and Prefix is the IPv4 prefix (padded with trailing bits to the end
+     * of an octet).
+     *
+     * @param prefixes the prefixes to encode
+     * @return the buffer with the encoded prefixes
+     */
+    private ChannelBuffer encodePackedPrefixes(Collection<IpPrefix> prefixes) {
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+
+        // Write each of the prefixes
+        for (IpPrefix prefix : prefixes) {
+            int prefixBitlen = prefix.prefixLength();
+            int prefixBytelen = (prefixBitlen + 7) / 8;         // Round-up
+            message.writeByte(prefixBitlen);
+
+            IpAddress address = prefix.toIpAddress();
+            long value = address.toInt() & 0xffffffffL;
+            for (int i = 0; i < IpAddress.INET_LEN; i++) {
+                if (prefixBytelen-- == 0) {
+                    break;
+                }
+                long nextByte =
+                    (value >> ((IpAddress.INET_LEN - i - 1) * 8)) & 0xff;
+                message.writeByte((int) nextByte);
+            }
+        }
+
+        return message;
+    }
+
+    /**
+     * Prepares BGP KEEPALIVE message.
+     *
+     * @return the message to transmit (BGP header included)
+     */
+    ChannelBuffer prepareBgpKeepalive() {
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+        return prepareBgpMessage(BgpConstants.BGP_TYPE_KEEPALIVE, message);
+    }
+
+    /**
+     * Prepares BGP NOTIFICATION message.
+     *
+     * @param errorCode the BGP NOTIFICATION Error Code
+     * @param errorSubcode the BGP NOTIFICATION Error Subcode if applicable,
+     * otherwise BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC
+     * @param payload the BGP NOTIFICATION Data if applicable, otherwise null
+     * @return the message to transmit (BGP header included)
+     */
+    ChannelBuffer prepareBgpNotification(int errorCode, int errorSubcode,
+                                         ChannelBuffer data) {
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+        // Prepare the NOTIFICATION message payload
+        message.writeByte(errorCode);
+        message.writeByte(errorSubcode);
+        if (data != null) {
+            message.writeBytes(data);
+        }
+        return prepareBgpMessage(BgpConstants.BGP_TYPE_NOTIFICATION, message);
+    }
+
+    /**
+     * Prepares BGP message.
+     *
+     * @param type the BGP message type
+     * @param payload the message payload to transmit (BGP header excluded)
+     * @return the message to transmit (BGP header included)
+     */
+    private ChannelBuffer prepareBgpMessage(int type, ChannelBuffer payload) {
+        ChannelBuffer message =
+            ChannelBuffers.buffer(BgpConstants.BGP_HEADER_LENGTH +
+                                  payload.readableBytes());
+
+        // Write the marker
+        for (int i = 0; i < BgpConstants.BGP_HEADER_MARKER_LENGTH; i++) {
+            message.writeByte(0xff);
+        }
+
+        // Write the rest of the BGP header
+        message.writeShort(BgpConstants.BGP_HEADER_LENGTH +
+                           payload.readableBytes());
+        message.writeByte(type);
+
+        // Write the payload
+        message.writeBytes(payload);
+        return message;
+    }
+}
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerFrameDecoder.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerFrameDecoder.java
new file mode 100644
index 0000000..42bbb90
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerFrameDecoder.java
@@ -0,0 +1,163 @@
+package org.onlab.onos.sdnip.bgp;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Class for handling the decoding of the BGP messages at the remote
+ * BGP peer session.
+ */
+class TestBgpPeerFrameDecoder extends FrameDecoder {
+    int remoteBgpVersion;               // 1 octet
+    long remoteAs;                      // 2 octets
+    long remoteHoldtime;                // 2 octets
+    IpAddress remoteBgpIdentifier;     // 4 octets -> IPv4 address
+
+    final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
+    final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
+
+    @Override
+    protected Object decode(ChannelHandlerContext ctx,
+                            Channel channel,
+                            ChannelBuffer buf) throws Exception {
+        // Test for minimum length of the BGP message
+        if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
+            // No enough data received
+            return null;
+        }
+
+        //
+        // Mark the current buffer position in case we haven't received
+        // the whole message.
+        //
+        buf.markReaderIndex();
+
+        //
+        // Read and check the BGP message Marker field: it must be all ones
+        //
+        byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
+        buf.readBytes(marker);
+        for (int i = 0; i < marker.length; i++) {
+            if (marker[i] != (byte) 0xff) {
+                // ERROR: Connection Not Synchronized. Close the channel.
+                ctx.getChannel().close();
+                return null;
+            }
+        }
+
+        //
+        // Read and check the BGP message Length field
+        //
+        int length = buf.readUnsignedShort();
+        if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
+            (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
+            // ERROR: Bad Message Length. Close the channel.
+            ctx.getChannel().close();
+            return null;
+        }
+
+        //
+        // Test whether the rest of the message is received:
+        // So far we have read the Marker (16 octets) and the
+        // Length (2 octets) fields.
+        //
+        int remainingMessageLen =
+            length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
+        if (buf.readableBytes() < remainingMessageLen) {
+            // No enough data received
+            buf.resetReaderIndex();
+            return null;
+        }
+
+        //
+        // Read the BGP message Type field, and process based on that type
+        //
+        int type = buf.readUnsignedByte();
+        remainingMessageLen--;      // Adjust after reading the type
+        ChannelBuffer message = buf.readBytes(remainingMessageLen);
+
+        //
+        // Process the remaining of the message based on the message type
+        //
+        switch (type) {
+        case BgpConstants.BGP_TYPE_OPEN:
+            processBgpOpen(ctx, message);
+            break;
+        case BgpConstants.BGP_TYPE_UPDATE:
+            // NOTE: Not used as part of the test, because ONOS does not
+            // originate UPDATE messages.
+            break;
+        case BgpConstants.BGP_TYPE_NOTIFICATION:
+            // NOTE: Not used as part of the testing (yet)
+            break;
+        case BgpConstants.BGP_TYPE_KEEPALIVE:
+            processBgpKeepalive(ctx, message);
+            break;
+        default:
+            // ERROR: Bad Message Type. Close the channel.
+            ctx.getChannel().close();
+            return null;
+        }
+
+        return null;
+    }
+
+    /**
+     * Processes BGP OPEN message.
+     *
+     * @param ctx the Channel Handler Context.
+     * @param message the message to process.
+     */
+    private void processBgpOpen(ChannelHandlerContext ctx,
+                                ChannelBuffer message) {
+        int minLength =
+            BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
+        if (message.readableBytes() < minLength) {
+            // ERROR: Bad Message Length. Close the channel.
+            ctx.getChannel().close();
+            return;
+        }
+
+        //
+        // Parse the OPEN message
+        //
+        remoteBgpVersion = message.readUnsignedByte();
+        remoteAs = message.readUnsignedShort();
+        remoteHoldtime = message.readUnsignedShort();
+        remoteBgpIdentifier = IpAddress.valueOf((int) message.readUnsignedInt());
+        // Optional Parameters
+        int optParamLen = message.readUnsignedByte();
+        if (message.readableBytes() < optParamLen) {
+            // ERROR: Bad Message Length. Close the channel.
+            ctx.getChannel().close();
+            return;
+        }
+        message.readBytes(optParamLen);             // NOTE: data ignored
+
+        // BGP OPEN message successfully received
+        receivedOpenMessageLatch.countDown();
+    }
+
+    /**
+     * Processes BGP KEEPALIVE message.
+     *
+     * @param ctx the Channel Handler Context.
+     * @param message the message to process.
+     */
+    private void processBgpKeepalive(ChannelHandlerContext ctx,
+                                     ChannelBuffer message) {
+        if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
+            BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
+            // ERROR: Bad Message Length. Close the channel.
+            ctx.getChannel().close();
+            return;
+        }
+        // BGP KEEPALIVE message successfully received
+        receivedKeepaliveMessageLatch.countDown();
+    }
+}
