Search in sources :

Example 1 with OFPortDesc

use of org.projectfloodlight.openflow.protocol.OFPortDesc 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 OFPortDesc

use of org.projectfloodlight.openflow.protocol.OFPortDesc in project open-kilda by telstra.

the class PathVerificationService method generateVerificationPacket.

public OFPacketOut generateVerificationPacket(IOFSwitch srcSw, OFPort port, IOFSwitch dstSw, boolean sign) {
    try {
        OFPortDesc ofPortDesc = srcSw.getPort(port);
        byte[] chassisId = new byte[] { 4, 0, 0, 0, 0, 0, 0 };
        byte[] portId = new byte[] { 2, 0, 0 };
        byte[] ttlValue = new byte[] { 0, 0x78 };
        byte[] dpidTLVValue = new byte[] { 0x0, 0x26, (byte) 0xe1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        LLDPTLV dpidTLV = new LLDPTLV().setType((byte) 127).setLength((short) dpidTLVValue.length).setValue(dpidTLVValue);
        byte[] dpidArray = new byte[8];
        ByteBuffer dpidBB = ByteBuffer.wrap(dpidArray);
        ByteBuffer portBB = ByteBuffer.wrap(portId, 1, 2);
        DatapathId dpid = srcSw.getId();
        dpidBB.putLong(dpid.getLong());
        System.arraycopy(dpidArray, 2, chassisId, 1, 6);
        // Set the optionalTLV to the full SwitchID
        System.arraycopy(dpidArray, 0, dpidTLVValue, 4, 8);
        byte[] zeroMac = { 0, 0, 0, 0, 0, 0 };
        byte[] srcMac = ofPortDesc.getHwAddr().getBytes();
        if (Arrays.equals(srcMac, zeroMac)) {
            int portVal = ofPortDesc.getPortNo().getPortNumber();
            // this is a common scenario
            logger.debug("Port {}/{} has zero hardware address: overwrite with lower 6 bytes of dpid", dpid.toString(), portVal);
            System.arraycopy(dpidArray, 2, srcMac, 0, 6);
        }
        portBB.putShort(port.getShortPortNumber());
        VerificationPacket vp = new VerificationPacket();
        vp.setChassisId(new LLDPTLV().setType((byte) 1).setLength((short) chassisId.length).setValue(chassisId));
        vp.setPortId(new LLDPTLV().setType((byte) 2).setLength((short) portId.length).setValue(portId));
        vp.setTtl(new LLDPTLV().setType((byte) 3).setLength((short) ttlValue.length).setValue(ttlValue));
        vp.getOptionalTLVList().add(dpidTLV);
        // Add the controller identifier to the TLV value.
        // vp.getOptionalTLVList().add(controllerTLV);
        // Add T0 based on format from Floodlight LLDP
        long time = System.currentTimeMillis();
        long swLatency = srcSw.getLatency().getValue();
        byte[] timestampTLVValue = ByteBuffer.allocate(Long.SIZE / 8 + 4).put((byte) 0x00).put((byte) 0x26).put((byte) 0xe1).put(// 0x01 is what we'll use to differentiate DPID (0x00) from time (0x01)
        (byte) 0x01).putLong(time + swLatency).array();
        LLDPTLV timestampTLV = new LLDPTLV().setType((byte) 127).setLength((short) timestampTLVValue.length).setValue(timestampTLVValue);
        vp.getOptionalTLVList().add(timestampTLV);
        // Type
        byte[] typeTLVValue = ByteBuffer.allocate(Integer.SIZE / 8 + 4).put((byte) 0x00).put((byte) 0x26).put((byte) 0xe1).put((byte) 0x02).putInt(PathType.ISL.ordinal()).array();
        LLDPTLV typeTLV = new LLDPTLV().setType((byte) 127).setLength((short) typeTLVValue.length).setValue(typeTLVValue);
        vp.getOptionalTLVList().add(typeTLV);
        if (sign) {
            String token = JWT.create().withClaim("dpid", dpid.getLong()).withClaim("ts", time + swLatency).sign(algorithm);
            byte[] tokenBytes = token.getBytes(Charset.forName("UTF-8"));
            byte[] tokenTLVValue = ByteBuffer.allocate(4 + tokenBytes.length).put((byte) 0x00).put((byte) 0x26).put((byte) 0xe1).put((byte) 0x03).put(tokenBytes).array();
            LLDPTLV tokenTLV = new LLDPTLV().setType((byte) 127).setLength((short) tokenTLVValue.length).setValue(tokenTLVValue);
            vp.getOptionalTLVList().add(tokenTLV);
        }
        MacAddress dstMac = MacAddress.of(VERIFICATION_BCAST_PACKET_DST);
        if (dstSw != null) {
            OFPortDesc sw2OfPortDesc = dstSw.getPort(port);
            dstMac = sw2OfPortDesc.getHwAddr();
        }
        Ethernet l2 = new Ethernet().setSourceMACAddress(MacAddress.of(srcMac)).setDestinationMACAddress(dstMac).setEtherType(EthType.IPv4);
        IPv4Address dstIp = IPv4Address.of(VERIFICATION_PACKET_IP_DST);
        if (dstSw != null) {
            dstIp = IPv4Address.of(((InetSocketAddress) dstSw.getInetAddress()).getAddress().getAddress());
        }
        IPv4 l3 = new IPv4().setSourceAddress(IPv4Address.of(((InetSocketAddress) srcSw.getInetAddress()).getAddress().getAddress())).setDestinationAddress(dstIp).setTtl((byte) 64).setProtocol(IpProtocol.UDP);
        UDP l4 = new UDP();
        l4.setSourcePort(TransportPort.of(VERIFICATION_PACKET_UDP_PORT));
        l4.setDestinationPort(TransportPort.of(VERIFICATION_PACKET_UDP_PORT));
        l2.setPayload(l3);
        l3.setPayload(l4);
        l4.setPayload(vp);
        byte[] data = l2.serialize();
        OFPacketOut.Builder pob = srcSw.getOFFactory().buildPacketOut().setBufferId(OFBufferId.NO_BUFFER).setActions(getDiscoveryActions(srcSw, port)).setData(data);
        OFMessageUtils.setInPort(pob, OFPort.CONTROLLER);
        return pob.build();
    } catch (Exception exception) {
        logger.error("error generating verification packet: {}", exception);
    }
    return null;
}
Also used : UDP(net.floodlightcontroller.packet.UDP) InetSocketAddress(java.net.InetSocketAddress) IPv4(net.floodlightcontroller.packet.IPv4) DatapathId(org.projectfloodlight.openflow.types.DatapathId) MacAddress(org.projectfloodlight.openflow.types.MacAddress) ByteBuffer(java.nio.ByteBuffer) IPv4Address(org.projectfloodlight.openflow.types.IPv4Address) 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) OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) OFPortDescPropEthernet(org.projectfloodlight.openflow.protocol.OFPortDescPropEthernet) Ethernet(net.floodlightcontroller.packet.Ethernet) LLDPTLV(net.floodlightcontroller.packet.LLDPTLV)

