@Test public void testRemovedSwitchSelf() { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); IOFSwitch sw1 = createMockSwitch(1L); replay(sw1); Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(1L), OFPort.of(3), U64.ZERO); LinkInfo info = new LinkInfo(new Date(), new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); // Mock up our expected behavior linkDiscovery.switchRemoved(sw1.getId()); verify(sw1); // check invariants hold assertNull(linkDiscovery.switchLinks.get(lt.getSrc())); assertNull(linkDiscovery.portLinks.get(lt.getSrc())); assertNull(linkDiscovery.portLinks.get(lt.getDst())); assertTrue(linkDiscovery.links.isEmpty()); }
private ImmutablePair<Long, Boolean> installLegacyMeter(final IOFSwitch sw, final DatapathId dpid, final long bandwidth, final long burstSize, final long meterId) { logger.debug("installing legacy meter {} on OVS switch {} width bandwidth {}", meterId, dpid, bandwidth); Set<OFLegacyMeterFlags> flags = new HashSet<>(Arrays.asList(OFLegacyMeterFlags.KBPS, OFLegacyMeterFlags.BURST)); OFFactory ofFactory = sw.getOFFactory(); OFLegacyMeterBandDrop.Builder bandBuilder = ofFactory.legacyMeterBandDrop(bandwidth, burstSize).createBuilder(); OFLegacyMeterMod meterMod = ofFactory.buildLegacyMeterMod() .setMeterId(meterId) .setCommand(OFLegacyMeterModCommand.ADD) .setMeters(singletonList(bandBuilder.build())) .setFlags(flags) .build(); boolean response = sw.write(meterMod); return new ImmutablePair<>(meterMod.getXid(), response); }
protected Match createMatchFromPacket(IOFSwitch sw, OFPort inPort, FloodlightContext cntx) { // The packet in match will only contain the port number. // We need to add in specifics for the hosts we're routing between. Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); MacAddress srcMac = eth.getSourceMACAddress(); MacAddress dstMac = eth.getDestinationMACAddress(); Match.Builder mb = sw.getOFFactory().buildMatch(); mb.setExact(MatchField.IN_PORT, inPort) .setExact(MatchField.ETH_SRC, srcMac) .setExact(MatchField.ETH_DST, dstMac); if (!vlan.equals(VlanVid.ZERO)) { mb.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlanVid(vlan)); } return mb.build(); }
/** * Builds OFAction list based on flow parameters for push scheme. * * @param sw IOFSwitch instance * @param outputVlanId set vlan on packet before forwarding via outputPort; 0 means not to set * @param outputVlanType type of action to apply to the outputVlanId if greater than 0 * @return list of {@link OFAction} */ private List<OFAction> pushSchemeOutputVlanTypeToOFActionList(IOFSwitch sw, int outputVlanId, OutputVlanType outputVlanType) { List<OFAction> actionList = new ArrayList<>(2); switch (outputVlanType) { case PUSH: // No VLAN on packet so push a new one actionList.add(actionPushVlan(sw, ETH_TYPE)); actionList.add(actionReplaceVlan(sw, outputVlanId)); break; case REPLACE: // VLAN on packet but needs to be replaced actionList.add(actionReplaceVlan(sw, outputVlanId)); break; case POP: // VLAN on packet, so remove it // TODO: can i do this? pop two vlan's back to back... actionList.add(actionPopVlan(sw)); break; case NONE: break; default: logger.error("Unknown OutputVlanType: " + outputVlanType); } return actionList; }
/** * Create an OFAction to change the outer most vlan. * * @param sw switch object * @param newVlan final VLAN to be set on the packet * @return {@link OFAction} */ private OFAction actionReplaceVlan(final IOFSwitch sw, final int newVlan) { OFFactory factory = sw.getOFFactory(); OFOxms oxms = factory.oxms(); OFActions actions = factory.actions(); if (OF_12.compareTo(factory.getVersion()) == 0) { return actions.buildSetField().setField(oxms.buildVlanVid() .setValue(OFVlanVidMatch.ofRawVid((short) newVlan)) .build()).build(); } else { return actions.buildSetField().setField(oxms.buildVlanVid() .setValue(OFVlanVidMatch.ofVlan(newVlan)) .build()).build(); } }
/** * {@inheritDoc} */ @Override public void switchActivated(final DatapathId switchId) { final IOFSwitch sw = switchService.getSwitch(switchId); Message message = buildSwitchMessage(sw, SwitchState.ACTIVATED); kafkaProducer.postMessage(TOPO_EVENT_TOPIC, message); ImmutablePair<Long, Boolean> metersDeleted; metersDeleted = switchManager.deleteMeter(switchId, ALL_VAL); if (!metersDeleted.getRight()) { logger.error("Could not delete meters from switch={} xid={}", switchId, metersDeleted.getLeft()); } boolean defaultRulesInstalled = switchManager.installDefaultRules(switchId); if (!defaultRulesInstalled) { logger.error("Could not install default rules on switch={}", switchId); } if (sw.getEnabledPortNumbers() != null) { for (OFPort p : sw.getEnabledPortNumbers()) { kafkaProducer.postMessage(TOPO_EVENT_TOPIC, buildPortMessage(sw.getId(), p, PortChangeType.UP)); } } }
@Override public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { if (!this.enabled) { return Command.CONTINUE; } switch (msg.getType()) { case PACKET_IN: IRoutingDecision decision = null; if (cntx != null) { decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); return this.processPacketInMessage(sw, (OFPacketIn) msg, decision, cntx); } break; default: break; } return Command.CONTINUE; }
/** * Set the role for this switch / channel. * * If the status indicates that we received a reply we set the role. * If the status indicates otherwise we disconnect the switch if * the role is SLAVE. * * "Setting a role" means setting the appropriate ChannelState, * setting the flags on the switch and * notifying Controller.java about new role of the switch * * @param role The role to set. * @param status How we derived at the decision to set this status. */ synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) { requestPending = false; if (status == RoleRecvStatus.RECEIVED_REPLY) sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); else sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); sw.setControllerRole(role); if (role != OFControllerRole.ROLE_SLAVE) { OFSwitchHandshakeHandler.this.setState(new MasterState()); } else { if (status != RoleRecvStatus.RECEIVED_REPLY) { if (log.isDebugEnabled()) { log.debug("Disconnecting switch {}. Doesn't support role" + "({}) request and controller is now SLAVE", getSwitchInfoString(), status); } // the disconnect will trigger a switch removed to // controller so no need to signal anything else sw.disconnect(); } else { OFSwitchHandshakeHandler.this.setState(new SlaveState()); } } }
/** * Writes a list of OFMessages to a switch * @param dpid The datapath ID of the switch to write to * @param messages The list of OFMessages to write. */ @LogMessageDoc(level="ERROR", message="Tried to write to switch {switch} but got {error}", explanation="An I/O error occured while trying to write a " + "static flow to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) private void writeOFMessagesToSwitch(DatapathId dpid, List<OFMessage> messages) { IOFSwitch ofswitch = switchService.getSwitch(dpid); if (ofswitch != null) { // is the switch connected if (log.isDebugEnabled()) { log.debug("Sending {} new entries to {}", messages.size(), dpid); } ofswitch.write(messages); ofswitch.flush(); } }
@Override public void handleOutgoingMessage(IOFSwitch sw, OFMessage m) { if (sw == null) throw new NullPointerException("Switch must not be null"); if (m == null) throw new NullPointerException("OFMessage must not be null"); FloodlightContext bc = new FloodlightContext(); List<IOFMessageListener> listeners = null; if (messageListeners.containsKey(m.getType())) { listeners = messageListeners.get(m.getType()).getOrderedListeners(); } if (listeners != null) { for (IOFMessageListener listener : listeners) { if (Command.STOP.equals(listener.receive(sw, m, bc))) { break; } } } }
/** * Process a new port. If link discovery is disabled on the port, then do * nothing. If autoportfast feature is enabled and the port is a fast port, * then do nothing. Otherwise, send LLDP message. Add the port to * quarantine. * * @param sw * @param p */ private void processNewPort(DatapathId sw, OFPort p) { if (isLinkDiscoverySuppressed(sw, p)) { // Do nothing as link discovery is suppressed. return; } IOFSwitch iofSwitch = switchService.getSwitch(sw); if (iofSwitch == null) { return; } NodePortTuple npt = new NodePortTuple(sw, p); discover(sw, p); addToQuarantineQueue(npt); }
@Override public boolean isAttachmentPointPort(DatapathId switchid, OFPort port, boolean tunnelEnabled) { // If the switch port is 'tun-bsn' port, it is not // an attachment point port, irrespective of whether // a link is found through it or not. if (linkDiscoveryService.isTunnelPort(switchid, port)) return false; TopologyInstance ti = getCurrentInstance(tunnelEnabled); // if the port is not attachment point port according to // topology instance, then return false if (ti.isAttachmentPointPort(switchid, port) == false) return false; // Check whether the port is a physical port. We should not learn // attachment points on "special" ports. if ((port.getShortPortNumber() & 0xff00) == 0xff00 && port.getShortPortNumber() != (short)0xfffe) return false; // Make sure that the port is enabled. IOFSwitch sw = switchService.getActiveSwitch(switchid); if (sw == null) return false; return (sw.portEnabled(port)); }
void enforceSecurityAcitions(IOFSwitch sw, FPContext cntx, SecurityAction sa){ switch(sa.getType()){ case REDIRECT: RedirectAction ra = (RedirectAction)sa; enforceRedirectAction(ra, library.isARP(cntx), ra.isIgnorePort()); break; case MIRROR: MirrorAction ma = (MirrorAction)sa; enforceMirrorAction(cntx, ma); break; case QUARANTINE: QuarantineAction qa = (QuarantineAction)sa; //proxy arp if (library.isARP(cntx)){ } enforceQuarantineAction(qa); break; case BLOCK: BlockAction ba = (BlockAction)sa; enforceBlockAction(ba); break; } }
@Override public void handleOutgoingMessage(IOFSwitch sw, OFMessage m) { FloodlightContext bc = new FloodlightContext(); List<IOFMessageListener> msgListeners = null; if (listeners.containsKey(m.getType())) { msgListeners = listeners.get(m.getType()).getOrderedListeners(); } if (msgListeners != null) { for (IOFMessageListener listener : msgListeners) { if (Command.STOP.equals(listener.receive(sw, m, bc))) { break; } } } }
public ObfuscationMask getObfuscationMask(long dst, IOFSwitch sw, Route route) { //System.out.println("get mask for " + dst); if (!checkMaskID(dst, route)) { // need new mask if (obfuscationMasks.containsKey(dst)) { // remove because mask must not be used anymore //System.out.println("*** remove mask !***"); obfuscationMasks.remove(dst); oLinkStateManager.resetNumberOfMaskUsages(dst); } } if (!obfuscationMasks.containsKey(dst)) { System.out.println("*** create new mask ***"); obfuscationMasks.put(dst, createNewObfuscationMask(dst)); } return obfuscationMasks.get(dst); }
private OFMessage createHubPacketOut(IOFSwitch sw, OFMessage msg) { OFPacketIn pi = (OFPacketIn) msg; OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); pob.setBufferId(pi.getBufferId()).setXid(pi.getXid()).setInPort((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT))); // set actions OFActionOutput.Builder actionBuilder = sw.getOFFactory().actions().buildOutput(); actionBuilder.setPort(OFPort.FLOOD); pob.setActions(Collections.singletonList((OFAction) actionBuilder.build())); // set data if it is included in the packetin if (pi.getBufferId() == OFBufferId.NO_BUFFER) { byte[] packetData = pi.getData(); pob.setData(packetData); } return pob.build(); }
public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { OFMessage outMessage; HubType ht = HubType.USE_PACKET_OUT; switch (ht) { case USE_FLOW_MOD: outMessage = createHubFlowMod(sw, msg); break; default: case USE_PACKET_OUT: outMessage = createHubPacketOut(sw, msg); break; } sw.write(outMessage); return Command.CONTINUE; }
public void dispatchMessage(IOFSwitch sw, OFMessage msg, FloodlightContext bc) { List<IOFMessageListener> theListeners = listeners.get(msg.getType()).getOrderedListeners(); if (theListeners != null) { Command result = Command.CONTINUE; Iterator<IOFMessageListener> it = theListeners.iterator(); if (OFType.PACKET_IN.equals(msg.getType())) { OFPacketIn pi = (OFPacketIn)msg; Ethernet eth = new Ethernet(); eth.deserialize(pi.getData(), 0, pi.getData().length); IFloodlightProviderService.bcStore.put(bc, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); } while (it.hasNext() && !Command.STOP.equals(result)) { result = it.next().receive(sw, msg, bc); } } }
/** * Writes an OFFlowMod to a switch * @param sw The IOFSwitch to write to * @param flowMod The OFFlowMod to write */ @LogMessageDoc(level="ERROR", message="Tried to write OFFlowMod to {switch} but got {error}", explanation="An I/O error occured while trying to write a " + "static flow to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) private void writeFlowModToSwitch(IOFSwitch sw, OFFlowMod flowMod) { sw.write(flowMod); sw.flush(); }
@Override public void keysModified(Iterator<DatapathId> keys, UpdateType type) { if (type == UpdateType.LOCAL) { // We only care for remote updates return; } while(keys.hasNext()) { DatapathId key = keys.next(); Versioned<SwitchSyncRepresentation> versionedSwitch = null; try { versionedSwitch = storeClient.get(key); } catch (SyncException e) { log.error("Exception while retrieving switch " + key.toString() + " from sync store. Skipping", e); continue; } if (log.isTraceEnabled()) { log.trace("Reveiced switch store notification: key={}, " + "entry={}", key, versionedSwitch.getValue()); } // versionedSwtich won't be null. storeClient.get() always // returns a non-null or throws an exception if (versionedSwitch.getValue() == null) { switchRemovedFromStore(key); continue; } SwitchSyncRepresentation storedSwitch = versionedSwitch.getValue(); IOFSwitch sw = getSwitch(storedSwitch.getDpid()); //TODO @Ryan need to get IOFSwitchBackend setFeaturesReply(storedSwitch.getFeaturesReply(sw.getOFFactory())); if (!key.equals(storedSwitch.getFeaturesReply(sw.getOFFactory()).getDatapathId())) { log.error("Inconsistent DPIDs from switch sync store: " + "key is {} but sw.getId() says {}. Ignoring", key.toString(), sw.getId()); continue; } switchAddedToStore(sw); } }
@Override public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: return processPacketIn(sw, (OFPacketIn)msg, cntx); default: break; } log.warn("Received unexpected message {}", msg); return Command.CONTINUE; }
/** * {@inheritDoc} */ @Override public OFFlowStatsReply dumpFlowTable(final DatapathId dpid) { OFFlowStatsReply values = null; IOFSwitch sw = ofSwitchService.getSwitch(dpid); if (sw == null) { throw new IllegalArgumentException(String.format("Switch %s was not found", dpid.toString())); } OFFactory ofFactory = sw.getOFFactory(); OFFlowStatsRequest flowRequest = ofFactory.buildFlowStatsRequest() .setMatch(sw.getOFFactory().matchWildcardAll()) .setTableId(TableId.ALL) .setOutPort(OFPort.ANY) .setOutGroup(OFGroup.ANY) .setCookieMask(U64.ZERO) .build(); try { ListenableFuture<OFFlowStatsReply> future = sw.writeRequest(flowRequest); values = future.get(10, TimeUnit.SECONDS); } catch (ExecutionException | InterruptedException | TimeoutException e) { logger.error("Could not get flow stats: {}", e.getMessage()); } return values; }
/** Move the channel to SLAVE state * Expects that the channel is in MASTER or SLAVE state. * */ public void changeRoleToSlaveWithRequest() throws Exception { assertTrue("This method can only be called when handler is in " + "MASTER or SLAVE role", switchHandler.isHandshakeComplete()); // Set the role long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_SLAVE); // prepare mocks and inject the role reply message reset(sw); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); expectLastCall().once(); sw.setControllerRole(OFControllerRole.ROLE_SLAVE); expectLastCall().once(); expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).once(); sw.setStatus(SwitchStatus.SLAVE); expectLastCall().once(); replay(sw); reset(switchManager); switchManager.switchStatusChanged(sw, SwitchStatus.MASTER, SwitchStatus.SLAVE); expectLastCall().once(); replay(switchManager); OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE); connection.getListener().messageReceived(connection, reply); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class)); }
@Override public void switchActivated(DatapathId switchId) { IOFSwitch sw = switchService.getSwitch(switchId); if (sw == null) //fix dereference violation in case race conditions return; if (sw.getEnabledPortNumbers() != null) { for (OFPort p : sw.getEnabledPortNumbers()) { processNewPort(sw.getId(), p); } } LDUpdate update = new LDUpdate(sw.getId(), SwitchType.BASIC_SWITCH, UpdateOperation.SWITCH_UPDATED); updates.add(update); }
private ImmutablePair<Long, Boolean> installMeter(final IOFSwitch sw, final DatapathId dpid, final long bandwidth, final long burstSize, final long meterId) { logger.debug("installing meter {} on switch {} width bandwidth {}", meterId, dpid, bandwidth); Set<OFMeterFlags> flags = new HashSet<>(Arrays.asList(OFMeterFlags.KBPS, OFMeterFlags.BURST)); OFFactory ofFactory = sw.getOFFactory(); OFMeterBandDrop.Builder bandBuilder = ofFactory.meterBands() .buildDrop() .setRate(bandwidth) .setBurstSize(burstSize); OFMeterMod.Builder meterModBuilder = ofFactory.buildMeterMod() .setMeterId(meterId) .setCommand(OFMeterModCommand.ADD) .setFlags(flags); if (sw.getOFFactory().getVersion().compareTo(OF_13) > 0) { meterModBuilder.setBands(singletonList(bandBuilder.build())); } else { meterModBuilder.setMeters(singletonList(bandBuilder.build())); } OFMeterMod meterMod = meterModBuilder.build(); boolean response = sw.write(meterMod); return new ImmutablePair<>(meterMod.getXid(), response); }
@Override public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: ctrIncoming.increment(); return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx); default: break; } return Command.CONTINUE; }
/** * Adds a host to the MAC/VLAN->SwitchPort mapping * @param sw The switch to add the mapping to * @param mac The MAC address of the host to add * @param vlan The VLAN that the host is on * @param portVal The switchport that the host is on */ protected void addToPortMap(IOFSwitch sw, MacAddress mac, VlanVid vlan, OFPort portVal) { Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); if (vlan == VlanVid.FULL_MASK || vlan == null) { vlan = VlanVid.ofVlan(0); } if (swMap == null) { // May be accessed by REST API so we need to make it thread safe swMap = Collections.synchronizedMap(new LRULinkedHashMap<MacVlanPair, OFPort>(MAX_MACS_PER_SWITCH)); macVlanToSwitchPortMap.put(sw, swMap); } swMap.put(new MacVlanPair(mac, vlan), portVal); }
/** * Creates a Match based on an inputPort and VlanID. * NB1: that this match only matches on the outer most tag which must be of ether-type 0x8100. * NB2: vlanId of 0 means match on port, not vlan * * @param sw switch object * @param inputPort input port for the match * @param vlanId vlanID to match on; 0 means match on port * @return {@link Match} */ private Match matchFlow(final IOFSwitch sw, final int inputPort, final int vlanId) { Match.Builder mb = sw.getOFFactory().buildMatch(); // // Extra emphasis: vlan of 0 means match on port on not VLAN. // if (vlanId > 0) { mb.setExact(MatchField.IN_PORT, OFPort.of(inputPort)) .setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(vlanId)); } else { mb.setExact(MatchField.IN_PORT, OFPort.of(inputPort)); } return mb.build(); }
private IOFSwitch makeSwitchMock(DatapathId id) { IOFSwitch mockSwitch = createMock(IOFSwitch.class); OFPortDesc mockPortDesc = createMock(OFPortDesc.class); OFPort port = OFPort.of(1); expect(mockSwitch.getId()).andReturn(id).anyTimes(); expect(mockSwitch.getPort(OFPort.of(1))).andReturn(mockPortDesc).anyTimes(); expect(mockPortDesc.getPortNo()).andReturn(port).anyTimes(); return mockSwitch; }
public static OFPortDesc createOFPortDesc(IOFSwitch sw, String name, int number) { OFPortDesc portDesc = sw.getOFFactory().buildPortDesc() .setHwAddr(MacAddress.NONE) .setPortNo(OFPort.of(number)) .setName(name) .build(); return portDesc; }
@Test public void testHandleMessageWithContext() throws Exception { IOFSwitch sw = createMock(IOFSwitch.class); expect(sw.getId()).andReturn(DatapathId.NONE).anyTimes(); IOFMessageListener test1 = createMock(IOFMessageListener.class); expect(test1.getName()).andReturn("test1").anyTimes(); expect(test1.isCallbackOrderingPrereq((OFType)anyObject(), (String)anyObject())) .andReturn(false).anyTimes(); expect(test1.isCallbackOrderingPostreq((OFType)anyObject(), (String)anyObject())) .andReturn(false).anyTimes(); FloodlightContext cntx = new FloodlightContext(); expect(test1.receive(same(sw), same(pi) , same(cntx))) .andReturn(Command.CONTINUE); IOFMessageListener test2 = createMock(IOFMessageListener.class); expect(test2.getName()).andReturn("test2").anyTimes(); expect(test2.isCallbackOrderingPrereq((OFType)anyObject(), (String)anyObject())) .andReturn(false).anyTimes(); expect(test2.isCallbackOrderingPostreq((OFType)anyObject(), (String)anyObject())) .andReturn(false).anyTimes(); // test2 will not receive any message! replay(test1, test2, sw); controller.addOFMessageListener(OFType.PACKET_IN, test1); controller.addOFMessageListener(OFType.ERROR, test2); controller.handleMessage(sw, pi, cntx); verify(test1, test2, sw); Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); assertArrayEquals(testPacket.serialize(), eth.serialize()); }
@Test public void testHARoleChange() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); IOFSwitch sw1 = createMockSwitch(1L); IOFSwitch sw2 = createMockSwitch(2L); replay(sw1, sw2); Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(1), U64.ZERO); NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(1)); LinkInfo info = new LinkInfo(new Date(), new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); // check invariants hold assertNotNull(linkDiscovery.switchLinks.get(lt.getSrc())); assertTrue(linkDiscovery.switchLinks.get(lt.getSrc()).contains(lt)); assertNotNull(linkDiscovery.portLinks.get(srcNpt)); assertTrue(linkDiscovery.portLinks.get(srcNpt).contains(lt)); assertNotNull(linkDiscovery.portLinks.get(dstNpt)); assertTrue(linkDiscovery.portLinks.get(dstNpt).contains(lt)); assertTrue(linkDiscovery.links.containsKey(lt)); /* FIXME: what's the right thing to do here: // check that it clears from memory getMockFloodlightProvider().dispatchRoleChanged(Role.SLAVE); assertTrue(linkDiscovery.switchLinks.isEmpty()); getMockFloodlightProvider().dispatchRoleChanged(Role.MASTER); // check that lldps were sent assertTrue(ldm.isSendLLDPsCalled); assertTrue(ldm.isClearLinksCalled); ldm.reset(); */ }
/** * @param sw * The switch we wish to remove flows from * @param outPort * The specific Output Action OutPort of specific flows we wish * to delete */ public void clearFlowMods(IOFSwitch sw, OFPort outPort) { // Delete all pre-existing flows with the same output action port or // outPort Match match = sw.getOFFactory().buildMatch().build(); OFFlowDelete fm = sw.getOFFactory().buildFlowDelete() .setMatch(match) .setOutPort(outPort) .build(); try { sw.write(fm); } catch (Exception e) { log.error("Failed to clear flows on switch {} - {}", this, e); } }
/** * Check if the two switches differ in their ports or in other * fields and if they differ enqueue a switch update * @param oldSw * @param newSw */ private synchronized void sendNotificationsIfSwitchDiffers(IOFSwitch oldSw, IOFSwitch newSw) { /*TODO @Ryan Collection<PortChangeEvent> portDiffs = oldSw.comparePorts(newSw.getPorts()); for (PortChangeEvent ev: portDiffs) { SwitchUpdate update = new SwitchUpdate(newSw.getId(), SwitchUpdateType.PORTCHANGED, ev.port, ev.type); addUpdateToQueue(update); }*/ }
/** Set the mock expectations for sw when sw is passed to addSwitch * The same expectations can be used when a new SwitchSyncRepresentation * is created from the given mocked switch */ protected void setupSwitchForAddSwitch(IOFSwitch sw, DatapathId datapathId, SwitchDescription description, OFFeaturesReply featuresReply) { if (description == null) { description = createSwitchDescription(); } if (featuresReply == null) { featuresReply = createOFFeaturesReply(datapathId); } List<OFPortDesc> ports = featuresReply.getPorts(); expect(sw.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_10)).anyTimes(); expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes(); expect(sw.getId()).andReturn(datapathId).anyTimes(); expect(sw.getSwitchDescription()).andReturn(description).anyTimes(); expect(sw.getBuffers()) .andReturn(featuresReply.getNBuffers()).anyTimes(); expect(sw.getNumTables()) .andReturn(featuresReply.getNTables()).anyTimes(); expect(sw.getCapabilities()) .andReturn(featuresReply.getCapabilities()).anyTimes(); expect(sw.getActions()) .andReturn(featuresReply.getActions()).anyTimes(); expect(sw.getPorts()) .andReturn(ports).anyTimes(); expect(sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) .andReturn(false).anyTimes(); expect(sw.getInetAddress()).andReturn(null).anyTimes(); }
/** * Check if incoming discovery messages are enabled or not. * @param sw * @param port * @param isStandard * @return */ protected boolean isIncomingDiscoveryAllowed(DatapathId sw, OFPort port, boolean isStandard) { if (isLinkDiscoverySuppressed(sw, port)) { /* Do not process LLDPs from this port as suppressLLDP is set */ return false; } IOFSwitch iofSwitch = switchService.getSwitch(sw); if (iofSwitch == null) { return false; } if (port == OFPort.LOCAL) return false; OFPortDesc ofpPort = iofSwitch.getPort(port); if (ofpPort == null) { if (log.isTraceEnabled()) { log.trace("Null physical port. sw={}, port={}", sw.toString(), port.getPortNumber()); } return false; } return true; }
/** * used to send proxy Arp for load balanced service requests * @param IOFSwitch sw * @param OFPacketIn pi * @param FloodlightContext cntx * @param String vipId */ protected void vipProxyArpReply(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, String vipId) { log.debug("vipProxyArpReply"); Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); // retrieve original arp to determine host configured gw IP address if (! (eth.getPayload() instanceof ARP)) return; ARP arpRequest = (ARP) eth.getPayload(); // have to do proxy arp reply since at this point we cannot determine the requesting application type // generate proxy ARP reply IPacket arpReply = new Ethernet() .setSourceMACAddress(vips.get(vipId).proxyMac) .setDestinationMACAddress(eth.getSourceMACAddress()) .setEtherType(EthType.ARP) .setVlanID(eth.getVlanID()) .setPriorityCode(eth.getPriorityCode()) .setPayload( new ARP() .setHardwareType(ARP.HW_TYPE_ETHERNET) .setProtocolType(ARP.PROTO_TYPE_IP) .setHardwareAddressLength((byte) 6) .setProtocolAddressLength((byte) 4) .setOpCode(ARP.OP_REPLY) .setSenderHardwareAddress(vips.get(vipId).proxyMac) .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress()) .setTargetHardwareAddress(eth.getSourceMACAddress()) .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress())); // push ARP reply out pushPacket(arpReply, sw, OFBufferId.NO_BUFFER, OFPort.ANY, (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)), cntx, true); log.debug("proxy ARP reply pushed as {}", IPv4.fromIPv4Address(vips.get(vipId).address)); return; }
/** * Iterates over all the switches and checks to see if they have controller * connections that points towards another master controller. * @return */ private boolean switchesHaveAnotherMaster() { IOFSwitchService switchService = controller.getSwitchService(); for(Entry<DatapathId, IOFSwitch> switchMap : switchService.getAllSwitchMap().entrySet()){ IOFSwitchBackend sw = (IOFSwitchBackend) switchMap.getValue(); if(sw.hasAnotherMaster()){ return true; } } return false; }