Search in sources :

Example 1 with IOFSwitch

use of net.floodlightcontroller.core.IOFSwitch in project open-kilda by telstra.

the class PathVerificationService method handlePacketIn.

private IListener.Command handlePacketIn(IOFSwitch sw, OFPacketIn pkt, FloodlightContext context) {
    long time = System.currentTimeMillis();
    logger.debug("packet_in {} received from {}", pkt.getXid(), sw.getId());
    VerificationPacket verificationPacket = null;
    Ethernet eth = IFloodlightProviderService.bcStore.get(context, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
    try {
        verificationPacket = deserialize(eth);
    } catch (Exception exception) {
        logger.error("Deserialization failure: {}, exception: {}", exception.getMessage(), exception);
        return Command.CONTINUE;
    }
    try {
        OFPort inPort = pkt.getVersion().compareTo(OFVersion.OF_12) < 0 ? pkt.getInPort() : pkt.getMatch().get(MatchField.IN_PORT);
        ByteBuffer portBB = ByteBuffer.wrap(verificationPacket.getPortId().getValue());
        portBB.position(1);
        OFPort remotePort = OFPort.of(portBB.getShort());
        long timestamp = 0;
        int pathOrdinal = 10;
        IOFSwitch remoteSwitch = null;
        boolean signed = false;
        for (LLDPTLV lldptlv : verificationPacket.getOptionalTLVList()) {
            if (lldptlv.getType() == 127 && lldptlv.getLength() == 12 && lldptlv.getValue()[0] == 0x0 && lldptlv.getValue()[1] == 0x26 && lldptlv.getValue()[2] == (byte) 0xe1 && lldptlv.getValue()[3] == 0x0) {
                ByteBuffer dpidBB = ByteBuffer.wrap(lldptlv.getValue());
                remoteSwitch = switchService.getSwitch(DatapathId.of(dpidBB.getLong(4)));
            } else if (lldptlv.getType() == 127 && lldptlv.getLength() == 12 && lldptlv.getValue()[0] == 0x0 && lldptlv.getValue()[1] == 0x26 && lldptlv.getValue()[2] == (byte) 0xe1 && lldptlv.getValue()[3] == 0x01) {
                ByteBuffer tsBB = ByteBuffer.wrap(lldptlv.getValue());
                /* skip OpenFlow OUI (4 bytes above) */
                long swLatency = sw.getLatency().getValue();
                timestamp = tsBB.getLong(4);
                /* include the RX switch latency to "subtract" it */
                timestamp = timestamp + swLatency;
            } else if (lldptlv.getType() == 127 && lldptlv.getLength() == 8 && lldptlv.getValue()[0] == 0x0 && lldptlv.getValue()[1] == 0x26 && lldptlv.getValue()[2] == (byte) 0xe1 && lldptlv.getValue()[3] == 0x02) {
                ByteBuffer typeBB = ByteBuffer.wrap(lldptlv.getValue());
                pathOrdinal = typeBB.getInt(4);
            } else if (lldptlv.getType() == 127 && lldptlv.getValue()[0] == 0x0 && lldptlv.getValue()[1] == 0x26 && lldptlv.getValue()[2] == (byte) 0xe1 && lldptlv.getValue()[3] == 0x03) {
                ByteBuffer bb = ByteBuffer.wrap(lldptlv.getValue());
                bb.position(4);
                byte[] tokenArray = new byte[lldptlv.getLength() - 4];
                bb.get(tokenArray, 0, tokenArray.length);
                String token = new String(tokenArray);
                try {
                    DecodedJWT jwt = verifier.verify(token);
                    signed = true;
                } catch (JWTVerificationException e) {
                    logger.error("Packet verification failed", e);
                    return Command.STOP;
                }
            }
        }
        if (remoteSwitch == null) {
            return Command.STOP;
        }
        if (!signed) {
            logger.warn("verification packet without sign");
            return Command.STOP;
        }
        U64 latency = (timestamp != 0 && (time - timestamp) > 0) ? U64.of(time - timestamp) : U64.ZERO;
        logger.debug("link discovered: {}-{} ===( {} ms )===> {}-{}", remoteSwitch.getId(), remotePort, latency.getValue(), sw.getId(), inPort);
        // this verification packet was sent from remote switch/port to received switch/port
        // so the link direction is from remote switch/port to received switch/port
        List<PathNode> nodes = Arrays.asList(new PathNode(remoteSwitch.getId().toString(), remotePort.getPortNumber(), 0, latency.getValue()), new PathNode(sw.getId().toString(), inPort.getPortNumber(), 1));
        OFPortDesc port = sw.getPort(inPort);
        long speed = Integer.MAX_VALUE;
        if (port.getVersion().compareTo(OFVersion.OF_13) > 0) {
            for (OFPortDescProp prop : port.getProperties()) {
                if (prop.getType() == 0x0) {
                    speed = ((OFPortDescPropEthernet) prop).getCurrSpeed();
                }
            }
        } else {
            speed = port.getCurrSpeed();
        }
        IslInfoData path = new IslInfoData(latency.getValue(), nodes, speed, IslChangeType.DISCOVERED, getAvailableBandwidth(speed));
        Message message = new InfoMessage(path, System.currentTimeMillis(), "system", null);
        final String json = MAPPER.writeValueAsString(message);
        logger.debug("about to send {}", json);
        producer.send(new ProducerRecord<>(TOPIC, json));
        logger.debug("packet_in processed for {}-{}", sw.getId(), inPort);
    } catch (JsonProcessingException exception) {
        logger.error("could not create json for path packet_in: {}", exception.getMessage(), exception);
    } catch (UnsupportedOperationException exception) {
        logger.error("could not parse packet_in message: {}", exception.getMessage(), exception);
    } catch (Exception exception) {
        logger.error("unknown error during packet_in message processing: {}", exception.getMessage(), exception);
        throw exception;
    }
    return Command.STOP;
}
Also used : IOFSwitch(net.floodlightcontroller.core.IOFSwitch) InfoMessage(org.openkilda.messaging.info.InfoMessage) OFMessage(org.projectfloodlight.openflow.protocol.OFMessage) Message(org.openkilda.messaging.Message) OFPortDescProp(org.projectfloodlight.openflow.protocol.OFPortDescProp) PathNode(org.openkilda.messaging.info.event.PathNode) ByteBuffer(java.nio.ByteBuffer) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JWTVerificationException(com.auth0.jwt.exceptions.JWTVerificationException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) FloodlightModuleException(net.floodlightcontroller.core.module.FloodlightModuleException) JWTVerificationException(com.auth0.jwt.exceptions.JWTVerificationException) U64(org.projectfloodlight.openflow.types.U64) OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) InfoMessage(org.openkilda.messaging.info.InfoMessage) OFPortDescPropEthernet(org.projectfloodlight.openflow.protocol.OFPortDescPropEthernet) Ethernet(net.floodlightcontroller.packet.Ethernet) OFPort(org.projectfloodlight.openflow.types.OFPort) IslInfoData(org.openkilda.messaging.info.event.IslInfoData) DecodedJWT(com.auth0.jwt.interfaces.DecodedJWT) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) LLDPTLV(net.floodlightcontroller.packet.LLDPTLV)

