mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-22 04:40:59 +02:00
Add path intent compiler that generates flow objective intents
Change-Id: I11bee398d927f0e3f32b7cf81d98cfe5816db477
This commit is contained in:
parent
00f481629a
commit
661c38cad5
@ -17,19 +17,25 @@
|
|||||||
package org.onosproject.net.intent;
|
package org.onosproject.net.intent;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import org.onosproject.core.ApplicationId;
|
import org.onosproject.core.ApplicationId;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.NetworkResource;
|
import org.onosproject.net.NetworkResource;
|
||||||
import org.onosproject.net.flowobjective.Objective;
|
import org.onosproject.net.flowobjective.Objective;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intent expressed as (and backed by) a collection of flow objectives through
|
* Intent expressed as (and backed by) a collection of flow objectives through
|
||||||
* which the intent is to be accomplished.
|
* which the intent is to be accomplished.
|
||||||
*/
|
*/
|
||||||
public class FlowObjectiveIntent extends Intent {
|
public final class FlowObjectiveIntent extends Intent {
|
||||||
|
|
||||||
private final Collection<Objective> objectives;
|
private final List<Objective> objectives;
|
||||||
|
private final List<DeviceId> devices;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for serialization.
|
* Constructor for serialization.
|
||||||
@ -37,6 +43,7 @@ public class FlowObjectiveIntent extends Intent {
|
|||||||
protected FlowObjectiveIntent() {
|
protected FlowObjectiveIntent() {
|
||||||
super();
|
super();
|
||||||
this.objectives = null;
|
this.objectives = null;
|
||||||
|
this.devices = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,13 +51,15 @@ public class FlowObjectiveIntent extends Intent {
|
|||||||
* resources.
|
* resources.
|
||||||
*
|
*
|
||||||
* @param appId application id
|
* @param appId application id
|
||||||
|
* @param devices list of target devices; in same order as the objectives
|
||||||
* @param objectives backing flow objectives
|
* @param objectives backing flow objectives
|
||||||
* @param resources backing network resources
|
* @param resources backing network resources
|
||||||
*/
|
*/
|
||||||
public FlowObjectiveIntent(ApplicationId appId,
|
public FlowObjectiveIntent(ApplicationId appId,
|
||||||
Collection<Objective> objectives,
|
List<DeviceId> devices,
|
||||||
|
List<Objective> objectives,
|
||||||
Collection<NetworkResource> resources) {
|
Collection<NetworkResource> resources) {
|
||||||
this(appId, null, objectives, resources);
|
this(appId, null, devices, objectives, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,14 +68,20 @@ public class FlowObjectiveIntent extends Intent {
|
|||||||
*
|
*
|
||||||
* @param appId application id
|
* @param appId application id
|
||||||
* @param key intent key
|
* @param key intent key
|
||||||
|
* @param devices list of target devices; in same order as the objectives
|
||||||
* @param objectives backing flow objectives
|
* @param objectives backing flow objectives
|
||||||
* @param resources backing network resources
|
* @param resources backing network resources
|
||||||
*/
|
*/
|
||||||
public FlowObjectiveIntent(ApplicationId appId, Key key,
|
public FlowObjectiveIntent(ApplicationId appId,
|
||||||
Collection<Objective> objectives,
|
Key key,
|
||||||
|
List<DeviceId> devices,
|
||||||
|
List<Objective> objectives,
|
||||||
Collection<NetworkResource> resources) {
|
Collection<NetworkResource> resources) {
|
||||||
super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
|
super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
|
||||||
this.objectives = objectives;
|
checkArgument(devices.size() == objectives.size(),
|
||||||
|
"Number of devices and objectives does not match");
|
||||||
|
this.objectives = ImmutableList.copyOf(objectives);
|
||||||
|
this.devices = ImmutableList.copyOf(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,10 +89,19 @@ public class FlowObjectiveIntent extends Intent {
|
|||||||
*
|
*
|
||||||
* @return flow objectives
|
* @return flow objectives
|
||||||
*/
|
*/
|
||||||
Collection<Objective> objectives() {
|
public List<Objective> objectives() {
|
||||||
return objectives;
|
return objectives;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of devices for the flow objectives.
|
||||||
|
*
|
||||||
|
* @return devices
|
||||||
|
*/
|
||||||
|
public List<DeviceId> devices() {
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInstallable() {
|
public boolean isInstallable() {
|
||||||
@ -91,7 +115,8 @@ public class FlowObjectiveIntent extends Intent {
|
|||||||
.add("key", key())
|
.add("key", key())
|
||||||
.add("appId", appId())
|
.add("appId", appId())
|
||||||
.add("resources", resources())
|
.add("resources", resources())
|
||||||
.add("objectives", objectives)
|
.add("device", devices())
|
||||||
|
.add("objectives", objectives())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,13 @@
|
|||||||
|
|
||||||
package org.onosproject.net.intent;
|
package org.onosproject.net.intent;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import java.util.Collection;
|
||||||
import com.google.common.testing.EqualsTester;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.onosproject.core.ApplicationId;
|
import org.onosproject.core.ApplicationId;
|
||||||
import org.onosproject.core.DefaultApplicationId;
|
import org.onosproject.core.DefaultApplicationId;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.NetworkResource;
|
import org.onosproject.net.NetworkResource;
|
||||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
@ -30,7 +32,9 @@ import org.onosproject.net.flowobjective.DefaultForwardingObjective;
|
|||||||
import org.onosproject.net.flowobjective.ForwardingObjective;
|
import org.onosproject.net.flowobjective.ForwardingObjective;
|
||||||
import org.onosproject.net.flowobjective.Objective;
|
import org.onosproject.net.flowobjective.Objective;
|
||||||
|
|
||||||
import java.util.Collection;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.testing.EqualsTester;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -52,8 +56,9 @@ public class FlowObjectiveIntentTest extends IntentTest {
|
|||||||
.withSelector(DefaultTrafficSelector.builder().matchEthType((short) 123).build())
|
.withSelector(DefaultTrafficSelector.builder().matchEthType((short) 123).build())
|
||||||
.withTreatment(DefaultTrafficTreatment.emptyTreatment())
|
.withTreatment(DefaultTrafficTreatment.emptyTreatment())
|
||||||
.withFlag(ForwardingObjective.Flag.VERSATILE).add();
|
.withFlag(ForwardingObjective.Flag.VERSATILE).add();
|
||||||
private static final Collection<Objective> OBJECTIVES = ImmutableSet.of(FO1, FO2);
|
private static final List<Objective> OBJECTIVES = ImmutableList.of(FO1, FO2);
|
||||||
private static final Collection<NetworkResource> RESOURCES = ImmutableSet.of();
|
private static final Collection<NetworkResource> RESOURCES = ImmutableSet.of();
|
||||||
|
private static final List<DeviceId> DEVICE = ImmutableList.of(DeviceId.NONE, DeviceId.NONE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests basics of construction and getters.
|
* Tests basics of construction and getters.
|
||||||
@ -61,7 +66,7 @@ public class FlowObjectiveIntentTest extends IntentTest {
|
|||||||
@Test
|
@Test
|
||||||
public void basics() {
|
public void basics() {
|
||||||
FlowObjectiveIntent intent =
|
FlowObjectiveIntent intent =
|
||||||
new FlowObjectiveIntent(APP_ID, KEY, OBJECTIVES, RESOURCES);
|
new FlowObjectiveIntent(APP_ID, KEY, DEVICE, OBJECTIVES, RESOURCES);
|
||||||
assertEquals("incorrect app id", APP_ID, intent.appId());
|
assertEquals("incorrect app id", APP_ID, intent.appId());
|
||||||
assertEquals("incorrect key", KEY, intent.key());
|
assertEquals("incorrect key", KEY, intent.key());
|
||||||
assertEquals("incorrect objectives", OBJECTIVES, intent.objectives());
|
assertEquals("incorrect objectives", OBJECTIVES, intent.objectives());
|
||||||
@ -89,11 +94,11 @@ public class FlowObjectiveIntentTest extends IntentTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Intent createOne() {
|
protected Intent createOne() {
|
||||||
return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES);
|
return new FlowObjectiveIntent(APP_ID, DEVICE, OBJECTIVES, RESOURCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Intent createAnother() {
|
protected Intent createAnother() {
|
||||||
return new FlowObjectiveIntent(APP_ID, OBJECTIVES, RESOURCES);
|
return new FlowObjectiveIntent(APP_ID, DEVICE, OBJECTIVES, RESOURCES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Open Networking Laboratory
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.onosproject.net.intent.impl.compiler;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.onlab.packet.VlanId;
|
||||||
|
import org.onosproject.net.ConnectPoint;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.Link;
|
||||||
|
import org.onosproject.net.LinkKey;
|
||||||
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
|
import org.onosproject.net.flow.TrafficSelector;
|
||||||
|
import org.onosproject.net.flow.TrafficTreatment;
|
||||||
|
import org.onosproject.net.flow.criteria.Criterion;
|
||||||
|
import org.onosproject.net.flow.criteria.VlanIdCriterion;
|
||||||
|
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
|
||||||
|
import org.onosproject.net.intent.PathIntent;
|
||||||
|
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
|
||||||
|
import org.onosproject.net.intent.impl.IntentCompilationException;
|
||||||
|
import org.onosproject.net.newresource.Resource;
|
||||||
|
import org.onosproject.net.newresource.ResourceService;
|
||||||
|
import org.onosproject.net.newresource.Resources;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import static org.onosproject.net.LinkKey.linkKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared APIs and implementations for path compilers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PathCompiler<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines methods used to create objects representing flows.
|
||||||
|
*/
|
||||||
|
public interface PathCompilerCreateFlow<T> {
|
||||||
|
|
||||||
|
void createFlow(TrafficSelector originalSelector,
|
||||||
|
TrafficTreatment originalTreatment,
|
||||||
|
ConnectPoint ingress, ConnectPoint egress,
|
||||||
|
int priority,
|
||||||
|
boolean applyTreatment,
|
||||||
|
List<T> flows,
|
||||||
|
List<DeviceId> devices);
|
||||||
|
|
||||||
|
Logger log();
|
||||||
|
|
||||||
|
ResourceService resourceService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLast(List<Link> links, int i) {
|
||||||
|
return i == links.size() - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<LinkKey, VlanId> assignVlanId(PathCompilerCreateFlow creator, PathIntent intent) {
|
||||||
|
Set<LinkKey> linkRequest =
|
||||||
|
Sets.newHashSetWithExpectedSize(intent.path()
|
||||||
|
.links().size() - 2);
|
||||||
|
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
|
||||||
|
LinkKey link = linkKey(intent.path().links().get(i));
|
||||||
|
linkRequest.add(link);
|
||||||
|
// add the inverse link. I want that the VLANID is reserved both for
|
||||||
|
// the direct and inverse link
|
||||||
|
linkRequest.add(linkKey(link.dst(), link.src()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<LinkKey, VlanId> vlanIds = findVlanIds(creator, linkRequest);
|
||||||
|
if (vlanIds.isEmpty()) {
|
||||||
|
creator.log().warn("No VLAN IDs available");
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
//same VLANID is used for both directions
|
||||||
|
Set<Resource> resources = vlanIds.entrySet().stream()
|
||||||
|
.flatMap(x -> Stream.of(
|
||||||
|
Resources.discrete(x.getKey().src().deviceId(), x.getKey().src().port(), x.getValue())
|
||||||
|
.resource(),
|
||||||
|
Resources.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port(), x.getValue())
|
||||||
|
.resource()
|
||||||
|
))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
List<org.onosproject.net.newresource.ResourceAllocation> allocations =
|
||||||
|
creator.resourceService().allocate(intent.id(), ImmutableList.copyOf(resources));
|
||||||
|
if (allocations.isEmpty()) {
|
||||||
|
Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return vlanIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<LinkKey, VlanId> findVlanIds(PathCompilerCreateFlow creator, Set<LinkKey> links) {
|
||||||
|
Map<LinkKey, VlanId> vlanIds = new HashMap<>();
|
||||||
|
for (LinkKey link : links) {
|
||||||
|
Set<VlanId> forward = findVlanId(creator, link.src());
|
||||||
|
Set<VlanId> backward = findVlanId(creator, link.dst());
|
||||||
|
Set<VlanId> common = Sets.intersection(forward, backward);
|
||||||
|
if (common.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vlanIds.put(link, common.iterator().next());
|
||||||
|
}
|
||||||
|
return vlanIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<VlanId> findVlanId(PathCompilerCreateFlow creator, ConnectPoint cp) {
|
||||||
|
return creator.resourceService().getAvailableResourceValues(
|
||||||
|
Resources.discrete(cp.deviceId(), cp.port()).id(),
|
||||||
|
VlanId.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void manageVlanEncap(PathCompilerCreateFlow<T> creator, List<T> flows,
|
||||||
|
List<DeviceId> devices,
|
||||||
|
PathIntent intent) {
|
||||||
|
Map<LinkKey, VlanId> vlanIds = assignVlanId(creator, intent);
|
||||||
|
|
||||||
|
Iterator<Link> links = intent.path().links().iterator();
|
||||||
|
Link srcLink = links.next();
|
||||||
|
|
||||||
|
Link link = links.next();
|
||||||
|
|
||||||
|
// Ingress traffic
|
||||||
|
VlanId vlanId = vlanIds.get(linkKey(link));
|
||||||
|
if (vlanId == null) {
|
||||||
|
throw new IntentCompilationException("No available VLAN ID for " + link);
|
||||||
|
}
|
||||||
|
VlanId prevVlanId = vlanId;
|
||||||
|
|
||||||
|
Optional<VlanIdCriterion> vlanCriterion = intent.selector().criteria()
|
||||||
|
.stream().filter(criterion -> criterion.type() == Criterion.Type.VLAN_VID)
|
||||||
|
.map(criterion -> (VlanIdCriterion) criterion)
|
||||||
|
.findAny();
|
||||||
|
|
||||||
|
//Push VLAN if selector does not include VLAN
|
||||||
|
TrafficTreatment.Builder treatBuilder = DefaultTrafficTreatment.builder();
|
||||||
|
if (!vlanCriterion.isPresent()) {
|
||||||
|
treatBuilder.pushVlan();
|
||||||
|
}
|
||||||
|
//Tag the traffic with the new encapsulation VLAN
|
||||||
|
treatBuilder.setVlanId(vlanId);
|
||||||
|
creator.createFlow(intent.selector(), treatBuilder.build(),
|
||||||
|
srcLink.dst(), link.src(), intent.priority(), true,
|
||||||
|
flows, devices);
|
||||||
|
|
||||||
|
ConnectPoint prev = link.dst();
|
||||||
|
|
||||||
|
while (links.hasNext()) {
|
||||||
|
|
||||||
|
link = links.next();
|
||||||
|
|
||||||
|
if (links.hasNext()) {
|
||||||
|
// Transit traffic
|
||||||
|
VlanId egressVlanId = vlanIds.get(linkKey(link));
|
||||||
|
if (egressVlanId == null) {
|
||||||
|
throw new IntentCompilationException("No available VLAN ID for " + link);
|
||||||
|
}
|
||||||
|
prevVlanId = egressVlanId;
|
||||||
|
|
||||||
|
TrafficSelector transitSelector = DefaultTrafficSelector.builder()
|
||||||
|
.matchInPort(prev.port())
|
||||||
|
.matchVlanId(prevVlanId).build();
|
||||||
|
|
||||||
|
TrafficTreatment.Builder transitTreat = DefaultTrafficTreatment.builder();
|
||||||
|
|
||||||
|
// Set the new vlanId only if the previous one is different
|
||||||
|
if (!prevVlanId.equals(egressVlanId)) {
|
||||||
|
transitTreat.setVlanId(egressVlanId);
|
||||||
|
}
|
||||||
|
creator.createFlow(transitSelector,
|
||||||
|
transitTreat.build(), prev, link.src(),
|
||||||
|
intent.priority(), true, flows, devices);
|
||||||
|
prev = link.dst();
|
||||||
|
} else {
|
||||||
|
// Egress traffic
|
||||||
|
TrafficSelector egressSelector = DefaultTrafficSelector.builder()
|
||||||
|
.matchInPort(prev.port())
|
||||||
|
.matchVlanId(prevVlanId).build();
|
||||||
|
TrafficTreatment.Builder egressTreat = DefaultTrafficTreatment.builder(intent.treatment());
|
||||||
|
|
||||||
|
Optional<L2ModificationInstruction.ModVlanIdInstruction> modVlanIdInstruction = intent.treatment()
|
||||||
|
.allInstructions().stream().filter(
|
||||||
|
instruction -> instruction instanceof L2ModificationInstruction.ModVlanIdInstruction)
|
||||||
|
.map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x).findAny();
|
||||||
|
|
||||||
|
Optional<L2ModificationInstruction.PopVlanInstruction> popVlanInstruction = intent.treatment()
|
||||||
|
.allInstructions().stream().filter(
|
||||||
|
instruction -> instruction instanceof L2ModificationInstruction.PopVlanInstruction)
|
||||||
|
.map(x -> (L2ModificationInstruction.PopVlanInstruction) x).findAny();
|
||||||
|
|
||||||
|
if (!modVlanIdInstruction.isPresent() && !popVlanInstruction.isPresent()) {
|
||||||
|
if (vlanCriterion.isPresent()) {
|
||||||
|
egressTreat.setVlanId(vlanCriterion.get().vlanId());
|
||||||
|
} else {
|
||||||
|
egressTreat.popVlan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
creator.createFlow(egressSelector,
|
||||||
|
egressTreat.build(), prev, link.src(),
|
||||||
|
intent.priority(), true, flows, devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an intent down to flows.
|
||||||
|
*
|
||||||
|
* @param creator how to create the flows
|
||||||
|
* @param intent intent to process
|
||||||
|
* @param flows list of generated flows
|
||||||
|
* @param devices list of devices that correspond to the flows
|
||||||
|
*/
|
||||||
|
public void compile(PathCompilerCreateFlow<T> creator,
|
||||||
|
PathIntent intent,
|
||||||
|
List<T> flows,
|
||||||
|
List<DeviceId> devices) {
|
||||||
|
// Note: right now recompile is not considered
|
||||||
|
// TODO: implement recompile behavior
|
||||||
|
|
||||||
|
List<Link> links = intent.path().links();
|
||||||
|
|
||||||
|
Optional<EncapsulationConstraint> encapConstraint = intent.constraints().stream()
|
||||||
|
.filter(constraint -> constraint instanceof EncapsulationConstraint)
|
||||||
|
.map(x -> (EncapsulationConstraint) x).findAny();
|
||||||
|
//if no encapsulation or is involved only a single switch use the default behaviour
|
||||||
|
if (!encapConstraint.isPresent() || links.size() == 1) {
|
||||||
|
for (int i = 0; i < links.size() - 1; i++) {
|
||||||
|
ConnectPoint ingress = links.get(i).dst();
|
||||||
|
ConnectPoint egress = links.get(i + 1).src();
|
||||||
|
creator.createFlow(intent.selector(), intent.treatment(),
|
||||||
|
ingress, egress, intent.priority(),
|
||||||
|
isLast(links, i), flows, devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encapConstraint.map(EncapsulationConstraint::encapType)
|
||||||
|
.map(type -> {
|
||||||
|
switch (type) {
|
||||||
|
case VLAN:
|
||||||
|
manageVlanEncap(creator, flows, devices, intent);
|
||||||
|
// TODO: implement MPLS case here
|
||||||
|
default:
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,57 +15,43 @@
|
|||||||
*/
|
*/
|
||||||
package org.onosproject.net.intent.impl.compiler;
|
package org.onosproject.net.intent.impl.compiler;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import java.util.LinkedList;
|
||||||
import com.google.common.collect.Sets;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.felix.scr.annotations.Activate;
|
import org.apache.felix.scr.annotations.Activate;
|
||||||
import org.apache.felix.scr.annotations.Component;
|
import org.apache.felix.scr.annotations.Component;
|
||||||
import org.apache.felix.scr.annotations.Deactivate;
|
import org.apache.felix.scr.annotations.Deactivate;
|
||||||
import org.apache.felix.scr.annotations.Reference;
|
import org.apache.felix.scr.annotations.Reference;
|
||||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||||
import org.onlab.packet.VlanId;
|
|
||||||
import org.onosproject.core.ApplicationId;
|
import org.onosproject.core.ApplicationId;
|
||||||
import org.onosproject.core.CoreService;
|
import org.onosproject.core.CoreService;
|
||||||
import org.onosproject.net.ConnectPoint;
|
import org.onosproject.net.ConnectPoint;
|
||||||
import org.onosproject.net.Link;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.LinkKey;
|
|
||||||
import org.onosproject.net.flow.DefaultFlowRule;
|
import org.onosproject.net.flow.DefaultFlowRule;
|
||||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
import org.onosproject.net.flow.FlowRule;
|
import org.onosproject.net.flow.FlowRule;
|
||||||
import org.onosproject.net.flow.TrafficSelector;
|
import org.onosproject.net.flow.TrafficSelector;
|
||||||
import org.onosproject.net.flow.TrafficTreatment;
|
import org.onosproject.net.flow.TrafficTreatment;
|
||||||
import org.onosproject.net.flow.criteria.Criterion;
|
|
||||||
import org.onosproject.net.flow.criteria.VlanIdCriterion;
|
|
||||||
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
|
|
||||||
import org.onosproject.net.intent.FlowRuleIntent;
|
import org.onosproject.net.intent.FlowRuleIntent;
|
||||||
import org.onosproject.net.intent.Intent;
|
import org.onosproject.net.intent.Intent;
|
||||||
import org.onosproject.net.intent.IntentCompiler;
|
import org.onosproject.net.intent.IntentCompiler;
|
||||||
import org.onosproject.net.intent.IntentExtensionService;
|
import org.onosproject.net.intent.IntentExtensionService;
|
||||||
import org.onosproject.net.intent.PathIntent;
|
import org.onosproject.net.intent.PathIntent;
|
||||||
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
|
|
||||||
import org.onosproject.net.intent.impl.IntentCompilationException;
|
|
||||||
import org.onosproject.net.newresource.Resource;
|
|
||||||
import org.onosproject.net.newresource.ResourceService;
|
import org.onosproject.net.newresource.ResourceService;
|
||||||
import org.onosproject.net.newresource.Resources;
|
|
||||||
import org.onosproject.net.resource.link.LinkResourceAllocations;
|
import org.onosproject.net.resource.link.LinkResourceAllocations;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.Collections;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.onosproject.net.LinkKey.linkKey;
|
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
public class PathIntentCompiler implements IntentCompiler<PathIntent> {
|
public class PathIntentCompiler
|
||||||
|
extends PathCompiler<FlowRule>
|
||||||
|
implements IntentCompiler<PathIntent>,
|
||||||
|
PathCompiler.PathCompilerCreateFlow<FlowRule> {
|
||||||
|
|
||||||
private final Logger log = getLogger(getClass());
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
@ -94,47 +80,30 @@ public class PathIntentCompiler implements IntentCompiler<PathIntent> {
|
|||||||
@Override
|
@Override
|
||||||
public List<Intent> compile(PathIntent intent, List<Intent> installable,
|
public List<Intent> compile(PathIntent intent, List<Intent> installable,
|
||||||
Set<LinkResourceAllocations> resources) {
|
Set<LinkResourceAllocations> resources) {
|
||||||
// Note: right now recompile is not considered
|
|
||||||
// TODO: implement recompile behavior
|
|
||||||
|
|
||||||
List<Link> links = intent.path().links();
|
List<FlowRule> rules = new LinkedList<>();
|
||||||
|
List<DeviceId> devices = new LinkedList<>();
|
||||||
Optional<EncapsulationConstraint> encapConstraint = intent.constraints().stream()
|
compile(this, intent, rules, devices);
|
||||||
.filter(constraint -> constraint instanceof EncapsulationConstraint)
|
|
||||||
.map(x -> (EncapsulationConstraint) x).findAny();
|
|
||||||
//if no encapsulation or is involved only a single switch use the default behaviour
|
|
||||||
if (!encapConstraint.isPresent() || links.size() == 1) {
|
|
||||||
List<FlowRule> rules = new LinkedList<>();
|
|
||||||
for (int i = 0; i < links.size() - 1; i++) {
|
|
||||||
ConnectPoint ingress = links.get(i).dst();
|
|
||||||
ConnectPoint egress = links.get(i + 1).src();
|
|
||||||
FlowRule rule = createFlowRule(intent.selector(), intent.treatment(),
|
|
||||||
ingress, egress, intent.priority(),
|
|
||||||
isLast(links, i));
|
|
||||||
rules.add(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ImmutableList.of(new FlowRuleIntent(appId, null, rules, intent.resources()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<FlowRule> rules = encapConstraint.map(EncapsulationConstraint::encapType)
|
|
||||||
.map(type -> {
|
|
||||||
switch (type) {
|
|
||||||
case VLAN:
|
|
||||||
return manageVlanEncap(intent);
|
|
||||||
// TODO: implement MPLS case here
|
|
||||||
default:
|
|
||||||
return Collections.<FlowRule>emptyList();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.orElse(Collections.emptyList());
|
|
||||||
|
|
||||||
return ImmutableList.of(new FlowRuleIntent(appId, null, rules, intent.resources()));
|
return ImmutableList.of(new FlowRuleIntent(appId, null, rules, intent.resources()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlowRule createFlowRule(TrafficSelector originalSelector, TrafficTreatment originalTreatment,
|
@Override
|
||||||
ConnectPoint ingress, ConnectPoint egress,
|
public Logger log() {
|
||||||
int priority, boolean applyTreatment) {
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceService resourceService() {
|
||||||
|
return resourceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createFlow(TrafficSelector originalSelector, TrafficTreatment originalTreatment,
|
||||||
|
ConnectPoint ingress, ConnectPoint egress,
|
||||||
|
int priority, boolean applyTreatment,
|
||||||
|
List<FlowRule> rules,
|
||||||
|
List<DeviceId> devices) {
|
||||||
TrafficSelector selector = DefaultTrafficSelector.builder(originalSelector)
|
TrafficSelector selector = DefaultTrafficSelector.builder(originalSelector)
|
||||||
.matchInPort(ingress.port())
|
.matchInPort(ingress.port())
|
||||||
.build();
|
.build();
|
||||||
@ -147,164 +116,13 @@ public class PathIntentCompiler implements IntentCompiler<PathIntent> {
|
|||||||
}
|
}
|
||||||
TrafficTreatment treatment = treatmentBuilder.setOutput(egress.port()).build();
|
TrafficTreatment treatment = treatmentBuilder.setOutput(egress.port()).build();
|
||||||
|
|
||||||
return DefaultFlowRule.builder()
|
rules.add(DefaultFlowRule.builder()
|
||||||
.forDevice(ingress.deviceId())
|
.forDevice(ingress.deviceId())
|
||||||
.withSelector(selector)
|
.withSelector(selector)
|
||||||
.withTreatment(treatment)
|
.withTreatment(treatment)
|
||||||
.withPriority(priority)
|
.withPriority(priority)
|
||||||
.fromApp(appId)
|
.fromApp(appId)
|
||||||
.makePermanent()
|
.makePermanent()
|
||||||
.build();
|
.build());
|
||||||
}
|
|
||||||
|
|
||||||
private List<FlowRule> manageVlanEncap(PathIntent intent) {
|
|
||||||
Map<LinkKey, VlanId> vlanIds = assignVlanId(intent);
|
|
||||||
|
|
||||||
Iterator<Link> links = intent.path().links().iterator();
|
|
||||||
Link srcLink = links.next();
|
|
||||||
|
|
||||||
Link link = links.next();
|
|
||||||
// List of flow rules to be installed
|
|
||||||
List<FlowRule> rules = new LinkedList<>();
|
|
||||||
|
|
||||||
// Ingress traffic
|
|
||||||
VlanId vlanId = vlanIds.get(linkKey(link));
|
|
||||||
if (vlanId == null) {
|
|
||||||
throw new IntentCompilationException("No available VLAN ID for " + link);
|
|
||||||
}
|
|
||||||
VlanId prevVlanId = vlanId;
|
|
||||||
|
|
||||||
Optional<VlanIdCriterion> vlanCriterion = intent.selector().criteria()
|
|
||||||
.stream().filter(criterion -> criterion.type() == Criterion.Type.VLAN_VID)
|
|
||||||
.map(criterion -> (VlanIdCriterion) criterion)
|
|
||||||
.findAny();
|
|
||||||
|
|
||||||
//Push VLAN if selector does not include VLAN
|
|
||||||
TrafficTreatment.Builder treatBuilder = DefaultTrafficTreatment.builder();
|
|
||||||
if (!vlanCriterion.isPresent()) {
|
|
||||||
treatBuilder.pushVlan();
|
|
||||||
}
|
|
||||||
//Tag the traffic with the new encapsulation VLAN
|
|
||||||
treatBuilder.setVlanId(vlanId);
|
|
||||||
rules.add(createFlowRule(intent.selector(), treatBuilder.build(),
|
|
||||||
srcLink.dst(), link.src(), intent.priority(), true));
|
|
||||||
|
|
||||||
ConnectPoint prev = link.dst();
|
|
||||||
|
|
||||||
while (links.hasNext()) {
|
|
||||||
|
|
||||||
link = links.next();
|
|
||||||
|
|
||||||
if (links.hasNext()) {
|
|
||||||
// Transit traffic
|
|
||||||
VlanId egressVlanId = vlanIds.get(linkKey(link));
|
|
||||||
if (egressVlanId == null) {
|
|
||||||
throw new IntentCompilationException("No available VLAN ID for " + link);
|
|
||||||
}
|
|
||||||
prevVlanId = egressVlanId;
|
|
||||||
|
|
||||||
TrafficSelector transitSelector = DefaultTrafficSelector.builder()
|
|
||||||
.matchInPort(prev.port())
|
|
||||||
.matchVlanId(prevVlanId).build();
|
|
||||||
|
|
||||||
TrafficTreatment.Builder transitTreat = DefaultTrafficTreatment.builder();
|
|
||||||
|
|
||||||
// Set the new vlanId only if the previous one is different
|
|
||||||
if (!prevVlanId.equals(egressVlanId)) {
|
|
||||||
transitTreat.setVlanId(egressVlanId);
|
|
||||||
}
|
|
||||||
rules.add(createFlowRule(transitSelector,
|
|
||||||
transitTreat.build(), prev, link.src(), intent.priority(), true));
|
|
||||||
prev = link.dst();
|
|
||||||
} else {
|
|
||||||
// Egress traffic
|
|
||||||
TrafficSelector egressSelector = DefaultTrafficSelector.builder()
|
|
||||||
.matchInPort(prev.port())
|
|
||||||
.matchVlanId(prevVlanId).build();
|
|
||||||
TrafficTreatment.Builder egressTreat = DefaultTrafficTreatment.builder(intent.treatment());
|
|
||||||
|
|
||||||
Optional<L2ModificationInstruction.ModVlanIdInstruction> modVlanIdInstruction = intent.treatment()
|
|
||||||
.allInstructions().stream().filter(
|
|
||||||
instruction -> instruction instanceof L2ModificationInstruction.ModVlanIdInstruction)
|
|
||||||
.map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x).findAny();
|
|
||||||
|
|
||||||
Optional<L2ModificationInstruction.PopVlanInstruction> popVlanInstruction = intent.treatment()
|
|
||||||
.allInstructions().stream().filter(
|
|
||||||
instruction -> instruction instanceof L2ModificationInstruction.PopVlanInstruction)
|
|
||||||
.map(x -> (L2ModificationInstruction.PopVlanInstruction) x).findAny();
|
|
||||||
|
|
||||||
if (!modVlanIdInstruction.isPresent() && !popVlanInstruction.isPresent()) {
|
|
||||||
if (vlanCriterion.isPresent()) {
|
|
||||||
egressTreat.setVlanId(vlanCriterion.get().vlanId());
|
|
||||||
} else {
|
|
||||||
egressTreat.popVlan();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rules.add(createFlowRule(egressSelector,
|
|
||||||
egressTreat.build(), prev, link.src(), intent.priority(), true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rules;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<LinkKey, VlanId> assignVlanId(PathIntent intent) {
|
|
||||||
Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
|
|
||||||
.links().size() - 2);
|
|
||||||
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
|
|
||||||
LinkKey link = linkKey(intent.path().links().get(i));
|
|
||||||
linkRequest.add(link);
|
|
||||||
// add the inverse link. I want that the VLANID is reserved both for
|
|
||||||
// the direct and inverse link
|
|
||||||
linkRequest.add(linkKey(link.dst(), link.src()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<LinkKey, VlanId> vlanIds = findVlanIds(linkRequest);
|
|
||||||
if (vlanIds.isEmpty()) {
|
|
||||||
log.warn("No VLAN IDs available");
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
//same VLANID is used for both directions
|
|
||||||
Set<Resource> resources = vlanIds.entrySet().stream()
|
|
||||||
.flatMap(x -> Stream.of(
|
|
||||||
Resources.discrete(x.getKey().src().deviceId(), x.getKey().src().port(), x.getValue())
|
|
||||||
.resource(),
|
|
||||||
Resources.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port(), x.getValue())
|
|
||||||
.resource()
|
|
||||||
))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
List<org.onosproject.net.newresource.ResourceAllocation> allocations =
|
|
||||||
resourceService.allocate(intent.id(), ImmutableList.copyOf(resources));
|
|
||||||
if (allocations.isEmpty()) {
|
|
||||||
Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
return vlanIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<LinkKey, VlanId> findVlanIds(Set<LinkKey> links) {
|
|
||||||
Map<LinkKey, VlanId> vlanIds = new HashMap<>();
|
|
||||||
for (LinkKey link : links) {
|
|
||||||
Set<VlanId> forward = findVlanId(link.src());
|
|
||||||
Set<VlanId> backward = findVlanId(link.dst());
|
|
||||||
Set<VlanId> common = Sets.intersection(forward, backward);
|
|
||||||
if (common.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vlanIds.put(link, common.iterator().next());
|
|
||||||
}
|
|
||||||
return vlanIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<VlanId> findVlanId(ConnectPoint cp) {
|
|
||||||
return resourceService.getAvailableResourceValues(
|
|
||||||
Resources.discrete(cp.deviceId(), cp.port()).id(),
|
|
||||||
VlanId.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLast(List<Link> links, int i) {
|
|
||||||
return i == links.size() - 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Open Networking Laboratory
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.onosproject.net.intent.impl.compiler;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.felix.scr.annotations.Activate;
|
||||||
|
import org.apache.felix.scr.annotations.Component;
|
||||||
|
import org.apache.felix.scr.annotations.Deactivate;
|
||||||
|
import org.apache.felix.scr.annotations.Reference;
|
||||||
|
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||||
|
import org.onosproject.core.ApplicationId;
|
||||||
|
import org.onosproject.core.CoreService;
|
||||||
|
import org.onosproject.net.ConnectPoint;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||||
|
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||||
|
import org.onosproject.net.flow.TrafficSelector;
|
||||||
|
import org.onosproject.net.flow.TrafficTreatment;
|
||||||
|
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
|
||||||
|
import org.onosproject.net.flowobjective.ForwardingObjective;
|
||||||
|
import org.onosproject.net.flowobjective.Objective;
|
||||||
|
import org.onosproject.net.intent.FlowObjectiveIntent;
|
||||||
|
import org.onosproject.net.intent.Intent;
|
||||||
|
import org.onosproject.net.intent.IntentCompiler;
|
||||||
|
import org.onosproject.net.intent.IntentExtensionService;
|
||||||
|
import org.onosproject.net.intent.PathIntent;
|
||||||
|
import org.onosproject.net.newresource.ResourceService;
|
||||||
|
import org.onosproject.net.resource.link.LinkResourceAllocations;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
|
@Component(immediate = true)
|
||||||
|
public class PathIntentFlowObjectiveCompiler
|
||||||
|
extends PathCompiler<Objective>
|
||||||
|
implements IntentCompiler<PathIntent>,
|
||||||
|
PathCompiler.PathCompilerCreateFlow<Objective> {
|
||||||
|
|
||||||
|
private final Logger log = getLogger(getClass());
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
|
protected CoreService coreService;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
|
protected IntentExtensionService intentManager;
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
|
protected ResourceService resourceService;
|
||||||
|
|
||||||
|
private ApplicationId appId;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public void activate() {
|
||||||
|
appId = coreService.registerApplication("org.onosproject.net.intent");
|
||||||
|
//intentManager.registerCompiler(PathIntent.class, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
public void deactivate() {
|
||||||
|
//intentManager.unregisterCompiler(PathIntent.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Intent> compile(PathIntent intent, List<Intent> installable,
|
||||||
|
Set<LinkResourceAllocations> resources) {
|
||||||
|
|
||||||
|
List<Objective> objectives = new LinkedList<>();
|
||||||
|
List<DeviceId> devices = new LinkedList<>();
|
||||||
|
compile(this, intent, objectives, devices);
|
||||||
|
|
||||||
|
return ImmutableList.of(new FlowObjectiveIntent(appId, devices, objectives, intent.resources()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Logger log() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceService resourceService() {
|
||||||
|
return resourceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createFlow(TrafficSelector originalSelector, TrafficTreatment originalTreatment,
|
||||||
|
ConnectPoint ingress, ConnectPoint egress,
|
||||||
|
int priority, boolean applyTreatment,
|
||||||
|
List<Objective> objectives,
|
||||||
|
List<DeviceId> devices) {
|
||||||
|
TrafficSelector selector = DefaultTrafficSelector.builder(originalSelector)
|
||||||
|
.matchInPort(ingress.port())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
TrafficTreatment.Builder treatmentBuilder;
|
||||||
|
if (applyTreatment) {
|
||||||
|
treatmentBuilder = DefaultTrafficTreatment.builder(originalTreatment);
|
||||||
|
} else {
|
||||||
|
treatmentBuilder = DefaultTrafficTreatment.builder();
|
||||||
|
}
|
||||||
|
TrafficTreatment treatment = treatmentBuilder.setOutput(egress.port()).build();
|
||||||
|
|
||||||
|
objectives.add(DefaultForwardingObjective.builder()
|
||||||
|
.withSelector(selector)
|
||||||
|
.withTreatment(treatment)
|
||||||
|
.withPriority(priority)
|
||||||
|
.fromApp(appId)
|
||||||
|
.makePermanent()
|
||||||
|
.withFlag(ForwardingObjective.Flag.SPECIFIC)
|
||||||
|
.add());
|
||||||
|
devices.add(ingress.deviceId());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user