diff options
Diffstat (limited to 'framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java')
-rw-r--r-- | framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java new file mode 100644 index 00000000..d89c3c2b --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java @@ -0,0 +1,565 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sdnip; + +import com.google.common.collect.Sets; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onlab.junit.TestUtils; +import org.onlab.junit.TestUtils.TestUtilsException; +import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv4; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onlab.packet.MacAddress; +import org.onlab.packet.TpPort; +import org.onlab.packet.VlanId; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.intf.InterfaceService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +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.InterfaceIpAddress; +import org.onosproject.net.intent.AbstractIntentTest; +import org.onosproject.net.intent.Intent; +import org.onosproject.net.intent.IntentService; +import org.onosproject.net.intent.PointToPointIntent; +import org.onosproject.routing.config.BgpConfig; +import org.onosproject.routing.config.BgpPeer; +import org.onosproject.routing.config.BgpSpeaker; +import org.onosproject.routing.config.InterfaceAddress; +import org.onosproject.routing.config.RoutingConfigurationService; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; +import static org.onosproject.sdnip.TestIntentServiceHelper.eqExceptId; + +/** + * Unit tests for PeerConnectivityManager. + */ +public class PeerConnectivityManagerTest extends AbstractIntentTest { + + private static final ApplicationId APPID = new ApplicationId() { + @Override + public short id() { + return 0; + } + + @Override + public String name() { + return "foo"; + } + }; + + private static final ApplicationId CONFIG_APP_ID = APPID; + + private PeerConnectivityManager peerConnectivityManager; + private IntentSynchronizer intentSynchronizer; + private RoutingConfigurationService routingConfig; + private InterfaceService interfaceService; + private NetworkConfigService networkConfigService; + private IntentService intentService; + + private Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers; + private Map<String, Interface> interfaces; + private Map<IpAddress, BgpPeer> peers; + + private BgpConfig bgpConfig; + + private Map<String, Interface> configuredInterfaces; + private Map<IpAddress, BgpPeer> configuredPeers; + private List<PointToPointIntent> intentList; + + private final String dpid1 = "00:00:00:00:00:00:00:01"; + private final String dpid2 = "00:00:00:00:00:00:00:02"; + + private final DeviceId deviceId1 = + DeviceId.deviceId(SdnIp.dpidToUri(dpid1)); + private final DeviceId deviceId2 = + DeviceId.deviceId(SdnIp.dpidToUri(dpid2)); + + // Interfaces connected to BGP speakers + private final ConnectPoint s1Eth100 = + new ConnectPoint(deviceId1, PortNumber.portNumber(100)); + private final ConnectPoint s2Eth100 = + new ConnectPoint(deviceId2, PortNumber.portNumber(100)); + + // Interfaces connected to BGP peers + private final ConnectPoint s1Eth1 = + new ConnectPoint(deviceId1, PortNumber.portNumber(1)); + private final ConnectPoint s2Eth1 = + new ConnectPoint(deviceId2, PortNumber.portNumber(1)); + + private final TrafficTreatment noTreatment = + DefaultTrafficTreatment.emptyTreatment(); + + @Before + public void setUp() throws Exception { + super.setUp(); + routingConfig = createMock(RoutingConfigurationService.class); + interfaceService = createMock(InterfaceService.class); + networkConfigService = createMock(NetworkConfigService.class); + bgpConfig = createMock(BgpConfig.class); + + // These will set expectations on routingConfig and interfaceService + bgpSpeakers = setUpBgpSpeakers(); + interfaces = Collections.unmodifiableMap(setUpInterfaces()); + peers = Collections.unmodifiableMap(setUpPeers()); + + initPeerConnectivity(); + intentList = setUpIntentList(); + } + + /** + * Sets up BGP speakers. + * + * @return configured BGP speakers as a map from speaker name to speaker + */ + private Set<BgpConfig.BgpSpeakerConfig> setUpBgpSpeakers() { + + BgpConfig.BgpSpeakerConfig speaker1 = new BgpConfig.BgpSpeakerConfig( + Optional.empty(), + s1Eth100, Collections.singleton(IpAddress.valueOf("192.168.10.1"))); + + BgpConfig.BgpSpeakerConfig speaker2 = new BgpConfig.BgpSpeakerConfig( + Optional.empty(), + s1Eth100, Sets.newHashSet(IpAddress.valueOf("192.168.20.1"), + IpAddress.valueOf("192.168.30.1"))); + + Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers = Sets.newHashSet(); + bgpSpeakers.add(speaker1); + bgpSpeakers.add(speaker2); + + return bgpSpeakers; + } + + /** + * Sets up logical interfaces, which emulate the configured interfaces + * in SDN-IP application. + * + * @return configured interfaces as a MAP from Interface name to Interface + */ + private Map<String, Interface> setUpInterfaces() { + + configuredInterfaces = new HashMap<>(); + + String interfaceSw1Eth1 = "s1-eth1"; + InterfaceIpAddress ia1 = + new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"), + IpPrefix.valueOf("192.168.10.0/24")); + Interface intfsw1eth1 = new Interface(s1Eth1, + Collections.singleton(ia1), + MacAddress.valueOf("00:00:00:00:00:01"), + VlanId.NONE); + + configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1); + String interfaceSw2Eth1 = "s2-eth1"; + InterfaceIpAddress ia2 = + new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"), + IpPrefix.valueOf("192.168.20.0/24")); + Interface intfsw2eth1 = new Interface(s2Eth1, + Collections.singleton(ia2), + MacAddress.valueOf("00:00:00:00:00:02"), + VlanId.NONE); + configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1); + + String interfaceSw2Eth1intf2 = "s2-eth1_2"; + InterfaceIpAddress ia3 = + new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"), + IpPrefix.valueOf("192.168.30.0/24")); + Interface intfsw2eth1intf2 = new Interface(s2Eth1, + Collections.singleton(ia3), + MacAddress.valueOf("00:00:00:00:00:03"), + VlanId.NONE); + configuredInterfaces.put(interfaceSw2Eth1intf2, intfsw2eth1intf2); + + expect(interfaceService.getInterfacesByPort(s1Eth1)) + .andReturn(Collections.singleton(intfsw1eth1)).anyTimes(); + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101"))) + .andReturn(Collections.singleton(intfsw1eth1)).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1"))) + .andReturn(intfsw1eth1).anyTimes(); + expect(interfaceService.getInterfacesByPort(s2Eth1)) + .andReturn(Collections.singleton(intfsw2eth1)).anyTimes(); + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101"))) + .andReturn(Collections.singleton(intfsw2eth1)).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1"))) + .andReturn(intfsw2eth1).anyTimes(); + + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101"))) + .andReturn(Collections.singleton(intfsw2eth1intf2)).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1"))) + .andReturn(intfsw2eth1intf2).anyTimes(); + + // Non-existent interface used during one of the tests + expect(interfaceService.getInterfacesByPort(new ConnectPoint( + DeviceId.deviceId(SdnIp.dpidToUri("00:00:00:00:00:00:01:00")), + PortNumber.portNumber(1)))) + .andReturn(null).anyTimes(); + + expect(interfaceService.getInterfaces()).andReturn( + Sets.newHashSet(configuredInterfaces.values())).anyTimes(); + + return configuredInterfaces; + } + + /** + * Sets up BGP daemon peers. + * + * @return configured BGP peers as a MAP from peer IP address to BgpPeer + */ + private Map<IpAddress, BgpPeer> setUpPeers() { + + configuredPeers = new HashMap<>(); + + String peerSw1Eth1 = "192.168.10.1"; + configuredPeers.put(IpAddress.valueOf(peerSw1Eth1), + new BgpPeer(dpid1, 1, peerSw1Eth1)); + + // Two BGP peers are connected to switch 2 port 1. + String peer1Sw2Eth1 = "192.168.20.1"; + configuredPeers.put(IpAddress.valueOf(peer1Sw2Eth1), + new BgpPeer(dpid2, 1, peer1Sw2Eth1)); + + String peer2Sw2Eth1 = "192.168.30.1"; + configuredPeers.put(IpAddress.valueOf(peer2Sw2Eth1), + new BgpPeer(dpid2, 1, peer2Sw2Eth1)); + + return configuredPeers; + } + + /** + * Sets up expected point to point intent list. + * + * @return point to point intent list + */ + private List<PointToPointIntent> setUpIntentList() { + + intentList = new ArrayList<>(); + + setUpBgpIntents(); + setUpIcmpIntents(); + + return intentList; + + } + + /** + * Constructs a BGP intent and put it into the intentList. + * <p/> + * The purpose of this method is too simplify the setUpBgpIntents() method, + * and to make the setUpBgpIntents() easy to read. + * + * @param srcPrefix source IP prefix to match + * @param dstPrefix destination IP prefix to match + * @param srcTcpPort source TCP port to match + * @param dstTcpPort destination TCP port to match + * @param srcConnectPoint source connect point for PointToPointIntent + * @param dstConnectPoint destination connect point for PointToPointIntent + */ + private void bgpPathintentConstructor(String srcPrefix, String dstPrefix, + Short srcTcpPort, Short dstTcpPort, + ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) { + + TrafficSelector.Builder builder = DefaultTrafficSelector.builder() + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_TCP) + .matchIPSrc(IpPrefix.valueOf(srcPrefix)) + .matchIPDst(IpPrefix.valueOf(dstPrefix)); + + if (srcTcpPort != null) { + builder.matchTcpSrc(TpPort.tpPort(srcTcpPort)); + } + if (dstTcpPort != null) { + builder.matchTcpDst(TpPort.tpPort(dstTcpPort)); + } + + PointToPointIntent intent = PointToPointIntent.builder() + .appId(APPID) + .selector(builder.build()) + .treatment(noTreatment) + .ingressPoint(srcConnectPoint) + .egressPoint(dstConnectPoint) + .build(); + + intentList.add(intent); + } + + /** + * Sets up intents for BGP paths. + */ + private void setUpBgpIntents() { + + Short bgpPort = 179; + + // Start to build intents between BGP speaker1 and BGP peer1 + bgpPathintentConstructor( + "192.168.10.101/32", "192.168.10.1/32", null, bgpPort, + s1Eth100, s1Eth1); + bgpPathintentConstructor( + "192.168.10.101/32", "192.168.10.1/32", bgpPort, null, + s1Eth100, s1Eth1); + + bgpPathintentConstructor( + "192.168.10.1/32", "192.168.10.101/32", null, bgpPort, + s1Eth1, s1Eth100); + bgpPathintentConstructor( + "192.168.10.1/32", "192.168.10.101/32", bgpPort, null, + s1Eth1, s1Eth100); + + // Start to build intents between BGP speaker1 and BGP peer2 + bgpPathintentConstructor( + "192.168.20.101/32", "192.168.20.1/32", null, bgpPort, + s1Eth100, s2Eth1); + bgpPathintentConstructor( + "192.168.20.101/32", "192.168.20.1/32", bgpPort, null, + s1Eth100, s2Eth1); + + bgpPathintentConstructor( + "192.168.20.1/32", "192.168.20.101/32", null, bgpPort, + s2Eth1, s1Eth100); + bgpPathintentConstructor( + "192.168.20.1/32", "192.168.20.101/32", bgpPort, null, + s2Eth1, s1Eth100); + + // + // Start to build intents between BGP speaker3 and BGP peer1 + bgpPathintentConstructor( + "192.168.30.101/32", "192.168.30.1/32", null, bgpPort, + s1Eth100, s2Eth1); + bgpPathintentConstructor( + "192.168.30.101/32", "192.168.30.1/32", bgpPort, null, + s1Eth100, s2Eth1); + + bgpPathintentConstructor( + "192.168.30.1/32", "192.168.30.101/32", null, bgpPort, + s2Eth1, s1Eth100); + bgpPathintentConstructor( + "192.168.30.1/32", "192.168.30.101/32", bgpPort, null, + s2Eth1, s1Eth100); + } + + /** + * Constructs a BGP intent and put it into the intentList. + * <p/> + * The purpose of this method is too simplify the setUpBgpIntents() method, + * and to make the setUpBgpIntents() easy to read. + * + * @param srcPrefix source IP prefix to match + * @param dstPrefix destination IP prefix to match + * @param srcConnectPoint source connect point for PointToPointIntent + * @param dstConnectPoint destination connect point for PointToPointIntent + */ + private void icmpPathintentConstructor(String srcPrefix, String dstPrefix, + ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) { + + TrafficSelector selector = DefaultTrafficSelector.builder() + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_ICMP) + .matchIPSrc(IpPrefix.valueOf(srcPrefix)) + .matchIPDst(IpPrefix.valueOf(dstPrefix)) + .build(); + + PointToPointIntent intent = PointToPointIntent.builder() + .appId(APPID) + .selector(selector) + .treatment(noTreatment) + .ingressPoint(srcConnectPoint) + .egressPoint(dstConnectPoint) + .build(); + + intentList.add(intent); + } + + /** + * Sets up intents for ICMP paths. + */ + private void setUpIcmpIntents() { + // Start to build intents between BGP speaker1 and BGP peer1 + icmpPathintentConstructor( + "192.168.10.101/32", "192.168.10.1/32", s1Eth100, s1Eth1); + icmpPathintentConstructor( + "192.168.10.1/32", "192.168.10.101/32", s1Eth1, s1Eth100); + + // Start to build intents between BGP speaker1 and BGP peer2 + icmpPathintentConstructor( + "192.168.20.101/32", "192.168.20.1/32", s1Eth100, s2Eth1); + icmpPathintentConstructor( + "192.168.20.1/32", "192.168.20.101/32", s2Eth1, s1Eth100); + + icmpPathintentConstructor( + "192.168.30.101/32", "192.168.30.1/32", s1Eth100, s2Eth1); + icmpPathintentConstructor( + "192.168.30.1/32", "192.168.30.101/32", s2Eth1, s1Eth100); + } + + /** + * Initializes peer connectivity testing environment. + * + * @throws TestUtilsException if exceptions when using TestUtils + */ + private void initPeerConnectivity() throws TestUtilsException { + expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes(); + expect(bgpConfig.bgpSpeakers()).andReturn(bgpSpeakers).anyTimes(); + replay(bgpConfig); + expect(networkConfigService.getConfig(APPID, BgpConfig.class)).andReturn(bgpConfig).anyTimes(); + replay(networkConfigService); + replay(routingConfig); + replay(interfaceService); + + intentService = createMock(IntentService.class); + replay(intentService); + + intentSynchronizer = new IntentSynchronizer(APPID, intentService, + null, routingConfig, + interfaceService); + intentSynchronizer.leaderChanged(true); + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); + + peerConnectivityManager = + new PeerConnectivityManager(APPID, intentSynchronizer, + networkConfigService, + CONFIG_APP_ID, + interfaceService); + } + + /** + * Tests whether peer connectivity manager can set up correct BGP and + * ICMP intents according to specific configuration. + * <p/> + * Two tricky cases included in the configuration are: 2 peers on a same + * switch port, peer on the same switch with BGPd. + */ + @Test + public void testConnectionSetup() { + + reset(intentService); + + // Setup the expected intents + for (Intent intent : intentList) { + intentService.submit(eqExceptId(intent)); + } + replay(intentService); + + // Running the interface to be tested. + peerConnectivityManager.start(); + + verify(intentService); + + } + + /** + * Tests a corner case, when there are no interfaces in the configuration. + */ + @Test + public void testNullInterfaces() { + reset(interfaceService); + + expect(interfaceService.getInterfaces()).andReturn( + Sets.<Interface>newHashSet()).anyTimes(); + expect(interfaceService.getInterfacesByPort(s2Eth1)) + .andReturn(Collections.emptySet()).anyTimes(); + expect(interfaceService.getInterfacesByPort(s1Eth1)) + .andReturn(Collections.emptySet()).anyTimes(); + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101"))) + .andReturn(Collections.emptySet()).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1"))) + .andReturn(null).anyTimes(); + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101"))) + .andReturn(Collections.emptySet()).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1"))) + .andReturn(null).anyTimes(); + expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101"))) + .andReturn(Collections.emptySet()).anyTimes(); + expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1"))) + .andReturn(null).anyTimes(); + + replay(interfaceService); + + reset(intentService); + replay(intentService); + peerConnectivityManager.start(); + verify(intentService); + } + + /** + * Tests a corner case, when there is no BGP speakers in the configuration. + */ + @Test + public void testNullBgpSpeakers() { + reset(routingConfig); + reset(bgpConfig); + + expect(bgpConfig.bgpSpeakers()).andReturn(Collections.emptySet()).anyTimes(); + replay(bgpConfig); + expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes(); + replay(routingConfig); + + reset(intentService); + replay(intentService); + peerConnectivityManager.start(); + verify(intentService); + } + + /** + * Tests a corner case, when there is no Interface configured for one BGP + * peer. + */ + @Test + public void testNoPeerInterface() { + String peerSw100Eth1 = "192.168.200.1"; + configuredPeers.put(IpAddress.valueOf(peerSw100Eth1), + new BgpPeer("00:00:00:00:00:00:01:00", 1, peerSw100Eth1)); + testConnectionSetup(); + } + + /** + * Tests a corner case, when there is no Interface configured for one BGP + * speaker. + */ + @Ignore + @Test + public void testNoSpeakerInterface() { + BgpSpeaker bgpSpeaker100 = new BgpSpeaker( + "bgpSpeaker100", + "00:00:00:00:00:00:01:00", 100, + "00:00:00:00:01:00"); + List<InterfaceAddress> interfaceAddresses100 = new LinkedList<>(); + interfaceAddresses100.add(new InterfaceAddress(dpid1, 1, "192.168.10.201")); + interfaceAddresses100.add(new InterfaceAddress(dpid2, 1, "192.168.20.201")); + bgpSpeaker100.setInterfaceAddresses(interfaceAddresses100); + testConnectionSetup(); + } +} |