Moved BGP code and Router code into their own bundle.
The main goal of this is to allow routing code to be used by multiple
applications.
Changes include:
* Created an onos-app-routing bundle and moved BGP code and routing code
into it.
* Created an onos-app-routing-api bundle as a common API bundle between
onos-app-routing and onos-app-sdnip, to prevent circular dependencies.
* Moved API classes into onos-app-routing-api bundle.
* Made Router and BgpSessionManager into OSGi components. This is not quite
clean, because there is still a chain of start() method calls from SdnIp
through to BgpSessionManager to preserve startup order. This should be
revisted so components can be started using activate()
* Created BgpService and RoutingService APIs to glue different components
together.
* Many unit test changes. A lot of the previous unit tests spanned the
Router and IntentSynchronizer classes, but this is not possible any more
since these classes are in different bundles. I had to rewrite some of
these tests so that each unit test class only tests one real class. A
nice side-effect is that the tests are now simpler because each test
tests less functionality.
* Removed SdnIp test seeing as it doesn't run automatically, was already
broken and has been largely superseded by other unit tests and the nightly
functional tests.
Change-Id: I70ecf5391aa353e99e7cdcf7ed38a530c87571bb
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
index e4808f7..d13aa2a 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
@@ -16,9 +16,8 @@
package org.onosproject.sdnip;
import com.google.common.collect.Sets;
-import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
-import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
-import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
+import org.easymock.EasyMock;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
@@ -32,18 +31,12 @@
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Intent;
@@ -51,10 +44,18 @@
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.net.provider.ProviderId;
+import org.onosproject.routingapi.FibEntry;
+import org.onosproject.routingapi.FibUpdate;
+import org.onosproject.routingapi.RouteEntry;
+import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
+import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
+import org.onosproject.sdnip.config.SdnIpConfigurationService;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -71,9 +72,9 @@
*/
public class IntentSyncTest extends AbstractIntentTest {
+ private SdnIpConfigurationService sdnIpConfigService;
private InterfaceService interfaceService;
private IntentService intentService;
- private HostService hostService;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
@@ -87,8 +88,11 @@
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
+ private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
+ DeviceId.deviceId("of:0000000000000004"),
+ PortNumber.portNumber(1));
+
private IntentSynchronizer intentSynchronizer;
- private Router router;
private static final ApplicationId APPID = new ApplicationId() {
@Override
@@ -106,12 +110,42 @@
public void setUp() throws Exception {
super.setUp();
setUpInterfaceService();
- setUpHostService();
+
+ setUpBgpPeers();
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
- null, interfaceService);
- router = new Router(intentSynchronizer, hostService);
+ sdnIpConfigService, interfaceService);
+ }
+
+ /**
+ * Sets up BGP peers in external networks.
+ */
+ private void setUpBgpPeers() {
+
+ Map<IpAddress, BgpPeer> peers = new HashMap<>();
+
+ String peerSw1Eth1 = "192.168.10.1";
+ peers.put(IpAddress.valueOf(peerSw1Eth1),
+ new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
+
+ // Two BGP peers are connected to switch 2 port 1.
+ String peer1Sw2Eth1 = "192.168.20.1";
+ peers.put(IpAddress.valueOf(peer1Sw2Eth1),
+ new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
+
+ String peer2Sw2Eth1 = "192.168.20.2";
+ peers.put(IpAddress.valueOf(peer2Sw2Eth1),
+ new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
+
+ String peer1Sw4Eth1 = "192.168.40.1";
+ peers.put(IpAddress.valueOf(peer1Sw4Eth1),
+ new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
+
+ sdnIpConfigService = createMock(SdnIpConfigurationService.class);
+ expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
+ EasyMock.replay(sdnIpConfigService);
+
}
/**
@@ -133,80 +167,279 @@
interfaces.add(sw1Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
- interfaceIpAddresses2.add(new InterfaceIpAddress(
- IpAddress.valueOf("192.168.20.101"),
- IpPrefix.valueOf("192.168.20.0/24")));
+ interfaceIpAddresses2.add(
+ new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
+ IpPrefix.valueOf("192.168.20.0/24")));
Interface sw2Eth1 = new Interface(SW2_ETH1,
interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
VlanId.NONE);
interfaces.add(sw2Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
- interfaceIpAddresses3.add(new InterfaceIpAddress(
- IpAddress.valueOf("192.168.30.101"),
- IpPrefix.valueOf("192.168.30.0/24")));
+ interfaceIpAddresses3.add(
+ new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
+ IpPrefix.valueOf("192.168.30.0/24")));
Interface sw3Eth1 = new Interface(SW3_ETH1,
interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
VlanId.NONE);
interfaces.add(sw3Eth1);
+ InterfaceIpAddress interfaceIpAddress4 =
+ new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
+ IpPrefix.valueOf("192.168.40.0/24"));
+ Interface sw4Eth1 = new Interface(SW4_ETH1,
+ Sets.newHashSet(interfaceIpAddress4),
+ MacAddress.valueOf("00:00:00:00:00:04"),
+ VlanId.vlanId((short) 1));
+
+ expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
+ interfaces.add(sw4Eth1);
+
expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
sw1Eth1).anyTimes();
expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
sw2Eth1).anyTimes();
expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
sw3Eth1).anyTimes();
- expect(interfaceService.getInterfaces()).andReturn(
- interfaces).anyTimes();
+ expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
replay(interfaceService);
}
/**
- * Sets up the host service with details of hosts.
+ * Tests adding a FIB entry to the IntentSynchronizer.
+ *
+ * We verify that the synchronizer records the correct state and that the
+ * correct intent is submitted to the IntentService.
+ *
+ * @throws TestUtilsException
*/
- private void setUpHostService() {
- hostService = createMock(HostService.class);
+ @Test
+ public void testFibAdd() throws TestUtilsException {
+ FibEntry fibEntry = new FibEntry(
+ Ip4Prefix.valueOf("1.1.1.0/24"),
+ Ip4Address.valueOf("192.168.10.1"),
+ MacAddress.valueOf("00:00:00:00:00:01"));
- hostService.addListener(anyObject(HostListener.class));
- expectLastCall().anyTimes();
+ // Construct a MultiPointToSinglePointIntent intent
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
+ fibEntry.prefix());
- IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
- Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
- MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
- new HostLocation(SW1_ETH1, 1),
- Sets.newHashSet(host1Address));
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder();
+ treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
- expect(hostService.getHostsByIp(host1Address))
- .andReturn(Sets.newHashSet(host1)).anyTimes();
- hostService.startMonitoringIp(host1Address);
- expectLastCall().anyTimes();
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+ ingressPoints.add(SW2_ETH1);
+ ingressPoints.add(SW3_ETH1);
+ ingressPoints.add(SW4_ETH1);
+
+ MultiPointToSinglePointIntent intent =
+ new MultiPointToSinglePointIntent(APPID,
+ selectorBuilder.build(), treatmentBuilder.build(),
+ ingressPoints, SW1_ETH1);
+
+ // Setup the expected intents
+ IntentOperations.Builder builder = IntentOperations.builder(APPID);
+ builder.addSubmitOperation(intent);
+ intentService.execute(TestIntentServiceHelper.eqExceptId(
+ builder.build()));
+ replay(intentService);
+
+ intentSynchronizer.leaderChanged(true);
+ TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+
+ FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
+ fibEntry);
+ intentSynchronizer.update(Collections.singleton(fibUpdate),
+ Collections.emptyList());
+
+ Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+ Intent firstIntent =
+ intentSynchronizer.getRouteIntents().iterator().next();
+ IntentKey firstIntentKey = new IntentKey(firstIntent);
+ IntentKey intentKey = new IntentKey(intent);
+ assertTrue(firstIntentKey.equals(intentKey));
+ verify(intentService);
+ }
+
+ /**
+ * Tests adding a FIB entry with to a next hop in a VLAN.
+ *
+ * We verify that the synchronizer records the correct state and that the
+ * correct intent is submitted to the IntentService.
+ *
+ * @throws TestUtilsException
+ */
+ @Test
+ public void testFibAddWithVlan() throws TestUtilsException {
+ FibEntry fibEntry = new FibEntry(
+ Ip4Prefix.valueOf("3.3.3.0/24"),
+ Ip4Address.valueOf("192.168.40.1"),
+ MacAddress.valueOf("00:00:00:00:00:04"));
+
+ // Construct a MultiPointToSinglePointIntent intent
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(fibEntry.prefix())
+ .matchVlanId(VlanId.ANY);
+
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder();
+ treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:04"))
+ .setVlanId(VlanId.vlanId((short) 1));
+
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+ ingressPoints.add(SW1_ETH1);
+ ingressPoints.add(SW2_ETH1);
+ ingressPoints.add(SW3_ETH1);
+
+ MultiPointToSinglePointIntent intent =
+ new MultiPointToSinglePointIntent(APPID,
+ selectorBuilder.build(), treatmentBuilder.build(),
+ ingressPoints, SW4_ETH1);
+
+ // Setup the expected intents
+ IntentOperations.Builder builder = IntentOperations.builder(APPID);
+ builder.addSubmitOperation(intent);
+ intentService.execute(
+ TestIntentServiceHelper.eqExceptId(builder.build()));
+ replay(intentService);
+
+ // Run the test
+ intentSynchronizer.leaderChanged(true);
+ TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+ FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
+
+ intentSynchronizer.update(Collections.singleton(fibUpdate),
+ Collections.emptyList());
+
+ // Verify
+ Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+ Intent firstIntent =
+ intentSynchronizer.getRouteIntents().iterator().next();
+ IntentKey firstIntentKey = new IntentKey(firstIntent);
+ IntentKey intentKey = new IntentKey(intent);
+ assertTrue(firstIntentKey.equals(intentKey));
+ verify(intentService);
+ }
+
+ /**
+ * Tests updating a FIB entry.
+ *
+ * We verify that the synchronizer records the correct state and that the
+ * correct intent is submitted to the IntentService.
+ *
+ * @throws TestUtilsException
+ */
+ @Test
+ public void testFibUpdate() throws TestUtilsException {
+ // Firstly add a route
+ testFibAdd();
+
+ Intent addedIntent =
+ intentSynchronizer.getRouteIntents().iterator().next();
+
+ // Start to construct a new route entry and new intent
+ FibEntry fibEntryUpdate = new FibEntry(
+ Ip4Prefix.valueOf("1.1.1.0/24"),
+ Ip4Address.valueOf("192.168.20.1"),
+ MacAddress.valueOf("00:00:00:00:00:02"));
+
+ // Construct a new MultiPointToSinglePointIntent intent
+ TrafficSelector.Builder selectorBuilderNew =
+ DefaultTrafficSelector.builder();
+ selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
+ fibEntryUpdate.prefix());
+
+ TrafficTreatment.Builder treatmentBuilderNew =
+ DefaultTrafficTreatment.builder();
+ treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
- IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
- Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
- MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
- new HostLocation(SW2_ETH1, 1),
- Sets.newHashSet(host2Address));
+ Set<ConnectPoint> ingressPointsNew = new HashSet<>();
+ ingressPointsNew.add(SW1_ETH1);
+ ingressPointsNew.add(SW3_ETH1);
+ ingressPointsNew.add(SW4_ETH1);
- expect(hostService.getHostsByIp(host2Address))
- .andReturn(Sets.newHashSet(host2)).anyTimes();
- hostService.startMonitoringIp(host2Address);
- expectLastCall().anyTimes();
+ MultiPointToSinglePointIntent intentNew =
+ new MultiPointToSinglePointIntent(APPID,
+ selectorBuilderNew.build(),
+ treatmentBuilderNew.build(),
+ ingressPointsNew, SW2_ETH1);
+ // Set up test expectation
+ reset(intentService);
+ // Setup the expected intents
+ IntentOperations.Builder builder = IntentOperations.builder(APPID);
+ builder.addWithdrawOperation(addedIntent.id());
+ intentService.execute(TestIntentServiceHelper.eqExceptId(
+ builder.build()));
+ builder = IntentOperations.builder(APPID);
+ builder.addSubmitOperation(intentNew);
+ intentService.execute(TestIntentServiceHelper.eqExceptId(
+ builder.build()));
+ replay(intentService);
- IpAddress host3Address = IpAddress.valueOf("192.168.30.1");
- Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
- MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE,
- new HostLocation(SW3_ETH1, 1),
- Sets.newHashSet(host3Address));
+ // Call the update() method in IntentSynchronizer class
+ intentSynchronizer.leaderChanged(true);
+ TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+ FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
+ fibEntryUpdate);
+ intentSynchronizer.update(Collections.singletonList(fibUpdate),
+ Collections.emptyList());
- expect(hostService.getHostsByIp(host3Address))
- .andReturn(Sets.newHashSet(host3)).anyTimes();
- hostService.startMonitoringIp(host3Address);
- expectLastCall().anyTimes();
+ // Verify
+ Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+ Intent firstIntent =
+ intentSynchronizer.getRouteIntents().iterator().next();
+ IntentKey firstIntentKey = new IntentKey(firstIntent);
+ IntentKey intentNewKey = new IntentKey(intentNew);
+ assertTrue(firstIntentKey.equals(intentNewKey));
+ verify(intentService);
+ }
+ /**
+ * Tests deleting a FIB entry.
+ *
+ * We verify that the synchronizer records the correct state and that the
+ * correct intent is withdrawn from the IntentService.
+ *
+ * @throws TestUtilsException
+ */
+ @Test
+ public void testFibDelete() throws TestUtilsException {
+ // Firstly add a route
+ testFibAdd();
- replay(hostService);
+ Intent addedIntent =
+ intentSynchronizer.getRouteIntents().iterator().next();
+
+ // Construct the existing route entry
+ FibEntry fibEntry = new FibEntry(
+ Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
+
+ // Set up expectation
+ reset(intentService);
+ // Setup the expected intents
+ IntentOperations.Builder builder = IntentOperations.builder(APPID);
+ builder.addWithdrawOperation(addedIntent.id());
+ intentService.execute(TestIntentServiceHelper.eqExceptId(
+ builder.build()));
+ replay(intentService);
+
+ // Call the update() method in IntentSynchronizer class
+ intentSynchronizer.leaderChanged(true);
+ TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+ FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
+ intentSynchronizer.update(Collections.emptyList(),
+ Collections.singletonList(fibUpdate));
+
+ // Verify
+ Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
+ verify(intentService);
}
/**
@@ -287,25 +520,7 @@
MultiPointToSinglePointIntent intent6 = intentBuilder(
routeEntry6.prefix(), "00:00:00:00:00:01", SW1_ETH1);
- // Set up the ribTable field in Router class and routeIntents fields
- // in IntentSynchronizer class
- InvertedRadixTree<RouteEntry> ribTable =
- new ConcurrentInvertedRadixTree<>(
- new DefaultByteArrayNodeFactory());
- ribTable.put(RouteEntry.createBinaryString(routeEntry1.prefix()),
- routeEntry1);
- ribTable.put(RouteEntry.createBinaryString(routeEntry3.prefix()),
- routeEntry3);
- ribTable.put(RouteEntry.createBinaryString(routeEntry4Update.prefix()),
- routeEntry4Update);
- ribTable.put(RouteEntry.createBinaryString(routeEntry5.prefix()),
- routeEntry5);
- ribTable.put(RouteEntry.createBinaryString(routeEntry6.prefix()),
- routeEntry6);
- ribTable.put(RouteEntry.createBinaryString(routeEntry7.prefix()),
- routeEntry7);
- TestUtils.setField(router, "ribTable4", ribTable);
-
+ // Set up the routeIntents field in IntentSynchronizer class
ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
routeIntents = new ConcurrentHashMap<>();
routeIntents.put(routeEntry1.prefix(), intent1);
@@ -353,20 +568,9 @@
// Start the test
intentSynchronizer.leaderChanged(true);
- /*
- TestUtils.callMethod(intentSynchronizer, "synchronizeIntents",
- new Class<?>[] {});
- */
intentSynchronizer.synchronizeIntents();
// Verify
- assertEquals(router.getRoutes4().size(), 6);
- assertTrue(router.getRoutes4().contains(routeEntry1));
- assertTrue(router.getRoutes4().contains(routeEntry3));
- assertTrue(router.getRoutes4().contains(routeEntry4Update));
- assertTrue(router.getRoutes4().contains(routeEntry5));
- assertTrue(router.getRoutes4().contains(routeEntry6));
-
assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
assertTrue(intentSynchronizer.getRouteIntents().contains(intent3));