use of org.onosproject.net.flow.instructions.Instructions.OutputInstruction in project onos by opennetworkinglab.
the class BasicInterpreterImpl method mapOutboundPacket.
@Override
public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet) throws PiInterpreterException {
TrafficTreatment treatment = packet.treatment();
// basic.p4 supports only OUTPUT instructions.
List<OutputInstruction> outInstructions = treatment.allInstructions().stream().filter(i -> i.type().equals(OUTPUT)).map(i -> (OutputInstruction) i).collect(toList());
if (treatment.allInstructions().size() != outInstructions.size()) {
// There are other instructions that are not of type OUTPUT.
throw new PiInterpreterException("Treatment not supported: " + treatment);
}
ImmutableList.Builder<PiPacketOperation> builder = ImmutableList.builder();
for (OutputInstruction outInst : outInstructions) {
if (outInst.port().isLogical() && !outInst.port().equals(FLOOD)) {
throw new PiInterpreterException(format("Output on logical port '%s' not supported", outInst.port()));
} else if (outInst.port().equals(FLOOD)) {
// Since basic.p4 does not support flooding, we create a packet
// operation for each switch port.
final DeviceService deviceService = handler().get(DeviceService.class);
for (Port port : deviceService.getPorts(packet.sendThrough())) {
builder.add(createPiPacketOperation(packet.data(), port.number().toLong()));
}
} else {
builder.add(createPiPacketOperation(packet.data(), outInst.port().toLong()));
}
}
return builder.build();
}
use of org.onosproject.net.flow.instructions.Instructions.OutputInstruction in project onos by opennetworkinglab.
the class FlowRuleJuniperImpl method manageRules.
private Collection<FlowRule> manageRules(Collection<FlowRule> rules, OperationType type) {
DeviceId deviceId = this.data().deviceId();
log.debug("{} flow entries to NETCONF device {}", type, deviceId);
NetconfSession session = lookupNetconfSession(deviceId);
Collection<FlowRule> managedRules = new HashSet<>();
for (FlowRule flowRule : rules) {
Optional<IPCriterion> ipCriterion = getIpCriterion(flowRule);
if (!ipCriterion.isPresent()) {
log.error("Currently not supported: IPv4 destination match must be used");
continue;
}
Optional<OutputInstruction> output = getOutput(flowRule);
if (!output.isPresent()) {
log.error("Currently not supported: the output action is needed");
continue;
}
getStaticRoute(deviceId, ipCriterion.get(), output.get(), flowRule.priority()).ifPresent(staticRoute -> {
// If the static route is not local, the driver tries to install
if (!staticRoute.isLocalRoute()) {
// FlowRule as installed.
if (editRoute(session, type, staticRoute)) {
managedRules.add(flowRule);
}
// If static route are local, they are not installed
// because are not required. Directly connected routes
// are automatically forwarded.
} else {
managedRules.add(flowRule);
}
});
}
return rules;
}
use of org.onosproject.net.flow.instructions.Instructions.OutputInstruction in project onos by opennetworkinglab.
the class FlowRuleJuniperImpl method getStaticRoute.
/**
* Helper method to convert FlowRule into an abstraction of static route
* {@link StaticRoute}.
*
* @param devId the device id
* @param criteria the IP destination criteria
* @param output the output instruction
* @return optional of Static Route
*/
private Optional<StaticRoute> getStaticRoute(DeviceId devId, IPCriterion criteria, OutputInstruction output, int priority) {
DeviceService deviceService = this.handler().get(DeviceService.class);
Collection<Port> ports = deviceService.getPorts(devId);
Optional<Port> port = ports.stream().filter(x -> x.number().equals(output.port())).findAny();
if (!port.isPresent()) {
log.error("The port {} does not exist in the device", output.port());
return Optional.empty();
}
// Find if the route refers to a local interface.
Optional<Port> local = deviceService.getPorts(devId).stream().filter(this::isIp).filter(p -> criteria.ip().getIp4Prefix().contains(Ip4Address.valueOf(p.annotations().value(JuniperUtils.AK_IP)))).findAny();
if (local.isPresent()) {
return Optional.of(new StaticRoute(criteria.ip().getIp4Prefix(), criteria.ip().getIp4Prefix().address(), true, priority));
}
Optional<Ip4Address> nextHop = findIpDst(devId, port.get());
if (nextHop.isPresent()) {
return Optional.of(new StaticRoute(criteria.ip().getIp4Prefix(), nextHop.get(), false, priority));
} else {
log.error("The destination interface has not an IP {}", port.get());
return Optional.empty();
}
}
use of org.onosproject.net.flow.instructions.Instructions.OutputInstruction in project onos by opennetworkinglab.
the class FlowRuleJuniperImpl method getFlowEntries.
@Override
public Collection<FlowEntry> getFlowEntries() {
DeviceId devId = checkNotNull(this.data().deviceId());
NetconfSession session = lookupNetconfSession(devId);
if (session == null) {
return Collections.emptyList();
}
// Installed static routes
String reply;
try {
reply = session.get(routingTableBuilder());
} catch (NetconfException e) {
throw new IllegalStateException(new NetconfException("Failed to retrieve configuration.", e));
}
Collection<StaticRoute> devicesStaticRoutes = JuniperUtils.parseRoutingTable(loadXmlString(reply));
// Expected FlowEntries installed
FlowRuleService flowRuleService = this.handler().get(FlowRuleService.class);
Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(devId);
Collection<FlowEntry> installedRules = new HashSet<>();
flowEntries.forEach(flowEntry -> {
Optional<IPCriterion> ipCriterion = getIpCriterion(flowEntry);
if (!ipCriterion.isPresent()) {
return;
}
Optional<OutputInstruction> output = getOutput(flowEntry);
if (!output.isPresent()) {
return;
}
// convert FlowRule into static route
getStaticRoute(devId, ipCriterion.get(), output.get(), flowEntry.priority()).ifPresent(staticRoute -> {
if (staticRoute.isLocalRoute()) {
// if the FlowRule is in PENDING_REMOVE or REMOVED, it is not reported.
if (flowEntry.state() == PENDING_REMOVE || flowEntry.state() == REMOVED) {
devicesStaticRoutes.remove(staticRoute);
} else {
// FlowRule is reported installed
installedRules.add(flowEntry);
devicesStaticRoutes.remove(staticRoute);
}
} else {
// if the route is found in the device, the FlowRule is reported installed.
if (devicesStaticRoutes.contains(staticRoute)) {
installedRules.add(flowEntry);
devicesStaticRoutes.remove(staticRoute);
}
}
});
});
if (!devicesStaticRoutes.isEmpty()) {
log.info("Found static routes on device {} not installed by ONOS: {}", devId, devicesStaticRoutes);
// FIXME: enable configuration to purge already installed flows.
// It cannot be allowed by default because it may remove needed management routes
// log.warn("Removing from device {} the FlowEntries not expected {}", deviceId, devicesStaticRoutes);
// devicesStaticRoutes.forEach(staticRoute -> editRoute(session, REMOVE, staticRoute));
}
return installedRules;
}
use of org.onosproject.net.flow.instructions.Instructions.OutputInstruction in project onos by opennetworkinglab.
the class PiReplicationGroupTranslatorImpl method translate.
/**
* Returns a PI PRE entry equivalent to the given group, for the given
* pipeconf and device.
* <p>
* The passed group is expected to have type {@link GroupDescription.Type#ALL}
* or {@link GroupDescription.Type#CLONE}.
*
* @param group group
* @param pipeconf pipeconf
* @param device device
* @return PI PRE entry
* @throws PiTranslationException if the group cannot be translated
*/
static PiPreEntry translate(Group group, PiPipeconf pipeconf, Device device) throws PiTranslationException {
checkNotNull(group);
final List<OutputInstruction> outInstructions = Lists.newArrayList();
int truncateMaxLen = PiCloneSessionEntry.DO_NOT_TRUNCATE;
for (GroupBucket bucket : group.buckets().buckets()) {
int numInstructionsInBucket = bucket.treatment().allInstructions().size();
List<OutputInstruction> outputs = getInstructions(bucket, Instruction.Type.OUTPUT, OutputInstruction.class);
List<TruncateInstruction> truncates = getInstructions(bucket, Instruction.Type.TRUNCATE, TruncateInstruction.class);
if (outputs.size() != 1) {
throw new PiTranslationException("support only groups with just one OUTPUT instruction per bucket");
}
outInstructions.add(outputs.get(0));
if (truncates.size() != 0) {
if (group.type() != GroupDescription.Type.CLONE) {
throw new PiTranslationException("only CLONE group support truncate instruction");
}
if (truncates.size() != 1) {
throw new PiTranslationException("support only groups with just one TRUNCATE instruction per bucket");
}
int truncateInstMaxLen = truncates.get(0).maxLen();
if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE && truncateMaxLen != truncateInstMaxLen) {
throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
}
truncateMaxLen = truncateInstMaxLen;
} else if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE) {
// No truncate instruction found in this bucket, but previous bucket contains one.
throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
}
if (numInstructionsInBucket != outputs.size() + truncates.size()) {
throw new PiTranslationException("bucket contains unsupported instruction(s)");
}
}
switch(group.type()) {
case ALL:
return PiMulticastGroupEntry.builder().withGroupId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).build();
case CLONE:
return PiCloneSessionEntry.builder().withSessionId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).withMaxPacketLengthBytes(truncateMaxLen).build();
default:
throw new PiTranslationException(format("group type %s not supported", group.type()));
}
}
Aggregations