Example 3 with OFPortDesc

use of org.projectfloodlight.openflow.protocol.OFPortDesc in project open-kilda by telstra.

the class RecordHandler method doPortsCommandDataRequest.

private void doPortsCommandDataRequest(Set<SwitchId> scope, PortsCommandData payload, String correlationId) {
    ISwitchManager switchManager = context.getModuleContext().getServiceImpl(ISwitchManager.class);
    try {
        logger.info("Getting ports data. Requester: {}", payload.getRequester());
        Map<DatapathId, IOFSwitch> allSwitchMap = context.getSwitchManager().getAllSwitchMap(true);
        for (Map.Entry<DatapathId, IOFSwitch> entry : allSwitchMap.entrySet()) {
            SwitchId switchId = new SwitchId(entry.getKey().toString());
            if (!scope.contains(switchId)) {
                continue;
            }
            try {
                IOFSwitch sw = entry.getValue();
                Set<PortStatusData> statuses = new HashSet<>();
                for (OFPortDesc portDesc : switchManager.getPhysicalPorts(sw.getId())) {
                    statuses.add(new PortStatusData(portDesc.getPortNo().getPortNumber(), portDesc.isEnabled() ? PortStatus.UP : PortStatus.DOWN));
                }
                SwitchPortStatusData response = SwitchPortStatusData.builder().switchId(switchId).ports(statuses).requester(payload.getRequester()).build();
                InfoMessage infoMessage = new InfoMessage(response, System.currentTimeMillis(), correlationId);
                getKafkaProducer().sendMessageAndTrack(context.getKafkaStatsTopic(), infoMessage);
            } catch (Exception e) {
                logger.error("Could not get port stats data for switch '{}' with error '{}'", switchId, e.getMessage(), e);
            }
        }
    } catch (Exception e) {
        logger.error("Could not get port data for stats '{}'", e.getMessage(), e);
    }
}
Also used : IOFSwitch(net.floodlightcontroller.core.IOFSwitch) ISwitchManager(org.openkilda.floodlight.switchmanager.ISwitchManager) SwitchPortStatusData(org.openkilda.messaging.info.stats.SwitchPortStatusData) DatapathId(org.projectfloodlight.openflow.types.DatapathId) SwitchId(org.openkilda.model.SwitchId) InvalidMeterIdException(org.openkilda.floodlight.error.InvalidMeterIdException) IOException(java.io.IOException) SwitchOperationException(org.openkilda.floodlight.error.SwitchOperationException) SwitchNotFoundException(org.openkilda.floodlight.error.SwitchNotFoundException) OfInstallException(org.openkilda.floodlight.error.OfInstallException) FlowCommandException(org.openkilda.floodlight.error.FlowCommandException) UnsupportedSwitchOperationException(org.openkilda.floodlight.error.UnsupportedSwitchOperationException) JsonMappingException(com.fasterxml.jackson.databind.JsonMappingException) PortStatusData(org.openkilda.messaging.info.stats.PortStatusData) SwitchPortStatusData(org.openkilda.messaging.info.stats.SwitchPortStatusData) OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) InfoMessage(org.openkilda.messaging.info.InfoMessage) Map(java.util.Map) HashSet(java.util.HashSet)

