/** * Send LLDPs to all switch-ports */ protected void discoverOnAllPorts() { log.info("Sending LLDP packets out of all the enabled ports"); // Send standard LLDPs for (DatapathId sw : switchService.getAllSwitchDpids()) { IOFSwitch iofSwitch = switchService.getSwitch(sw); if (iofSwitch == null) continue; if (!iofSwitch.isActive()) continue; /* can't do anything if the switch is SLAVE */ if (iofSwitch.getEnabledPorts() != null) { for (OFPortDesc ofp : iofSwitch.getEnabledPorts()) { if (isLinkDiscoverySuppressed(sw, ofp.getPortNo())) { continue; } sendDiscoveryMessage(sw, ofp.getPortNo(), true, false); // If the switch port is not already in the maintenance // queue, add it. NodePortTuple npt = new NodePortTuple(sw, ofp.getPortNo()); addToMaintenanceQueue(npt); } } } }
/** * We don't react the port changed notifications here. we listen for * OFPortStatus messages directly. Might consider using this notifier * instead */ @Override public void switchPortChanged(DatapathId switchId, OFPortDesc port, PortChangeType type) { switch (type) { case UP: processNewPort(switchId, port.getPortNo()); break; case DELETE: case DOWN: handlePortDown(switchId, port.getPortNo()); break; case OTHER_UPDATE: case ADD: // This is something other than port add or delete. // Topology does not worry about this. // If for some reason the port features change, which // we may have to react. break; } }
public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType, OFPortDesc port, PortChangeType changeType) { if (switchUpdateType == SwitchUpdateType.PORTCHANGED) { if (port == null) { throw new NullPointerException("Port must not be null " + "for PORTCHANGED updates"); } if (changeType == null) { throw new NullPointerException("ChangeType must not be " + "null for PORTCHANGED updates"); } } else { if (port != null || changeType != null) { throw new IllegalArgumentException("port and changeType " + "must be null for " + switchUpdateType + " updates"); } } this.swId = swId; this.switchUpdateType = switchUpdateType; this.port = port; this.changeType = changeType; }
@Override public synchronized void notifyPortChanged(IOFSwitchBackend sw, OFPortDesc port, PortChangeType changeType) { Preconditions.checkNotNull(sw, "switch must not be null"); Preconditions.checkNotNull(port, "port must not be null"); Preconditions.checkNotNull(changeType, "changeType must not be null"); if (role != OFControllerRole.ROLE_MASTER) { counters.invalidPortsChanged.increment(); return; } if (!this.switches.containsKey(sw.getId())) { counters.invalidPortsChanged.increment(); return; } if(sw.getStatus().isVisible()) { // no need to count here. SwitchUpdate.dispatch will count // the portchanged SwitchUpdate update = new SwitchUpdate(sw.getId(), SwitchUpdateType.PORTCHANGED, port, changeType); addUpdateToQueue(update); } }
@Override public void setFeaturesReply(OFFeaturesReply featuresReply) { if (portManager.getPorts().isEmpty() && featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) { /* ports are updated via port status message, so we * only fill in ports on initial connection. */ List<OFPortDesc> OFPortDescs = featuresReply.getPorts(); portManager.updatePorts(OFPortDescs); } this.capabilities = featuresReply.getCapabilities(); this.buffers = featuresReply.getNBuffers(); if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0 ) { // FIXME:LOJI: OF1.3 has per table actions. This needs to be modeled / handled here this.actions = featuresReply.getActions(); } this.tables = featuresReply.getNTables(); }
@Before public void setUp() throws Exception { super.setUp(); cntx = new FloodlightContext(); FloodlightModuleContext fmc = new FloodlightModuleContext(); fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); fmc.addService(IOFSwitchService.class, getMockSwitchService()); swDescription = factory.buildDescStatsReply().build(); pvs = new PathVerificationService(); pvs.initAlgorithm("secret"); srcIpTarget = new InetSocketAddress("192.168.10.1", 200); dstIpTarget = new InetSocketAddress("192.168.10.101", 100); sw1HwAddrTarget = "11:22:33:44:55:66"; sw2HwAddrTarget = "AA:BB:CC:DD:EE:FF"; OFPortDesc sw1Port1 = EasyMock.createMock(OFPortDesc.class); expect(sw1Port1.getHwAddr()).andReturn(MacAddress.of(sw1HwAddrTarget)).anyTimes(); OFPortDesc sw2Port1 = EasyMock.createMock(OFPortDesc.class); expect(sw2Port1.getHwAddr()).andReturn(MacAddress.of(sw2HwAddrTarget)).anyTimes(); replay(sw1Port1); replay(sw2Port1); sw1 = buildMockIOFSwitch(1L, sw1Port1, factory, swDescription, srcIpTarget); sw2 = buildMockIOFSwitch(2L, sw2Port1, factory, swDescription, dstIpTarget); replay(sw1); replay(sw2); }
/** 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) { String dpidString = datapathId.toString(); 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.getId()).andReturn(datapathId).anyTimes(); expect(sw.getId().toString()).andReturn(dpidString).anyTimes(); expect(sw.getSwitchDescription()).andReturn(description).atLeastOnce(); expect(sw.getBuffers()) .andReturn(featuresReply.getNBuffers()).atLeastOnce(); expect(sw.getTables()) .andReturn(featuresReply.getNTables()).atLeastOnce(); expect(sw.getCapabilities()) .andReturn(featuresReply.getCapabilities()).atLeastOnce(); expect(sw.getActions()) .andReturn(featuresReply.getActions()).atLeastOnce(); expect(sw.getPorts()) .andReturn(ports).atLeastOnce(); expect(sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) .andReturn(false).anyTimes(); expect(sw.getInetAddress()).andReturn(null).anyTimes(); }
public OFPortDesc toOFPortDesc(OFFactory factory) { OFPortDesc.Builder builder = factory.buildPortDesc(); builder.setPortNo(port.getPortNo()); builder.setHwAddr(port.getHwAddr()); builder.setName(port.getName()); builder.setConfig(port.getConfig()); builder.setState(port.getState()); builder.setCurr(port.getCurr()); builder.setAdvertised(port.getAdvertised()); builder.setSupported(port.getSupported()); builder.setPeer(port.getPeer()); return builder.build(); }
private OFFeaturesReply createOFFeaturesReply(DatapathId datapathId) { OFFeaturesReply fr = factory.buildFeaturesReply() .setXid(0) .setDatapathId(datapathId) .setPorts(ImmutableList.<OFPortDesc>of()) .build(); return fr; }
@Override /** * Returns a list of standard (Ethernet) ports. * * @return List of ports */ public List<OFPortDesc> getPorts() { return Collections.EMPTY_LIST; }
private static List<SyncedPort> toSyncedPortList(Collection<OFPortDesc> ports) { List<SyncedPort> rv = new ArrayList<SyncedPort>(ports.size()); for (OFPortDesc p: ports) { rv.add(SyncedPort.fromOFPortDesc(p)); } return rv; }
@Override public void changePortState(DeviceId deviceId, PortNumber portNumber, boolean enable) { final Dpid dpid = dpid(deviceId.uri()); OpenFlowSwitch sw = controller.getSwitch(dpid); if (sw == null || !sw.isConnected()) { LOG.error("Failed to change portState on device {}", deviceId); return; } OFPortMod.Builder pmb = sw.factory().buildPortMod(); OFPort port = OFPort.of((int) portNumber.toLong()); pmb.setPortNo(port); if (enable) { pmb.setConfig(0x0); // port_down bit 0 } else { pmb.setConfig(0x1); // port_down bit 1 } pmb.setMask(0x1); pmb.setAdvertise(0x0); for (OFPortDesc pd : sw.getPorts()) { if (pd.getPortNo().equals(port)) { pmb.setHwAddr(pd.getHwAddr()); break; } } sw.sendMsg(Collections.singletonList(pmb.build())); }
private PortDescription buildOduCltPortDescription(OFPortDesc port) { PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); Long portSpeedInMbps = portSpeed(port); CltSignalType sigType = null; switch (portSpeedInMbps.toString()) { case "1000": sigType = CltSignalType.CLT_1GBE; break; case "10000": sigType = CltSignalType.CLT_10GBE; break; case "40000": sigType = CltSignalType.CLT_40GBE; break; case "100000": sigType = CltSignalType.CLT_100GBE; break; default: throw new RuntimeException("Un recognize OduClt speed: " + portSpeedInMbps.toString()); } SparseAnnotations annotations = buildOduCltAnnotation(port); return oduCltPortDescription(portNo, enabled, sigType, annotations); }
private SparseAnnotations buildOduCltAnnotation(OFPortDesc port) { SparseAnnotations annotations = null; String portName = Strings.emptyToNull(port.getName()); if (portName != null) { annotations = DefaultAnnotations.builder() .set(AnnotationKeys.PORT_NAME, portName) .set(AnnotationKeys.STATIC_PORT, Boolean.TRUE.toString()).build(); } return annotations; }
/** * Build a portDescription from a given Ethernet port description. * * @param port the port to build from. * @return portDescription for the port. */ private PortDescription buildPortDescription(OFPortDesc port) { PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER; SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); return new DefaultPortDescription(portNo, enabled, type, portSpeed(port), annotations); }
public OFPortDesc getPort(String name) { if (name == null) { throw new NullPointerException("Port name must not be null"); } lock.readLock().lock(); try { return portsByName.get(name.toLowerCase()); } finally { lock.readLock().unlock(); } }
@Override public void switchActivated(DatapathId switchId) { IOFSwitch sw = switchService.getSwitch(switchId); if (sw == null) { log.warn("Switch {} was activated but had no switch object in the switch service. Perhaps it quickly disconnected", switchId); return; } if (OFDPAUtils.isOFDPASwitch(sw)) { sw.write(sw.getOFFactory().buildFlowDelete() .setTableId(TableId.ALL) .build() ); sw.write(sw.getOFFactory().buildGroupDelete() .setGroup(OFGroup.ANY) .setGroupType(OFGroupType.ALL) .build() ); sw.write(sw.getOFFactory().buildGroupDelete() .setGroup(OFGroup.ANY) .setGroupType(OFGroupType.INDIRECT) .build() ); sw.write(sw.getOFFactory().buildBarrierRequest().build()); List<OFPortModeTuple> portModes = new ArrayList<OFPortModeTuple>(); for (OFPortDesc p : sw.getPorts()) { portModes.add(OFPortModeTuple.of(p.getPortNo(), OFPortMode.ACCESS)); } if (log.isWarnEnabled()) { log.warn("For OF-DPA switch {}, initializing VLAN {} on ports {}", new Object[] { switchId, VlanVid.ZERO, portModes}); } OFDPAUtils.addLearningSwitchPrereqs(sw, VlanVid.ZERO, portModes); } }
/** * Send link discovery message out of a given switch port. The discovery * message may be a standard LLDP or a modified LLDP, where the dst mac * address is set to :ff. TODO: The modified LLDP will updated in the future * and may use a different eth-type. * * @param sw * @param port * @param isStandard * indicates standard or modified LLDP * @param isReverse * indicates whether the LLDP was sent as a response */ @LogMessageDoc(level = "ERROR", message = "Failure sending LLDP out port {port} on switch {switch}", explanation = "An I/O error occured while sending LLDP message " + "to the switch.", recommendation = LogMessageDoc.CHECK_SWITCH) protected void sendDiscoveryMessage(DatapathId sw, OFPort port, boolean isStandard, boolean isReverse) { // Takes care of all checks including null pointer checks. if (!isOutgoingDiscoveryAllowed(sw, port, isStandard, isReverse)) return; IOFSwitch iofSwitch = switchService.getSwitch(sw); OFPortDesc ofpPort = iofSwitch.getPort(port); if (log.isTraceEnabled()) { log.trace("Sending LLDP packet out of swich: {}, port: {}", sw.toString(), port.getPortNumber()); } OFPacketOut po = generateLLDPMessage(sw, port, isStandard, isReverse); OFPacketOut.Builder pob = po.createBuilder(); // Add actions List<OFAction> actions = getDiscoveryActions(iofSwitch, ofpPort.getPortNo()); pob.setActions(actions); // no need to set length anymore // send // no more try-catch. switch will silently fail iofSwitch.write(pob.build()); iofSwitch.flush(); }
/** * Check if outgoing discovery messages are enabled or not. * @param sw * @param port * @param isStandard * @param isReverse * @return */ protected boolean isOutgoingDiscoveryAllowed(DatapathId sw, OFPort port, boolean isStandard, boolean isReverse) { if (isLinkDiscoverySuppressed(sw, port)) { /* Dont send LLDPs out of 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; } else { return true; } }
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; }
@Override public void switchAdded(DatapathId dpid) { /* Insert static flows on all ports of the switch to redirect * DHCP client --> DHCP DHCPServer traffic to the controller. * DHCP client's operate on UDP port 67 */ IOFSwitch sw = switchService.getSwitch(dpid); //fix concurrency flaw if (sw == null){ return; } OFFlowAdd.Builder flow = sw.getOFFactory().buildFlowAdd(); Match.Builder match = sw.getOFFactory().buildMatch(); ArrayList<OFAction> actionList = new ArrayList<OFAction>(); OFActionOutput.Builder action = sw.getOFFactory().actions().buildOutput(); for (OFPortDesc port : sw.getPorts()) { match.setExact(MatchField.IN_PORT, port.getPortNo()); match.setExact(MatchField.ETH_TYPE, EthType.IPv4); match.setExact(MatchField.IP_PROTO, IpProtocol.UDP); match.setExact(MatchField.UDP_SRC, UDP.DHCP_CLIENT_PORT); action.setMaxLen(0xffFFffFF); action.setPort(OFPort.CONTROLLER); actionList.add(action.build()); flow.setBufferId(OFBufferId.NO_BUFFER); flow.setHardTimeout(0); flow.setIdleTimeout(0); flow.setOutPort(OFPort.CONTROLLER); flow.setActions(actionList); flow.setMatch(match.build()); flow.setPriority(32767); sfp.addFlow("dhcp-port---" + port.getPortNo().getPortNumber() + "---(" + port.getName() + ")", flow.build(), sw.getId()); } }
@Override public Collection<OFPortDesc> getSortedPorts() { List<OFPortDesc> sortedPorts = new ArrayList<OFPortDesc>(portManager.getPorts()); Collections.sort(sortedPorts, new Comparator<OFPortDesc>() { @Override public int compare(OFPortDesc o1, OFPortDesc o2) { String name1 = o1.getName(); String name2 = o2.getName(); return name1.compareToIgnoreCase(name2); } }); return sortedPorts; }
@Override public void setPortDescStats(OFPortDescStatsReply reply) { /* ports are updated via port status message, so we * only fill in ports on initial connection. */ List<OFPortDesc> OFPortDescs = reply.getEntries(); portManager.updatePorts(OFPortDescs); }
private static List<OFPortDesc> toOFPortDescList(OFFactory factory, Collection<SyncedPort> ports) { List<OFPortDesc> rv = new ArrayList<OFPortDesc>(ports.size()); for (SyncedPort p: ports) { rv.add(p.toOFPortDesc(factory)); } return rv; }
OFPortDescStatsReply getPortDescStatsReply() { OFPortDesc portDesc = factory.buildPortDesc() .setName("Eth1") .setPortNo(OFPort.of(1)) .build(); return factory.buildPortDescStatsReply() .setEntries(ImmutableList.<OFPortDesc>of(portDesc)) .build(); }
/** * Set the internal data structure storing this switch's port * to the ports specified by newPortsByNumber * * CALLER MUST HOLD WRITELOCK * * @param newPortsByNumber * @throws IllegaalStateException if called without holding the * writelock */ private void updatePortsWithNewPortsByNumber( Map<OFPort,OFPortDesc> newPortsByNumber) { if (!lock.writeLock().isHeldByCurrentThread()) { throw new IllegalStateException("Method called without " + "holding writeLock"); } Map<String,OFPortDesc> newPortsByName = new HashMap<String, OFPortDesc>(); List<OFPortDesc> newPortList = new ArrayList<OFPortDesc>(); List<OFPortDesc> newEnabledPortList = new ArrayList<OFPortDesc>(); List<OFPort> newEnabledPortNumbers = new ArrayList<OFPort>(); for(OFPortDesc p: newPortsByNumber.values()) { newPortList.add(p); newPortsByName.put(p.getName().toLowerCase(), p); if (!p.getState().contains(OFPortState.LINK_DOWN) && !p.getConfig().contains(OFPortConfig.PORT_DOWN)) { if (!newEnabledPortList.contains(p)) { newEnabledPortList.add(p); } if (!newEnabledPortNumbers.contains(p.getPortNo())) { newEnabledPortNumbers.add(p.getPortNo()); } } } portsByName = Collections.unmodifiableMap(newPortsByName); portsByNumber = Collections.unmodifiableMap(newPortsByNumber); enabledPortList = Collections.unmodifiableList(newEnabledPortList); enabledPortNumbers = Collections.unmodifiableList(newEnabledPortNumbers); portList = Collections.unmodifiableList(newPortList); }
public OFPortDesc getPort(OFPort portNumber) { lock.readLock().lock(); try { return portsByNumber.get(portNumber); } finally { lock.readLock().unlock(); } }
public List<OFPortDesc> getPorts() { lock.readLock().lock(); try { return portList; } finally { lock.readLock().unlock(); } }
@Override public void switchPortChanged(DatapathId switchId, OFPortDesc port, PortChangeType type) { String msg = String.format("Switch %s port %s changed: %s", switchId, port.getName(), type.toString()); notifier.postNotification(msg); }
private void floodArpRequest(IOFSwitch sw, IPv4Address requestedAddress) { IPacket arpRequest = new Ethernet() .setSourceMACAddress("00:00:00:00:00:01") .setDestinationMACAddress("ff:ff:ff:ff:ff:ff") .setEtherType(EthType.ARP) .setVlanID((short) 0) .setPriorityCode((byte) 0) .setPayload( new ARP() .setHardwareType(ARP.HW_TYPE_ETHERNET) .setProtocolType(ARP.PROTO_TYPE_IP) .setHardwareAddressLength((byte) 6) .setProtocolAddressLength((byte) 4) .setOpCode(ARP.OP_REQUEST) .setSenderHardwareAddress(HexString.fromHexString("00:00:00:00:00:01")) .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.111")) .setTargetHardwareAddress(HexString.fromHexString("00:00:00:00:00:00")) .setTargetProtocolAddress(requestedAddress.getBytes())); Set<OFPort> portsConnectedToSwitches = new HashSet<OFPort>(); for (Link link : linkDiscoveryService.getSwitchLinks().get(sw.getId())) { if (link.getSrc() == sw.getId()) portsConnectedToSwitches.add(link.getSrcPort()); } for (OFPortDesc port : sw.getPorts()) { if (!portsConnectedToSwitches.contains(port.getPortNo())) { pushPacket(arpRequest, sw, OFBufferId.NO_BUFFER, OFPort.ANY, port.getPortNo()); } } }
/** * 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; }