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;
}
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());
}
}
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);
}
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();
}
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;
}
});
}
Aggregations