@Override public void updateControllerConnections(OFBsnControllerConnectionsReply controllerCxnsReply) { // Instantiate clean map, can't use a builder here since we need to call temp.get() Map<URI,Map<OFAuxId, OFBsnControllerConnection>> temp = new ConcurrentHashMap<URI,Map<OFAuxId, OFBsnControllerConnection>>(); List<OFBsnControllerConnection> controllerCxnUpdates = controllerCxnsReply.getConnections(); for(OFBsnControllerConnection update : controllerCxnUpdates) { URI uri = URI.create(update.getUri()); Map<OFAuxId, OFBsnControllerConnection> cxns = temp.get(uri); // Add to nested map if(cxns != null){ cxns.put(update.getAuxiliaryId(), update); } else{ cxns = new ConcurrentHashMap<OFAuxId, OFBsnControllerConnection>(); cxns.put(update.getAuxiliaryId(), update); temp.put(uri, cxns); } } this.controllerConnections = ImmutableMap.<URI,Map<OFAuxId, OFBsnControllerConnection>>copyOf(temp); }
public OFConnection(@Nonnull DatapathId dpid, @Nonnull OFFactory factory, @Nonnull Channel channel, @Nonnull OFAuxId auxId, @Nonnull IDebugCounterService debugCounters, @Nonnull Timer timer) { Preconditions.checkNotNull(dpid, "dpid"); Preconditions.checkNotNull(factory, "factory"); Preconditions.checkNotNull(channel, "channel"); Preconditions.checkNotNull(timer, "timer"); Preconditions.checkNotNull(debugCounters); this.listener = NullConnectionListener.INSTANCE; this.dpid = dpid; this.factory = factory; this.channel = channel; this.auxId = auxId; this.connectedSince = new Date(); this.xidDeliverableMap = new ConcurrentHashMap<>(); this.counters = new OFConnectionCounters(debugCounters, dpid, this.auxId); this.timer = timer; this.latency = U64.ZERO; }
@Override void enterState() throws IOException{ setSwitchHandshakeTimeout(); // Handle non 1.3 connections if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){ connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, OFAuxId.MAIN, debugCounters, timer); } // Handle 1.3 connections else { connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, featuresReply.getAuxiliaryId(), debugCounters, timer); // If this is an aux connection, we set a longer echo idle time if (!featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) { setAuxChannelIdle(); } } connection.updateLatency(U64.of(featuresLatency)); echoSendTime = 0; // Notify the connection broker notifyConnectionOpened(connection); }
/** * Tests that the switch manager should only return a switch to a getActiveSwitch * call when the switch is visible/active. */ @Test public void testGetActiveSwitch() { MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN); IOFSwitchBackend sw = new MockOFSwitchImpl(connection); sw.setStatus(SwitchStatus.HANDSHAKE); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); switchManager.switchAdded(sw); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.MASTER); assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.QUARANTINED); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.SLAVE); assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.DISCONNECTED); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); // we don't care for updates. drain queue. controller.processUpdateQueueForTesting(); }
/** * This test ensures that the switch accurately determined if another master * exists in the cluster by examining the controller connections it has. */ @Test public void testHasAnotherMaster() { URI cokeUri = URIUtil.createURI("1.2.3.4", 6653); InetSocketAddress address = (InetSocketAddress) sw.getConnection(OFAuxId.MAIN).getLocalInetAddress(); URI pepsiUri = URIUtil.createURI(address.getHostName(), address.getPort()); updateControllerConnections(sw, OFControllerRole.ROLE_SLAVE, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, cokeUri.toString(), OFControllerRole.ROLE_MASTER, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, pepsiUri.toString()); // From the perspective of pepsi, the cluster currently does NOT have another master controller assertFalse(sw.hasAnotherMaster()); // Switch the controller connections so that pepsi is no longer master updateControllerConnections(sw, OFControllerRole.ROLE_MASTER, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, cokeUri.toString(), OFControllerRole.ROLE_SLAVE, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, pepsiUri.toString()); // From the perspective of pepsi, the cluster currently has another master controller assertTrue(sw.hasAnotherMaster()); }
public OFConnection(@Nonnull DatapathId dpid, @Nonnull OFFactory factory, @Nonnull Channel channel, @Nonnull OFAuxId auxId, @Nonnull IDebugCounterService debugCounters, @Nonnull Timer timer) { Preconditions.checkNotNull(dpid, "dpid"); Preconditions.checkNotNull(factory, "factory"); Preconditions.checkNotNull(channel, "channel"); Preconditions.checkNotNull(timer, "timer"); Preconditions.checkNotNull(debugCounters); this.listener = NullConnectionListener.INSTANCE; this.dpid = dpid; this.factory = factory; this.channel = channel; this.auxId = auxId; this.connectedSince = new Date(); this.xidDeliverableMap = new ConcurrentHashMap<>(); this.counters = new OFConnectionCounters(debugCounters, dpid, this.auxId); this.timer = timer; }
@Before public void setUp() throws Exception { switchManager = createMock(IOFSwitchManager.class); roleManager = createMock(RoleManager.class); sw = createMock(IOFSwitchBackend.class); timer = createMock(Timer.class); expect(timer.newTimeout(anyObject(TimerTask.class), anyLong(), anyObject(TimeUnit.class))).andReturn(EasyMock.createNiceMock(Timeout.class)); replay(timer); seenXids = null; // TODO: should mock IDebugCounterService and make sure // the expected counters are updated. debugCounterService = new DebugCounterServiceImpl(); SwitchManagerCounters counters = new SwitchManagerCounters(debugCounterService); expect(switchManager.getCounters()).andReturn(counters).anyTimes(); replay(switchManager); connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN); switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer); // replay sw. Reset it if you need more specific behavior replay(sw); }
public OFChannelInfo(@Nonnull DatapathId id, @Nonnull OFAuxId auxId, @Nonnull SocketAddress address) { Preconditions.checkNotNull(id, "id should not be null"); Preconditions.checkNotNull(auxId, "auxId should not be null"); Preconditions.checkNotNull(address, "address should not be null"); this.id = id; this.auxId = auxId; InetSocketAddress socketAddress = (InetSocketAddress) address; this.address = IPAddress.of(socketAddress.getHostString()); this.port = socketAddress.getPort(); }
public OFSwitch(IOFConnectionBackend connection, @Nonnull OFFactory factory, @Nonnull IOFSwitchManager switchManager, @Nonnull DatapathId datapathId) { if(connection == null) throw new NullPointerException("connection must not be null"); if(!connection.getAuxId().equals(OFAuxId.MAIN)) throw new IllegalArgumentException("connection must be the main connection"); if(factory == null) throw new NullPointerException("factory must not be null"); if(switchManager == null) throw new NullPointerException("switchManager must not be null"); this.connected = true; this.factory = factory; this.switchManager = switchManager; this.datapathId = datapathId; this.attributes = new ConcurrentHashMap<Object, Object>(); this.role = null; this.description = new SwitchDescription(); this.portManager = new PortManager(); this.status = SwitchStatus.HANDSHAKE; // Connections this.connections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); this.connections.put(connection.getAuxId(), connection); // Switch's controller connection this.controllerConnections = ImmutableMap.of(); // Defaults properties for an ideal switch this.setAttribute(PROP_FASTWILDCARDS, EnumSet.allOf(OFFlowWildcards.class)); this.setAttribute(PROP_SUPPORTS_OFPP_FLOOD, Boolean.TRUE); this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, Boolean.TRUE); this.tableFeaturesByTableId = new HashMap<TableId, TableFeatures>(); this.tables = new ArrayList<TableId>(); this.securityKernel = switchManager.getSecurityKernelService(); }
/** * Gets a connection specified by aux Id. * @param auxId the specified aux id for the connection desired. * @return the aux connection specified by the auxId */ public IOFConnection getConnection(OFAuxId auxId) { IOFConnection connection = this.connections.get(auxId); if (connection == null) { throw new IllegalArgumentException("OF Connection for " + this + " with " + auxId + " does not exist."); } return connection; }
@Override public void disconnect() { // Iterate through connections and perform cleanup for (Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()) { entry.getValue().disconnect(); this.connections.remove(entry.getKey()); } log.debug("~~~~~~~SWITCH DISCONNECTED~~~~~~"); // Remove all counters from the store connected = false; }
@Override public boolean hasAnotherMaster() { //TODO: refactor get connection to not throw illegal arg exceptions IOFConnection mainCxn = this.getConnection(OFAuxId.MAIN); if(mainCxn != null) { // Determine the local URI InetSocketAddress address = (InetSocketAddress) mainCxn.getLocalInetAddress(); URI localURI = URIUtil.createURI(address.getHostName(), address.getPort()); for(Entry<URI,Map<OFAuxId, OFBsnControllerConnection>> entry : this.controllerConnections.entrySet()) { // Don't check our own controller connections URI uri = entry.getKey(); if(!localURI.equals(uri)){ // We only care for the MAIN connection Map<OFAuxId, OFBsnControllerConnection> cxns = this.controllerConnections.get(uri); OFBsnControllerConnection controllerCxn = cxns.get(OFAuxId.MAIN); if(controllerCxn != null) { // If the controller id disconnected or not master we know it is not connected if(controllerCxn.getState() == OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED && controllerCxn.getRole() == OFControllerRole.ROLE_MASTER){ return true; } } else { log.warn("Unable to find controller connection with aux id " + "MAIN for switch {} on controller with URI {}.", this, uri); } } } } return false; }
/** * Create a new unconnected OFChannelHandler. * @param controller * @param broker * @throws SwitchHandshakeHandlerException */ OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection, @Nonnull OFFeaturesReply featuresReply, @Nonnull IOFSwitchManager switchManager, @Nonnull RoleManager roleManager, @Nonnull Timer timer) { Preconditions.checkNotNull(connection, "connection"); Preconditions.checkNotNull(featuresReply, "featuresReply"); Preconditions.checkNotNull(switchManager, "switchManager"); Preconditions.checkNotNull(roleManager, "roleManager"); Preconditions.checkNotNull(timer, "timer"); Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN), "connection must be MAIN connection but is %s", connection); this.switchManager = switchManager; this.roleManager = roleManager; this.mainConnection = connection; this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); this.featuresReply = featuresReply; this.timer = timer; this.switchManagerCounters = switchManager.getCounters(); this.factory = OFFactories.getFactory(featuresReply.getVersion()); this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS); setState(new InitState()); this.pendingPortStatusMsg = new ArrayList<OFPortStatus>(); connection.setListener(this); }
private int calcNumRequiredConnections() { if(!this.logicalOFMessageCategories.isEmpty()){ // We use tree set here to maintain ordering TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>(); for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){ auxConnections.add(category.getAuxId()); } OFAuxId first = auxConnections.first(); OFAuxId last = auxConnections.last(); // Check for contiguous set (1....size()) if(first.equals(OFAuxId.MAIN)) { if(last.getValue() != auxConnections.size() - 1){ throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)"); } return auxConnections.size() - 1; } else if(first.equals(OFAuxId.of(1))) { if(last.getValue() != auxConnections.size()){ throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)"); } return auxConnections.size(); } else { throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1"); } } else { return 0; } }
@Override @Before public void setUp() throws Exception { dc = new DebugCounterServiceImpl(); dc.registerModule(OFConnectionCounters.COUNTER_MODULE); auxId = OFAuxId.of(5); dpId = DatapathId.of(5); counters = new OFConnectionCounters(dc, dpId, auxId); }
@Test public void testNewConnectionOpened() { MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN); OFFeaturesReply featuresReply = createOFFeaturesReply(DATAPATH_ID_1); // Assert no switch handlers assertTrue(switchManager.getSwitchHandshakeHandlers().isEmpty()); switchManager.connectionOpened(connection, featuresReply); // Ensure a assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1); assertTrue(switchManager.getSwitchHandshakeHandlers().get(0).getDpid().equals(DATAPATH_ID_1)); }
@Test public void testDuplicateConnectionOpened() { // Seed with 1 connection and handler testNewConnectionOpened(); MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN); OFFeaturesReply featuresReply = createOFFeaturesReply(DATAPATH_ID_1); switchManager.connectionOpened(connection, featuresReply); // Ensure duplicate connections are assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1); assertTrue(switchManager.getSwitchHandshakeHandlers().get(0).getDpid().equals(DATAPATH_ID_1)); }
public void setUpFeaturesReply() { portDesc = factory.buildPortDesc() .setName("Eth1") .setPortNo(OFPort.of(1)) .build(); featuresReply = factory.buildFeaturesReply() .setDatapathId(dpid) .setNBuffers(1) .setNTables((short)1) .setCapabilities(EnumSet.<OFCapabilities>of(OFCapabilities.FLOW_STATS, OFCapabilities.TABLE_STATS)) .setAuxiliaryId(OFAuxId.MAIN) .build(); }
@Test public void testMissingConnection() { // Just to make sure so this test is worth it assertFalse("Switch should not have a connection with auxId 5", sw.getConnections().contains(OFAuxId.of(5))); try{ sw.getConnection(OFAuxId.of(5)); fail("Expected exception not thrown"); } catch(IllegalArgumentException e){ /* expected */ } }
@Override OFFeaturesReply getFeaturesReply() { return factory.buildFeaturesReply() .setDatapathId(dpid) .setNBuffers(1) .setNTables((short)1) .setCapabilities(EnumSet.<OFCapabilities>of(OFCapabilities.FLOW_STATS, OFCapabilities.TABLE_STATS)) .setAuxiliaryId(OFAuxId.MAIN) .build(); }
@Before public void setUp() throws Exception { factory = OFFactories.getFactory(OFVersion.OF_13); switchId = DatapathId.of(1); timer = new HashedWheelTimer(); channel = EasyMock.createMock(Channel.class); IDebugCounterService debugCounterService = new DebugCounterServiceImpl(); debugCounterService.registerModule(OFConnectionCounters.COUNTER_MODULE); conn = new OFConnection(switchId, factory, channel, OFAuxId.MAIN, debugCounterService, timer); eventLoop = new TestEventLoop(); expect(channel.eventLoop()).andReturn(eventLoop).anyTimes(); }
public MockOFConnection(DatapathId id, OFAuxId auxId){ this.id = id; this.auxId = auxId; this.setDefaultAddresses(); this.messages = new ArrayList<>(); this.requests = new HashMap<>(); }
/** * Helper to load controller connection messages into a switch for testing. * @param sw the switch to insert the message on * @param role the role for the controller connection message * @param state the state for the controller connection message * @param uri the URI for the controller connection message */ public void updateControllerConnections(IOFSwitchBackend sw, OFControllerRole role1, OFBsnControllerConnectionState state1, String uri1 , OFControllerRole role2, OFBsnControllerConnectionState state2, String uri2) { OFBsnControllerConnection connection1 = factory.buildBsnControllerConnection() .setAuxiliaryId(OFAuxId.MAIN) .setRole(role1) .setState(state1) .setUri(uri1) .build(); OFBsnControllerConnection connection2 = factory.buildBsnControllerConnection() .setAuxiliaryId(OFAuxId.MAIN) .setRole(role2) .setState(state2) .setUri(uri2) .build(); List<OFBsnControllerConnection> connections = new ArrayList<OFBsnControllerConnection>(); connections.add(connection1); connections.add(connection2); OFBsnControllerConnectionsReply reply = factory.buildBsnControllerConnectionsReply() .setConnections(connections) .build(); sw.updateControllerConnections(reply); }
@Before public void setUp() throws Exception { /* * This needs to be called explicitly to ensure the featuresReply is not null. * Otherwise, there is no guarantee @Before will for setUpFeaturesReply() will * call that function before our @Before setUp() here. */ setUpFeaturesReply(); switchManager = createMock(IOFSwitchManager.class); roleManager = createMock(RoleManager.class); sw = createMock(IOFSwitchBackend.class); timer = createMock(Timer.class); expect(timer.newTimeout(anyObject(TimerTask.class), anyLong(), anyObject(TimeUnit.class))).andReturn(EasyMock.createNiceMock(Timeout.class)); replay(timer); seenXids = null; // TODO: should mock IDebugCounterService and make sure // the expected counters are updated. debugCounterService = new DebugCounterServiceImpl(); SwitchManagerCounters counters = new SwitchManagerCounters(debugCounterService); expect(switchManager.getCounters()).andReturn(counters).anyTimes(); replay(switchManager); connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN); switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer); // replay sw. Reset it if you need more specific behavior replay(sw); }