Example 2 with IOFSwitch

use of net.floodlightcontroller.core.IOFSwitch in project open-kilda by telstra.

the class SwitchEventCollector method switchActivated.

/**
 * {@inheritDoc}
 */
@Override
public void switchActivated(final DatapathId switchId) {
    final IOFSwitch sw = switchService.getSwitch(switchId);
    logger.info("ACTIVATING SWITCH: {}", switchId);
    // Message message = buildExtendedSwitchMessage(sw, SwitchState.ACTIVATED, switchManager.dumpFlowTable(switchId));
    // kafkaProducer.postMessage(TOPO_EVENT_TOPIC, message);
    ConnectModeRequest.Mode mode = switchManager.connectMode(null);
    try {
        if (mode == ConnectModeRequest.Mode.SAFE) {
            // the bulk of work below is done as part of the safe protocol
            switchManager.startSafeMode(switchId);
            return;
        }
        switchManager.sendSwitchActivate(sw);
        if (mode == ConnectModeRequest.Mode.AUTO) {
            switchManager.installDefaultRules(switchId);
        }
        // else MANUAL MODE - Don't install default rules. NB: without the default rules,
        // ISL discovery will fail.
        switchManager.sendPortUpEvents(sw);
    } catch (SwitchOperationException e) {
        logger.error("Could not activate switch={}", switchId);
    }
}
Also used : IOFSwitch(net.floodlightcontroller.core.IOFSwitch) ConnectModeRequest(org.openkilda.messaging.command.switches.ConnectModeRequest)

Example 3 with IOFSwitch