Example 4 with OFPortDesc

use of org.projectfloodlight.openflow.protocol.OFPortDesc in project open-kilda by telstra.

the class PathVerificationService method getSwitchPortSpeed.

private long getSwitchPortSpeed(IOFSwitch sw, OFPort inPort) {
    OFPortDesc port = sw.getPort(inPort);
    long speed = -1;
    if (port.getVersion().compareTo(OFVersion.OF_13) > 0) {
        for (OFPortDescProp prop : port.getProperties()) {
            if (prop.getType() == 0) {
                speed = ((OFPortDescPropEthernet) prop).getCurrSpeed();
                break;
            }
        }
    }
    if (speed < 0) {
        speed = port.getCurrSpeed();
    }
    return speed;
}
Also used : OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) OFPortDescProp(org.projectfloodlight.openflow.protocol.OFPortDescProp)

Example 5 with OFPortDesc

use of org.projectfloodlight.openflow.protocol.OFPortDesc in project open-kilda by telstra.

the class PathVerificationCommonTests method setUp.

@Before
public void setUp() throws Exception {
    super.setUp();
    FloodlightModuleContext fmc = new FloodlightModuleContext();
    fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider);
    fmc.addService(FeatureDetectorService.class, featureDetectorService);
    fmc.addService(IOFSwitchService.class, getMockSwitchService());
    pvs = new PathVerificationService();
    pvs.initAlgorithm("secret");
    fmc.addConfigParam(pvs, "isl_bandwidth_quotient", "0.0");
    fmc.addConfigParam(pvs, "hmac256-secret", "secret");
    fmc.addConfigParam(pvs, "bootstrap-servers", "");
    pvs.init(fmc);
    InetSocketAddress srcIpTarget = new InetSocketAddress("192.168.10.1", 200);
    long switchId = 0x112233445566L;
    OFPortDesc portDescription = EasyMock.createMock(OFPortDesc.class);
    OFDescStatsReply swDescription = factory.buildDescStatsReply().build();
    sw = buildMockIoFSwitch(switchId, portDescription, factory, swDescription, srcIpTarget);
    replay(sw);
}
Also used : OFDescStatsReply(org.projectfloodlight.openflow.protocol.OFDescStatsReply) OFPortDesc(org.projectfloodlight.openflow.protocol.OFPortDesc) InetSocketAddress(java.net.InetSocketAddress) FloodlightModuleContext(net.floodlightcontroller.core.module.FloodlightModuleContext) Before(org.junit.Before)

Aggregations

OFPortDesc (org.projectfloodlight.openflow.protocol.OFPortDesc)11 InetSocketAddress (java.net.InetSocketAddress)5 IOFSwitch (net.floodlightcontroller.core.IOFSwitch)4 DatapathId (org.projectfloodlight.openflow.types.DatapathId)4 FloodlightModuleContext (net.floodlightcontroller.core.module.FloodlightModuleContext)3 Before (org.junit.Before)3 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 ByteBuffer (java.nio.ByteBuffer)2 Map (java.util.Map)2 FloodlightModuleException (net.floodlightcontroller.core.module.FloodlightModuleException)2 Ethernet (net.floodlightcontroller.packet.Ethernet)2 LLDPTLV (net.floodlightcontroller.packet.LLDPTLV)2 Test (org.junit.Test)2 OFDescStatsReply (org.projectfloodlight.openflow.protocol.OFDescStatsReply)2 OFPortDescProp (org.projectfloodlight.openflow.protocol.OFPortDescProp)2 OFPortDescPropEthernet (org.projectfloodlight.openflow.protocol.OFPortDescPropEthernet)2 DecodedJWT (com.auth0.jwt.interfaces.DecodedJWT)1