Search in sources :

Example 6 with PathNode

use of org.openkilda.messaging.info.event.PathNode 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 7 with PathNode

use of org.openkilda.messaging.info.event.PathNode in project open-kilda by telstra.

the class IslServiceImpl method discoverLink.

/**
 * {@inheritDoc}
 */
@Override
public void discoverLink(final IslInfoData data) {
    logger.debug("Isl discover: isl={}", data);
    PathNode sourceNode = data.getPath().get(0);
    PathNode destinationNode = data.getPath().get(1);
    Isl isl = islRepository.findIsl(sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo());
    logger.debug("Isl relationship found: {}", isl);
    if (isl == null) {
        Switch sourceSwitch = switchRepository.findByName(sourceNode.getSwitchId());
        Switch destinationSwitch = switchRepository.findByName(destinationNode.getSwitchId());
        if (sourceSwitch == null || destinationSwitch == null) {
            logger.error("Could not find switch: source={}, destination={}", sourceSwitch, destinationSwitch);
            return;
        }
        isl = new Isl(sourceSwitch, destinationSwitch, sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo(), data.getLatency(), data.getSpeed(), 0L);
        // TODO: replace queries on Spring auto generated
        // islRepository.save(isl);
        logger.debug("Isl relationship create: isl={}", isl);
        islRepository.creteIsl(sourceSwitch.getName(), destinationSwitch.getName(), sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo(), data.getLatency(), data.getSpeed(), 0L);
    } else {
        islRepository.updateLatency(sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo(), data.getLatency());
        logger.debug("Isl relationship update: latency={}", data.getLatency());
    }
}
Also used : Isl(org.openkilda.topology.domain.Isl) Switch(org.openkilda.topology.domain.Switch) PathNode(org.openkilda.messaging.info.event.PathNode)

Example 8 with PathNode

use of org.openkilda.messaging.info.event.PathNode in project open-kilda by telstra.

the class IslServiceImpl method dropLink.

/**
 * {@inheritDoc}
 */
@Override
public void dropLink(final IslInfoData data) {
    logger.debug("Isl drop: isl={}", data);
    PathNode sourceNode = data.getPath().get(0);
    PathNode destinationNode = data.getPath().get(1);
    Switch sourceSwitch = switchRepository.findByName(sourceNode.getSwitchId());
    Switch destinationSwitch = switchRepository.findByName(destinationNode.getSwitchId());
    if (sourceSwitch == null || destinationSwitch == null) {
        logger.error("Could not find switch: source={}, destination={}", sourceSwitch, destinationSwitch);
        return;
    }
    Isl isl = islRepository.findIsl(sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo());
    logger.debug("Isl relationship found: {}", isl);
    if (isl == null) {
        throw new MessageException(ErrorType.NOT_FOUND, System.currentTimeMillis());
    }
    // TODO: replace queries on Spring auto generated
    // islRepository.delete(isl);
    islRepository.deleteIsl(sourceNode.getSwitchId(), sourceNode.getPortNo(), destinationNode.getSwitchId(), destinationNode.getPortNo());
    logger.debug("Isl delete relationship: isl={}", isl);
}
Also used : Isl(org.openkilda.topology.domain.Isl) Switch(org.openkilda.topology.domain.Switch) MessageException(org.openkilda.messaging.error.MessageException) PathNode(org.openkilda.messaging.info.event.PathNode)

Example 9 with PathNode

use of org.openkilda.messaging.info.event.PathNode in project open-kilda by telstra.

the class TopologyChecker method isIslEqual.

/**
 * Check whether the link equals the link definition.
 *
 * @param linkDef the link definition
 * @param islInfoData the link to match
 * @return whether the link matches the definition
 */
public static boolean isIslEqual(TopologyDefinition.Isl linkDef, IslInfoData islInfoData) {
    PathNode discoveredSrcNode = islInfoData.getPath().get(0);
    PathNode discoveredDstNode = islInfoData.getPath().get(1);
    return discoveredSrcNode.getSwitchId().equalsIgnoreCase(linkDef.getSrcSwitch().getDpId()) && discoveredSrcNode.getPortNo() == linkDef.getSrcPort() && discoveredDstNode.getSwitchId().equalsIgnoreCase(linkDef.getDstSwitch().getDpId()) && discoveredDstNode.getPortNo() == linkDef.getDstPort();
}
Also used : PathNode(org.openkilda.messaging.info.event.PathNode)

Example 10 with PathNode

use of org.openkilda.messaging.info.event.PathNode in project open-kilda by telstra.

the class FlowReinstallTest method flowPathContainsSwitch.

@Then("^flow (.*) is(.*) built through (.*) switch")
public void flowPathContainsSwitch(final String flow, final String shouldNotContain, final String switchId) throws InterruptedException {
    await().atMost(20, TimeUnit.SECONDS).pollInterval(Duration.ONE_SECOND).until(() -> {
        FlowPathPayload payload = FlowUtils.getFlowPath(FlowUtils.getFlowName(flow));
        assertTrue("Flow path should exist", payload != null && payload.getPath() != null);
        List<PathNode> path = payload.getPath().getPath();
        boolean contains = path.stream().anyMatch(node -> switchId.equalsIgnoreCase(node.getSwitchId()));
        if (StringUtils.isBlank(shouldNotContain)) {
            return contains;
        } else {
            return !contains;
        }
    });
}
Also used : FlowPathPayload(org.openkilda.messaging.payload.flow.FlowPathPayload) PathNode(org.openkilda.messaging.info.event.PathNode) Then(cucumber.api.java.en.Then)

Aggregations

PathNode (org.openkilda.messaging.info.event.PathNode)26 IslInfoData (org.openkilda.messaging.info.event.IslInfoData)14 ArrayList (java.util.ArrayList)8 Test (org.junit.Test)8 Isl (org.openkilda.topology.domain.Isl)7 PathInfoData (org.openkilda.messaging.info.event.PathInfoData)6 CommandMessage (org.openkilda.messaging.command.CommandMessage)5 SwitchInfoData (org.openkilda.messaging.info.event.SwitchInfoData)4 HashSet (java.util.HashSet)3 InfoMessage (org.openkilda.messaging.info.InfoMessage)3 Then (cucumber.api.java.en.Then)2 Set (java.util.Set)2 Message (org.openkilda.messaging.Message)2 FlowRerouteRequest (org.openkilda.messaging.command.flow.FlowRerouteRequest)2 InfoData (org.openkilda.messaging.info.InfoData)2 ImmutablePair (org.openkilda.messaging.model.ImmutablePair)2 Switch (org.openkilda.topology.domain.Switch)2 AbstractStormTest (org.openkilda.wfm.AbstractStormTest)2 JWTVerificationException (com.auth0.jwt.exceptions.JWTVerificationException)1 DecodedJWT (com.auth0.jwt.interfaces.DecodedJWT)1