use of net.floodlightcontroller.core.IOFSwitch in project open-kilda by telstra.

the class RecordHandler method doNetworkDump.

/**
 * Create network dump for OFELinkBolt
 *
 * @param message NetworkCommandData
 */
private void doNetworkDump(final CommandMessage message) {
    logger.info("Create network dump");
    NetworkCommandData command = (NetworkCommandData) message.getData();
    Map<DatapathId, IOFSwitch> allSwitchMap = context.getSwitchManager().getAllSwitchMap();
    Set<SwitchInfoData> switchesInfoData = allSwitchMap.values().stream().map(this::buildSwitchInfoData).collect(Collectors.toSet());
    Set<PortInfoData> portsInfoData = allSwitchMap.values().stream().flatMap(sw -> sw.getEnabledPorts().stream().map(port -> new PortInfoData(sw.getId().toString(), port.getPortNo().getPortNumber(), null, PortChangeType.UP)).collect(Collectors.toSet()).stream()).collect(Collectors.toSet());
    NetworkInfoData dump = new NetworkInfoData(command.getRequester(), switchesInfoData, portsInfoData, Collections.emptySet(), Collections.emptySet());
    InfoMessage infoMessage = new InfoMessage(dump, System.currentTimeMillis(), message.getCorrelationId());
    context.getKafkaProducer().postMessage(OUTPUT_DISCO_TOPIC, infoMessage);
}
Also used : InfoMessage(org.openkilda.messaging.info.InfoMessage) OFFlowStatsConverter(org.openkilda.floodlight.converter.OFFlowStatsConverter) LoggerFactory(org.slf4j.LoggerFactory) InstallTransitFlow(org.openkilda.messaging.command.flow.InstallTransitFlow) SwitchRulesInstallRequest(org.openkilda.messaging.command.switches.SwitchRulesInstallRequest) SwitchRulesDeleteRequest(org.openkilda.messaging.command.switches.SwitchRulesDeleteRequest) IOFSwitch(net.floodlightcontroller.core.IOFSwitch) SwitchOperationException(org.openkilda.floodlight.switchmanager.SwitchOperationException) CommandMessage(org.openkilda.messaging.command.CommandMessage) PortChangeType(org.openkilda.messaging.info.event.PortChangeType) Arrays.asList(java.util.Arrays.asList) DeleteRulesAction(org.openkilda.messaging.command.switches.DeleteRulesAction) ConnectModeRequest(org.openkilda.messaging.command.switches.ConnectModeRequest) SwitchFlowEntries(org.openkilda.messaging.info.rule.SwitchFlowEntries) OutputVlanType(org.openkilda.messaging.payload.flow.OutputVlanType) RemoveFlow(org.openkilda.messaging.command.flow.RemoveFlow) DiscoverIslCommandData(org.openkilda.messaging.command.discovery.DiscoverIslCommandData) SwitchInfoData(org.openkilda.messaging.info.event.SwitchInfoData) InstallMissedFlowsRequest(org.openkilda.messaging.command.switches.InstallMissedFlowsRequest) IOFSwitchConverter(org.openkilda.floodlight.converter.IOFSwitchConverter) ISwitchManager(org.openkilda.floodlight.switchmanager.ISwitchManager) Collectors(java.util.stream.Collectors) InstallEgressFlow(org.openkilda.messaging.command.flow.InstallEgressFlow) OFPort(org.projectfloodlight.openflow.types.OFPort) DumpRulesRequest(org.openkilda.messaging.command.switches.DumpRulesRequest) Topic(org.openkilda.messaging.Topic) ConsumerRecord(org.apache.kafka.clients.consumer.ConsumerRecord) MeterPool(org.openkilda.floodlight.switchmanager.MeterPool) InstallIngressFlow(org.openkilda.messaging.command.flow.InstallIngressFlow) CommandData(org.openkilda.messaging.command.CommandData) java.util(java.util) SwitchState(org.openkilda.messaging.info.event.SwitchState) NetworkInfoData(org.openkilda.messaging.info.discovery.NetworkInfoData) BaseInstallFlow(org.openkilda.messaging.command.flow.BaseInstallFlow) OFFlowStatsReply(org.projectfloodlight.openflow.protocol.OFFlowStatsReply) MAPPER(org.openkilda.messaging.Utils.MAPPER) ConnectModeResponse(org.openkilda.messaging.info.switches.ConnectModeResponse) Logger(org.slf4j.Logger) DiscoverPathCommandData(org.openkilda.messaging.command.discovery.DiscoverPathCommandData) NetworkCommandData(org.openkilda.messaging.command.discovery.NetworkCommandData) ErrorType(org.openkilda.messaging.error.ErrorType) FlowEntry(org.openkilda.messaging.info.rule.FlowEntry) CommandWithReplyToMessage(org.openkilda.messaging.command.CommandWithReplyToMessage) PortInfoData(org.openkilda.messaging.info.event.PortInfoData) InstallOneSwitchFlow(org.openkilda.messaging.command.flow.InstallOneSwitchFlow) InstallRulesAction(org.openkilda.messaging.command.switches.InstallRulesAction) SwitchRulesResponse(org.openkilda.messaging.info.switches.SwitchRulesResponse) Destination(org.openkilda.messaging.Destination) DatapathId(org.projectfloodlight.openflow.types.DatapathId) ErrorData(org.openkilda.messaging.error.ErrorData) ErrorMessage(org.openkilda.messaging.error.ErrorMessage) IOFSwitch(net.floodlightcontroller.core.IOFSwitch) NetworkInfoData(org.openkilda.messaging.info.discovery.NetworkInfoData) InfoMessage(org.openkilda.messaging.info.InfoMessage) DatapathId(org.projectfloodlight.openflow.types.DatapathId) PortInfoData(org.openkilda.messaging.info.event.PortInfoData) NetworkCommandData(org.openkilda.messaging.command.discovery.NetworkCommandData) SwitchInfoData(org.openkilda.messaging.info.event.SwitchInfoData)

