/* * Copyright (c) 2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * * 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.sdnplatform.tunnelmanager; import static org.easymock.EasyMock.*; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.easymock.IAnswer; import org.junit.Before; import org.junit.Test; import org.openflow.protocol.OFError; import org.openflow.protocol.OFFeaturesReply; import org.openflow.protocol.OFPhysicalPort; import org.openflow.protocol.OFVendor; import org.openflow.protocol.OFError.OFErrorType; import org.openflow.util.HexString; import org.sdnplatform.IBetterOFSwitch; import org.sdnplatform.core.ListenerContext; import org.sdnplatform.core.IOFSwitch; import org.sdnplatform.core.IOFSwitch.OFPortType; import org.sdnplatform.core.test.MockThreadPoolService; import org.sdnplatform.devicemanager.IDevice; import org.sdnplatform.ovsdb.IOVSDB; import org.sdnplatform.ovsdb.IOVSDBManagerService; import org.sdnplatform.packet.Ethernet; import org.sdnplatform.packet.IPv4; import org.sdnplatform.storage.memory.MemoryStorageSource; import org.sdnplatform.test.PlatformTestCase; import org.sdnplatform.tunnelmanager.TunnelManager; import org.sdnplatform.tunnelmanager.TunnelManagerTest.TMTest; import org.sdnplatform.util.MACAddress; import org.sdnplatform.vendor.OFBigSwitchVendorData; import org.sdnplatform.vendor.OFInterfaceIPReplyVendorData; import org.sdnplatform.vendor.OFInterfaceVendorData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TunnelManagerPollTest extends PlatformTestCase{ protected static Logger logger = LoggerFactory. getLogger(TunnelManagerPollTest.class); private TunnelManager tm; private static final String SWITCH_CONFIG_TABLE_NAME = "controller_switchconfig"; private static final String SWITCH_DPID = "dpid"; private static final String TUNNEL_ENABLED_OR_NOT = "tunnel_termination"; public TunnelManager getTunnelManager() { return tm; } private MemoryStorageSource stosrc; @Override @Before public void setUp() throws Exception { super.setUp(); MockThreadPoolService tp = new MockThreadPoolService(); tp.init(null); TunnelManager.TUNNEL_TASK_DELAY = 0; tm = new TunnelManager(); tm.setControllerProvider(getMockControllerProvider()); tm.threadPool = tp; stosrc = new MemoryStorageSource(); tm.setStorageSource(stosrc); Set<String> cols = new HashSet<String>(); cols.add(SWITCH_DPID); cols.add(TUNNEL_ENABLED_OR_NOT); stosrc.createTable(SWITCH_CONFIG_TABLE_NAME, cols); /* stosrc = createNiceMock(IStorageSource.class); tm.setStorageSource(stosrc); stosrc.addListener(SWITCH_CONFIG_TABLE_NAME, tm); expectLastCall().atLeastOnce(); */ tm.startUp(null); } protected OFFeaturesReply getFeaturesReply(long dpid) { OFFeaturesReply fr = new OFFeaturesReply(); fr.setDatapathId(dpid); fr.setPorts((List<OFPhysicalPort>)getPorts(true)); return fr; } protected void setupIOFSwitchPortType(IOFSwitch sw) { expect(sw.getPortType((short)4)).andReturn(OFPortType.TUNNEL_LOOPBACK).times(2); expect(sw.getPortType((short)3)).andReturn(OFPortType.TUNNEL).times(1); expect(sw.getPortType((short)1)).andReturn(OFPortType.NORMAL).anyTimes(); expect(sw.getPortType((short)2)).andReturn(OFPortType.NORMAL).anyTimes(); expect(sw.getPortType((short)0xfffe)).andReturn(OFPortType.NORMAL).anyTimes(); } protected void setupOneStandardOVSSwitchMock(IOFSwitch sw, long dpid) { expect(sw.getId()).andReturn(dpid).anyTimes(); String dpidString = HexString.toHexString(dpid); expect(sw.getStringId()).andReturn(dpidString).anyTimes(); expect(sw.getEnabledPorts()).andReturn(getPorts(true)).anyTimes(); expect(sw.getPort(anyObject(String.class))) .andAnswer(new GetPortAnswer()).anyTimes(); expect(sw.attributeEquals(IBetterOFSwitch.SUPPORTS_BSN_SET_TUNNEL_DST_ACTION, true)) .andReturn(false).anyTimes(); expect(sw.attributeEquals(IBetterOFSwitch.SUPPORTS_OVSDB_TUNNEL_SETUP, true)) .andReturn(true).anyTimes(); setupIOFSwitchPortType(sw); } protected void setupStandardOVSSwitchMocks(IOFSwitch sw1, IOFSwitch sw2, IOFSwitch sw3) { setupOneStandardOVSSwitchMock(sw1, 1L); setupOneStandardOVSSwitchMock(sw2, 2L); setupOneStandardOVSSwitchMock(sw3, 3L); ConcurrentHashMap<Long, IOFSwitch> switchmap = new ConcurrentHashMap<Long, IOFSwitch>(); switchmap.put(1L, sw1); switchmap.put(2L, sw2); switchmap.put(3L, sw3); getMockControllerProvider().setSwitches(switchmap); } @SuppressWarnings("unchecked") protected void setupOneBSNOVSSwitchMock(IOFSwitch sw, long dpid) throws IOException { expect(sw.getId()).andReturn(dpid).anyTimes(); String dpidString = HexString.toHexString(dpid); expect(sw.getStringId()).andReturn(dpidString).anyTimes(); expect(sw.getEnabledPorts()).andReturn(getPorts(true)).anyTimes(); expect(sw.getPort(anyObject(String.class))) .andAnswer(new GetPortAnswer()).anyTimes(); expect(sw.attributeEquals(IBetterOFSwitch.SUPPORTS_BSN_SET_TUNNEL_DST_ACTION, true)) .andReturn(true).anyTimes(); expect(sw.attributeEquals(IBetterOFSwitch.SUPPORTS_OVSDB_TUNNEL_SETUP, true)) .andReturn(false).anyTimes(); expect(sw.getNextTransactionId()).andReturn(42).anyTimes(); sw.write(anyObject(List.class), anyObject(ListenerContext.class)); expectLastCall().atLeastOnce(); setupIOFSwitchPortType(sw); } protected void setupBSNOVSSwitchMocks(IOFSwitch sw1, IOFSwitch sw2, IOFSwitch sw3) throws IOException { setupOneBSNOVSSwitchMock(sw1, 1L); setupOneBSNOVSSwitchMock(sw2, 2L); setupOneBSNOVSSwitchMock(sw3, 3L); ConcurrentHashMap<Long, IOFSwitch> switchmap = new ConcurrentHashMap<Long, IOFSwitch>(); switchmap.put(1L, sw1); switchmap.put(2L, sw2); switchmap.put(3L, sw3); getMockControllerProvider().setSwitches(switchmap); } protected void setupIOFSwitchMocks(IOFSwitch sw1, IOFSwitch sw2, IOFSwitch sw3) { sw1.setFeaturesReply(getFeaturesReply(1L)); sw2.setFeaturesReply(getFeaturesReply(2L)); sw3.setFeaturesReply(getFeaturesReply(3L)); ConcurrentHashMap<Long, IOFSwitch> switchmap = new ConcurrentHashMap<Long, IOFSwitch>(); switchmap.put(1L, sw1); switchmap.put(2L, sw2); switchmap.put(3L, sw3); getMockControllerProvider().setSwitches(switchmap); } protected void setupIOVSDBMocks(IOVSDB db1, IOVSDB db2, IOVSDB db3, IOVSDBManagerService ovsdb) { ArrayList<IOVSDB> ovsdbs = new ArrayList<IOVSDB>(); ovsdbs.add(db1); ovsdbs.add(db2); ovsdbs.add(db3); } public class GetPortAnswer implements IAnswer<OFPhysicalPort> { @Override public OFPhysicalPort answer() throws Throwable { Object[] args = getCurrentArguments(); String portName = (String)args[0]; for(OFPhysicalPort p : getPorts(true)) { if (p.getName().equals(portName)) return p; } return null; } } protected Collection<OFPhysicalPort> getPorts(boolean hasTunnel) { List<OFPhysicalPort> switchIntfs = new ArrayList<OFPhysicalPort>(); OFPhysicalPort p; int numports = (hasTunnel) ? 5 : 3; for (short i=0; i<numports; i++) { p = new OFPhysicalPort(); p.setConfig(0); p.setState(0); p.setCurrentFeatures(0xc0); p.setAdvertisedFeatures(0); p.setSupportedFeatures(0); p.setPeerFeatures(0); switch (i) { case 0: // eth1 uplink port p.setPortNumber((short) 1); byte[] hardwareAddress1 = new byte[]{ (byte)0xcc,0,0,0,0,(byte)1}; p.setHardwareAddress(hardwareAddress1); p.setName("eth1"); break; case 1: // ovs-br0 LOCAL port p.setPortNumber((short) 0xfffe); byte[] hardwareAddress2 = new byte[]{ (byte)0xcc,0,0,0,0,(byte)2}; p.setHardwareAddress(hardwareAddress2); p.setName("ovs-br0"); break; case 2: // a tap port for a connected VM p.setPortNumber((short) 2); byte[] hardwareAddress3 = new byte[]{ (byte)0xcc,0,0,0,0,(byte)3}; p.setHardwareAddress(hardwareAddress3); p.setName("tap0"); break; case 3: // a GRE tunnel port p.setPortNumber((short) 3); byte[] hardwareAddress4 = new byte[]{ (byte)0xcc,0,0,0,0,(byte)4}; p.setHardwareAddress(hardwareAddress4); p.setName("tun-bsn"); break; case 4: // a tunnel-endpoint port p.setPortNumber((short) 4); byte[] hardwareAddress5 = new byte[]{ (byte)0xcc,0,0,0,0,(byte)5}; p.setHardwareAddress(hardwareAddress5); p.setName("tun-loopback"); break; } switchIntfs.add(p); } return switchIntfs; } //************************************************ private static final TMTest emptyTest; static { emptyTest = new TMTest(); } @Test public void testPollStandardOVSSwitch() { logger.info("*** Starting test 1: testPollStandardOVSSwitch ***"); emptyTest.writeToStorage(stosrc); IOFSwitch sw1 = createMock(IOFSwitch.class); IOFSwitch sw2 = createMock(IOFSwitch.class); IOFSwitch sw3 = createMock(IOFSwitch.class); IOVSDBManagerService ovsdb = createNiceMock(IOVSDBManagerService.class); tm.setOVSDBManager(ovsdb); IOVSDB db1 = createMock(IOVSDB.class); IOVSDB db2 = createMock(IOVSDB.class); IOVSDB db3 = createMock(IOVSDB.class); //setupIOFSwitchMocks(sw1, sw2, sw3); setupStandardOVSSwitchMocks(sw1, sw2, sw3); setupIOVSDBMocks(db1, db2, db3, ovsdb); // first time OVS setup and no IP address found expect(ovsdb.getOVSDB(1L)).andReturn(null).atLeastOnce(); expect(ovsdb.getOVSDB(2L)).andReturn(null).atLeastOnce(); expect(ovsdb.getOVSDB(3L)).andReturn(null).atLeastOnce(); expect(ovsdb.addOVSDB(1L)).andReturn(db1).atLeastOnce(); expect(ovsdb.addOVSDB(2L)).andReturn(db2).atLeastOnce(); expect(ovsdb.addOVSDB(3L)).andReturn(db3).atLeastOnce(); expect(db1.getTunnelIPAddress(false)).andReturn(null).anyTimes(); expect(db2.getTunnelIPAddress(false)).andReturn(null).anyTimes(); expect(db3.getTunnelIPAddress(false)).andReturn(null).anyTimes(); replay(sw1, sw2, sw3); replay(db1, db2, db3, ovsdb); tm.addedSwitch(sw1); tm.addedSwitch(sw2); tm.addedSwitch(sw3); verify(db1, db2, db3, ovsdb); assertEquals(true, tm.outstandingTunnelIP.contains(1L)); assertEquals(true, tm.outstandingTunnelIP.contains(2L)); assertEquals(true, tm.outstandingTunnelIP.contains(3L)); assertEquals(false, tm.tunnelCapableSwitches.get(1L).active); assertEquals(false, tm.tunnelCapableSwitches.get(2L).active); assertEquals(false, tm.tunnelCapableSwitches.get(3L).active); assertEquals(0, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(0, tm.tunnelCapableSwitches.get(2L).ipv4Addr); assertEquals(0, tm.tunnelCapableSwitches.get(3L).ipv4Addr); assertNull(tm.tunnIPToDpid.get(16843009)); assertNull(tm.tunnIPToDpid.get(33686018)); assertNull(tm.tunnIPToDpid.get(50529027)); // invalid mac and ip addresses IDevice noTunnelEndp1 = createMock(IDevice.class); expect(noTunnelEndp1.getMACAddress()).andReturn(100L).atLeastOnce(); expect(noTunnelEndp1.getIPv4Addresses()).andReturn( new Integer[] {100, 200}).atLeastOnce(); // valid tunnel-endpoint mac for a standard OVS switch IDevice tunnelEndp2 = createMock(IDevice.class); expect(tunnelEndp2.getMACAddress()).andReturn( Ethernet.toLong(new byte[] {(byte) 0xcc,0,0,0,0,2})).atLeastOnce(); replay(noTunnelEndp1, tunnelEndp2); assertEquals(false, tm.isTunnelEndpoint(noTunnelEndp1)); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp2)); assertEquals(null, tm.getTunnelIPAddr(1L)); assertEquals(null, tm.getTunnelIPAddr(2L)); assertEquals(null, tm.getTunnelIPAddr(3L)); assertEquals(false, tm.isTunnelActiveByDpid(3L)); assertEquals(false, tm.isTunnelActiveByDpid(2L)); assertEquals(false, tm.isTunnelActiveByDpid(1L)); assertEquals(false, tm.isTunnelActiveByIP(1)); assertEquals(false, tm.isTunnelActiveByIP(168430090)); assertEquals(3, tm.getTunnelPortNumber(1L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(2L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(3L).shortValue()); verify(noTunnelEndp1, tunnelEndp2); verify(sw1, sw2, sw3); } @Test public void testPollStandardOVSSwitch2() { logger.info("*** Starting test 2: testPollStandardOVSSwitch 2***"); emptyTest.writeToStorage(stosrc); IOFSwitch sw1 = createMock(IOFSwitch.class); IOFSwitch sw2 = createMock(IOFSwitch.class); IOFSwitch sw3 = createMock(IOFSwitch.class); IOVSDBManagerService ovsdb = createNiceMock(IOVSDBManagerService.class); tm.setOVSDBManager(ovsdb); IOVSDB db1 = createMock(IOVSDB.class); IOVSDB db2 = createMock(IOVSDB.class); IOVSDB db3 = createMock(IOVSDB.class); setupStandardOVSSwitchMocks(sw1, sw2, sw3); setupIOVSDBMocks(db1, db2, db3, ovsdb); // next time IP address found expect(ovsdb.getOVSDB(1L)).andReturn(db1).atLeastOnce(); expect(ovsdb.getOVSDB(2L)).andReturn(db2).atLeastOnce(); expect(ovsdb.getOVSDB(3L)).andReturn(db3).atLeastOnce(); expect(db1.getTunnelIPAddress(false)).andReturn("1.1.1.1").anyTimes(); expect(db2.getTunnelIPAddress(false)).andReturn("2.2.2.2").anyTimes(); expect(db3.getTunnelIPAddress(false)).andReturn("3.3.3.3").anyTimes(); replay(sw1, sw2, sw3); replay(db1, db2, db3, ovsdb); tm.addedSwitch(sw1); tm.addedSwitch(sw2); tm.addedSwitch(sw3); verify(db1, db2, db3, ovsdb); assertEquals(false, tm.outstandingTunnelIP.contains(1L)); assertEquals(false, tm.outstandingTunnelIP.contains(2L)); assertEquals(false, tm.outstandingTunnelIP.contains(3L)); assertEquals(true, tm.tunnelCapableSwitches.get(1L).active); assertEquals(true, tm.tunnelCapableSwitches.get(2L).active); assertEquals(true, tm.tunnelCapableSwitches.get(3L).active); assertEquals(16843009, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(33686018, tm.tunnelCapableSwitches.get(2L).ipv4Addr); assertEquals(50529027, tm.tunnelCapableSwitches.get(3L).ipv4Addr); assertEquals(Long.valueOf(1L), tm.tunnIPToDpid.get(16843009)); assertEquals(Long.valueOf(2L), tm.tunnIPToDpid.get(33686018)); assertEquals(Long.valueOf(3L), tm.tunnIPToDpid.get(50529027)); //valid mac IDevice tunnelEndp1 = createMock(IDevice.class); expect(tunnelEndp1.getMACAddress()).andReturn( Ethernet.toLong(new byte[] {(byte) 0xcc,0,0,0,0,2})).atLeastOnce(); // valid IP IDevice tunnelEndp2 = createMock(IDevice.class); expect(tunnelEndp2.getMACAddress()).andReturn(100L).atLeastOnce(); expect(tunnelEndp2.getIPv4Addresses()).andReturn( new Integer[] {100, 16843009}).atLeastOnce(); replay(tunnelEndp1, tunnelEndp2); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp1)); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp2)); assertEquals(16843009, tm.getTunnelIPAddr(1L).intValue()); assertEquals(33686018, tm.getTunnelIPAddr(2L).intValue()); assertEquals(50529027, tm.getTunnelIPAddr(3L).intValue()); assertEquals(true, tm.isTunnelActiveByDpid(3L)); assertEquals(true, tm.isTunnelActiveByDpid(2L)); assertEquals(true, tm.isTunnelActiveByDpid(1L)); assertEquals(false, tm.isTunnelActiveByIP(1)); assertEquals(true, tm.isTunnelActiveByIP(16843009)); assertEquals(3, tm.getTunnelPortNumber(1L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(2L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(3L).shortValue()); verify(tunnelEndp1, tunnelEndp2); verify(sw1, sw2, sw3); } @Test public void testPollBSNOVSSwitch() throws IOException { logger.info("*** Starting test 3: testPollBSNOVSSwitch ***"); emptyTest.writeToStorage(stosrc); IOFSwitch sw1 = createMock(IOFSwitch.class); IOFSwitch sw2 = createMock(IOFSwitch.class); IOFSwitch sw3 = createMock(IOFSwitch.class); setupBSNOVSSwitchMocks(sw1, sw2, sw3); IOVSDBManagerService ovsdb = createNiceMock(IOVSDBManagerService.class); tm.setOVSDBManager(ovsdb); /* OFVendor ov = new OFVendor(); ov.setLength((short)16); ov.setXid(1); ov.setVendor(OFBigSwitchVendorData.BSN_VENDOR_ID); OFInterfaceIPRequestVendorData vd = new OFInterfaceIPRequestVendorData(); ov.setVendorData(vd); List<OFMessage> msgList = new ArrayList<OFMessage>(1); msgList.add(ov); Object[] m = msgList.toArray(); expect(ch1.write(EasyMock.aryEq(m))).andReturn(null).atLeastOnce(); */ // expect the Interface IP request message replay(sw1, sw2, sw3); tm.addedSwitch(sw1); tm.addedSwitch(sw2); tm.addedSwitch(sw3); assertEquals(true, tm.outstandingTunnelIP.contains(1L)); assertEquals(true, tm.outstandingTunnelIP.contains(2L)); assertEquals(true, tm.outstandingTunnelIP.contains(3L)); assertEquals(false, tm.tunnelCapableSwitches.get(1L).active); assertEquals(false, tm.tunnelCapableSwitches.get(2L).active); assertEquals(false, tm.tunnelCapableSwitches.get(3L).active); assertEquals(0, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(0, tm.tunnelCapableSwitches.get(2L).ipv4Addr); assertEquals(0, tm.tunnelCapableSwitches.get(3L).ipv4Addr); assertEquals(true, tm.sentIPRequests.containsKey(1L)); assertEquals(true, tm.sentIPRequests.containsKey(2L)); assertEquals(true, tm.sentIPRequests.containsKey(3L)); //switch 1 receives empty list int xidsw1 = tm.sentIPRequests.get(1L).iterator().next(); OFVendor ov1 = getReplyMsg(0, xidsw1, false, false); tm.receive(sw1, ov1, null); assertEquals(true, tm.outstandingTunnelIP.contains(1L)); assertEquals(false, tm.tunnelCapableSwitches.get(1L).active); assertEquals(0, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(false, tm.sentIPRequests.get(1L).contains(xidsw1)); //switch 2 receives more than one interface int xidsw2 = tm.sentIPRequests.get(2L).iterator().next(); OFVendor ov2 = getReplyMsg(2, xidsw2, false, false); tm.receive(sw2, ov2, null); assertEquals(true, tm.outstandingTunnelIP.contains(2L)); assertEquals(false, tm.tunnelCapableSwitches.get(2L).active); assertEquals(0, tm.tunnelCapableSwitches.get(2L).ipv4Addr); assertEquals(false, tm.sentIPRequests.get(2L).contains(xidsw2)); //switch 3 receives exactly one interface int xidsw3 = tm.sentIPRequests.get(3L).iterator().next(); OFVendor ov3 = getReplyMsg(1, xidsw3, false, false); tm.receive(sw3, ov3, null); assertEquals(false, tm.outstandingTunnelIP.contains(3L)); assertEquals(true, tm.tunnelCapableSwitches.get(3L).active); assertEquals(168430090, tm.tunnelCapableSwitches.get(3L).ipv4Addr); assertEquals(MACAddress.valueOf("0a:00:0a:00:0a:01"), MACAddress.valueOf(tm.tunnelCapableSwitches.get(3L).macAddr)); assertEquals(false, tm.sentIPRequests.get(3L).contains(xidsw3)); assertEquals(3L, tm.tunnIPToDpid.get(168430090).longValue()); // switch 1 receives unknown vendor if (tm.sentIPRequests.get(1L) != null) tm.sentIPRequests.get(1L).clear(); tm.getTunnelIPFromOF(sw1); int xid2sw1 = tm.sentIPRequests.get(1L).iterator().next(); OFVendor ov1b = getReplyMsg(1, xid2sw1, true, false); tm.receive(sw1, ov1b, null); assertEquals(true, tm.outstandingTunnelIP.contains(1L)); assertEquals(false, tm.tunnelCapableSwitches.get(1L).active); assertEquals(0, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(true, tm.sentIPRequests.get(1L).contains(xid2sw1)); // switch 2 receives unknown message sub-type if (tm.sentIPRequests.get(2L) != null) tm.sentIPRequests.get(2L).clear(); tm.getTunnelIPFromOF(sw2); int xid2sw2 = tm.sentIPRequests.get(2L).iterator().next(); OFVendor ov2b = getReplyMsg(1, xid2sw2, false, true); tm.receive(sw2, ov2b, null); assertEquals(true, tm.outstandingTunnelIP.contains(2L)); assertEquals(false, tm.tunnelCapableSwitches.get(2L).active); assertEquals(0, tm.tunnelCapableSwitches.get(2L).ipv4Addr); assertEquals(true, tm.sentIPRequests.get(2L).contains(xid2sw2)); // switch 1 receives permissions error message if (tm.sentIPRequests.get(1L) != null) tm.sentIPRequests.get(1L).clear(); tm.getTunnelIPFromOF(sw1); int xid3sw1 = tm.sentIPRequests.get(1L).iterator().next(); OFError err1 = new OFError(); err1.setXid(xid3sw1); err1.setErrorType(OFErrorType.OFPET_BAD_REQUEST.getValue()); err1.setErrorCode(OFError.OFBadRequestCode.OFPBRC_EPERM); tm.receive(sw1, err1, null); assertEquals(true, tm.outstandingTunnelIP.contains(1L)); assertEquals(false, tm.tunnelCapableSwitches.get(1L).active); assertEquals(0, tm.tunnelCapableSwitches.get(1L).ipv4Addr); assertEquals(false, tm.sentIPRequests.get(1L).contains(xid3sw1)); //check API calls // invalid mac and ip addresses IDevice noTunnelEndp1 = createMock(IDevice.class); expect(noTunnelEndp1.getMACAddress()).andReturn(100L).atLeastOnce(); expect(noTunnelEndp1.getIPv4Addresses()).andReturn( new Integer[] {100, 200}).atLeastOnce(); // valid mac but for a standard OVS switch - does not apply to BSN-OVS IDevice noTunnelEndp2 = createMock(IDevice.class); expect(noTunnelEndp2.getMACAddress()).andReturn( Ethernet.toLong(new byte[] {(byte) 0xcc,0,0,0,0,2})).atLeastOnce(); expect(noTunnelEndp2.getIPv4Addresses()).andReturn( new Integer[] {100, 200}).atLeastOnce(); // valid mac IDevice tunnelEndp1 = createMock(IDevice.class); expect(tunnelEndp1.getMACAddress()).andReturn( Ethernet.toLong(new byte[] {(byte)0xa,0,(byte)0xa,0,(byte)0xa,(byte)0x1})) .atLeastOnce(); // valid IP IDevice tunnelEndp2 = createMock(IDevice.class); expect(tunnelEndp2.getMACAddress()).andReturn(100L).atLeastOnce(); expect(tunnelEndp2.getIPv4Addresses()).andReturn( new Integer[] {100, 168430090}).atLeastOnce(); replay(noTunnelEndp1, noTunnelEndp2, tunnelEndp1, tunnelEndp2); assertEquals(false, tm.isTunnelEndpoint(noTunnelEndp1)); assertEquals(false, tm.isTunnelEndpoint(noTunnelEndp2)); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp1)); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp2)); tm.tunnelCapableSwitches.get(3L).active = false; assertEquals(true, tm.isTunnelEndpoint(tunnelEndp1)); assertEquals(true, tm.isTunnelEndpoint(tunnelEndp2)); tm.tunnelCapableSwitches.get(3L).active = true; assertEquals(null, tm.getTunnelIPAddr(1L)); assertEquals(null, tm.getTunnelIPAddr(2L)); assertEquals(168430090, tm.getTunnelIPAddr(3L).intValue()); tm.tunnelCapableSwitches.get(3L).active = false; assertEquals(null, tm.getTunnelIPAddr(3L)); tm.tunnelCapableSwitches.get(3L).active = true; assertEquals(true, tm.isTunnelActiveByDpid(3L)); assertEquals(false, tm.isTunnelActiveByDpid(2L)); assertEquals(false, tm.isTunnelActiveByDpid(1L)); assertEquals(false, tm.isTunnelActiveByIP(1)); assertEquals(true, tm.isTunnelActiveByIP(168430090)); assertEquals(3, tm.getTunnelPortNumber(1L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(2L).shortValue()); assertEquals(3, tm.getTunnelPortNumber(3L).shortValue()); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.128"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.0"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.1"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.255"))); assertEquals(false, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.11.0"))); assertEquals(false, tm.isTunnelSubnet(IPv4.toIPv4Address("0.0.0.0"))); assertEquals(false, tm.isTunnelSubnet(IPv4.toIPv4Address("255.255.255.0"))); assertEquals(1, tm.tunnelIPSubnets.size()); int e = IPv4.toIPv4Address("255.255.255.0") & IPv4.toIPv4Address("10.10.10.13"); tm.tunnelIPSubnets.get(IPv4.toIPv4Address("255.255.255.0")).add(e); // same subnet as 10.10.10.10 - should not add to mask->set assertEquals(1, tm.tunnelIPSubnets.size()); assertEquals(1, tm.tunnelIPSubnets.get(IPv4.toIPv4Address("255.255.255.0")).size()); int ex = IPv4.toIPv4Address("255.255.255.0") & IPv4.toIPv4Address("10.10.11.13"); tm.tunnelIPSubnets.get(IPv4.toIPv4Address("255.255.255.0")).add(ex); assertEquals(1, tm.tunnelIPSubnets.size()); assertEquals(2, tm.tunnelIPSubnets.get(IPv4.toIPv4Address("255.255.255.0")).size()); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.128"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.11.128"))); assertEquals(false, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.12.128"))); Set<Integer> s = Collections.newSetFromMap( new ConcurrentHashMap<Integer,Boolean>()); int tex = IPv4.toIPv4Address("255.255.0.0") & IPv4.toIPv4Address("10.10.11.13"); s.add(tex); tm.tunnelIPSubnets.put(IPv4.toIPv4Address("255.255.0.0"), s); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.10.128"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.11.128"))); assertEquals(true, tm.isTunnelSubnet(IPv4.toIPv4Address("10.10.12.128"))); verify(noTunnelEndp1, noTunnelEndp2, tunnelEndp1, tunnelEndp2); // api calls after switch removal // mac IDevice tunnelEndp5 = createMock(IDevice.class); expect(tunnelEndp5.getMACAddress()).andReturn( Ethernet.toLong(new byte[] {(byte)0xa,0,(byte)0xa,0,(byte)0xa,(byte)0x1})) .atLeastOnce(); expect(tunnelEndp5.getIPv4Addresses()).andReturn( new Integer[] {100, 168430090}).atLeastOnce(); // IP IDevice tunnelEndp6 = createMock(IDevice.class); expect(tunnelEndp6.getMACAddress()).andReturn(100L).atLeastOnce(); expect(tunnelEndp6.getIPv4Addresses()).andReturn( new Integer[] {100, 168430090}).atLeastOnce(); replay(tunnelEndp5, tunnelEndp6); tm.removedSwitch(sw3); assertEquals(null, tm.getTunnelIPAddr(3L)); assertEquals(false, tm.tunnelCapableSwitches.containsKey(sw3.getId())); assertEquals(false, tm.isTunnelEndpoint(tunnelEndp5)); assertEquals(false, tm.isTunnelEndpoint(tunnelEndp6)); assertEquals(null, tm.getTunnelPortNumber(3L)); assertEquals(false, tm.isTunnelActiveByDpid(3L)); assertEquals(false, tm.isTunnelActiveByIP(168430090)); verify(tunnelEndp5, tunnelEndp6); verify(sw1, sw2, sw3); } private OFVendor getReplyMsg(int numIntfs, int xid, boolean badVendor, boolean badSubtype) { OFVendor ov = new OFVendor(); ov.setLength((short)16); ov.setXid(xid); if (badVendor) { ov.setVendor(0); } else { ov.setVendor(OFBigSwitchVendorData.BSN_VENDOR_ID); } OFInterfaceIPReplyVendorData vd = new OFInterfaceIPReplyVendorData(); if (badSubtype) { vd.setDataType(100); } List<OFInterfaceVendorData> intfs = new ArrayList<OFInterfaceVendorData>(); OFInterfaceVendorData intf = new OFInterfaceVendorData(); intf.setName("tun-loopback"); intf.setHardwareAddress(new byte[] {10,0,10,0,10,1}); intf.setIpv4Addr(168430090); // 10.10.10.10 intf.setIpv4AddrMask(IPv4.toIPv4Address("255.255.255.0")); if (numIntfs == 1) { intfs.add(intf); } else if (numIntfs > 1) { intfs.add(intf); intfs.add(intf); } vd.setInterfaces(intfs); ov.setVendorData(vd); return ov; } }