Example 4 with IOFSwitch

use of net.floodlightcontroller.core.IOFSwitch in project open-kilda by telstra.

the class PathVerificationService method sendDiscoveryMessage.

@Override
public boolean sendDiscoveryMessage(DatapathId srcSwId, OFPort port, DatapathId dstSwId) {
    boolean result = false;
    try {
        IOFSwitch srcSwitch = switchService.getSwitch(srcSwId);
        if (srcSwitch != null && srcSwitch.getPort(port) != null) {
            IOFSwitch dstSwitch = (dstSwId == null) ? null : switchService.getSwitch(dstSwId);
            OFPacketOut ofPacketOut = generateVerificationPacket(srcSwitch, port, dstSwitch, true);
            if (ofPacketOut != null) {
                logger.debug("==> Sending verification packet out {}/{}: {}", srcSwitch.getId().toString(), port.getPortNumber(), Hex.encodeHexString(ofPacketOut.getData()));
                result = srcSwitch.write(ofPacketOut);
            } else {
                logger.error("<== Received null from generateVerificationPacket, inputs where: " + "srcSwitch: {}, port: {}, dstSwitch: {}", srcSwitch, port, dstSwitch);
            }
        }
    } catch (Exception exception) {
        logger.error("Error trying to sendDiscoveryMessage: {}", exception);
    }
    return result;
}
Also used : IOFSwitch(net.floodlightcontroller.core.IOFSwitch) OFPacketOut(org.projectfloodlight.openflow.protocol.OFPacketOut) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JWTVerificationException(com.auth0.jwt.exceptions.JWTVerificationException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) FloodlightModuleException(net.floodlightcontroller.core.module.FloodlightModuleException)

Example 5 with IOFSwitch

use of net.floodlightcontroller.core.IOFSwitch in project open-kilda by telstra.

the class RecordHandlerTest method networkDumpTest.

/**
 * Simple TDD test that was used to develop warming mechanism for OFELinkBolt. We create
 * command and put it to KafkaMessageCollector then mock ISwitchManager::getAllSwitchMap and
 * verify that output message comes to producer.
 */
@Test
public void networkDumpTest() {
    // Cook mock data for ISwitchManager::getAllSwitchMap
    // Two switches with two ports on each
    // switches for ISwitchManager::getAllSwitchMap
    OFSwitch iofSwitch1 = mock(OFSwitch.class);
    OFSwitch iofSwitch2 = mock(OFSwitch.class);
    Map<DatapathId, IOFSwitch> switches = ImmutableMap.of(DatapathId.of(1), iofSwitch1, DatapathId.of(2), iofSwitch2);
    for (DatapathId swId : switches.keySet()) {
        IOFSwitch sw = switches.get(swId);
        expect(sw.isActive()).andReturn(true).anyTimes();
        expect(sw.getId()).andReturn(swId).anyTimes();
    }
    expect(switchManager.getAllSwitchMap()).andReturn(switches);
    // ports for OFSwitch::getEnabledPorts
    OFPortDesc ofPortDesc1 = mock(OFPortDesc.class);
    OFPortDesc ofPortDesc2 = mock(OFPortDesc.class);
    OFPortDesc ofPortDesc3 = mock(OFPortDesc.class);
    OFPortDesc ofPortDesc4 = mock(OFPortDesc.class);
    expect(ofPortDesc1.getPortNo()).andReturn(OFPort.ofInt(1));
    expect(ofPortDesc2.getPortNo()).andReturn(OFPort.ofInt(2));
    expect(ofPortDesc3.getPortNo()).andReturn(OFPort.ofInt(3));
    expect(ofPortDesc4.getPortNo()).andReturn(OFPort.ofInt(4));
    expect(iofSwitch1.getEnabledPorts()).andReturn(ImmutableList.of(ofPortDesc1, ofPortDesc2));
    expect(iofSwitch2.getEnabledPorts()).andReturn(ImmutableList.of(ofPortDesc3, ofPortDesc4));
    // Logic in SwitchEventCollector.buildSwitchInfoData is too complicated and requires a lot
    // of mocking code so I replaced it with mock on kafkaMessageCollector.buildSwitchInfoData
    handler.overrideSwitchInfoData(DatapathId.of(1), new SwitchInfoData("sw1", SwitchState.ADDED, "127.0.0.1", "localhost", "test switch", "kilda"));
    handler.overrideSwitchInfoData(DatapathId.of(2), new SwitchInfoData("sw2", SwitchState.ADDED, "127.0.0.1", "localhost", "test switch", "kilda"));
    // setup hook for verify that we create new message for producer
    producer.postMessage(eq(OUTPUT_DISCO_TOPIC), anyObject(InfoMessage.class));
    replayAll();
    // Create CommandMessage with NetworkCommandData for trigger network dump
    CommandMessage command = new CommandMessage(new NetworkCommandData(), System.currentTimeMillis(), Utils.SYSTEM_CORRELATION_ID, Destination.CONTROLLER);
    // KafkaMessageCollector contains a complicated run logic with couple nested private
    // classes, threading and that is very painful for writing clear looking test code so I
    // created the simple method in KafkaMessageCollector for simplifying test logic.
    handler.handleMessage(command);
    verify(producer);
// TODO: verify content of InfoMessage in producer.postMessage
}
Also used : IOFSwitch(net.floodlightcontroller.core.IOFSwitch) OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) InfoMessage(org.openkilda.messaging.info.InfoMessage) IOFSwitch(net.floodlightcontroller.core.IOFSwitch) OFSwitch(net.floodlightcontroller.core.internal.OFSwitch) DatapathId(org.projectfloodlight.openflow.types.DatapathId) SwitchInfoData(org.openkilda.messaging.info.event.SwitchInfoData) NetworkCommandData(org.openkilda.messaging.command.discovery.NetworkCommandData) CommandMessage(org.openkilda.messaging.command.CommandMessage) Test(org.junit.Test)

Aggregations

IOFSwitch (net.floodlightcontroller.core.IOFSwitch)8 DatapathId (org.projectfloodlight.openflow.types.DatapathId)4 InfoMessage (org.openkilda.messaging.info.InfoMessage)3 JWTVerificationException (com.auth0.jwt.exceptions.JWTVerificationException)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 FloodlightModuleException (net.floodlightcontroller.core.module.FloodlightModuleException)2 Ethernet (net.floodlightcontroller.packet.Ethernet)2 CommandMessage (org.openkilda.messaging.command.CommandMessage)2 NetworkCommandData (org.openkilda.messaging.command.discovery.NetworkCommandData)2 SwitchInfoData (org.openkilda.messaging.info.event.SwitchInfoData)2 OFPacketOut (org.projectfloodlight.openflow.protocol.OFPacketOut)2 DecodedJWT (com.auth0.jwt.interfaces.DecodedJWT)1 ByteBuffer (java.nio.ByteBuffer)1 java.util (java.util)1 Arrays.asList (java.util.Arrays.asList)1 HashMap (java.util.HashMap)1 Collectors (java.util.stream.Collectors)1 FloodlightContext (net.floodlightcontroller.core.FloodlightContext)1 SwitchDescription (net.floodlightcontroller.core.SwitchDescription)1