helenyrwu
Committed by Gerrit Code Review

Implement path protection for point to point intents

Change-Id: I3f3627e7c2a7e3ab017e46655692ab70fdeae413
...@@ -17,6 +17,7 @@ package org.onosproject.cli.net; ...@@ -17,6 +17,7 @@ package org.onosproject.cli.net;
17 17
18 import org.apache.karaf.shell.commands.Argument; 18 import org.apache.karaf.shell.commands.Argument;
19 import org.apache.karaf.shell.commands.Command; 19 import org.apache.karaf.shell.commands.Command;
20 +import org.apache.karaf.shell.commands.Option;
20 import org.onosproject.net.ConnectPoint; 21 import org.onosproject.net.ConnectPoint;
21 import org.onosproject.net.flow.TrafficSelector; 22 import org.onosproject.net.flow.TrafficSelector;
22 import org.onosproject.net.flow.TrafficTreatment; 23 import org.onosproject.net.flow.TrafficTreatment;
...@@ -24,6 +25,7 @@ import org.onosproject.net.intent.Constraint; ...@@ -24,6 +25,7 @@ import org.onosproject.net.intent.Constraint;
24 import org.onosproject.net.intent.Intent; 25 import org.onosproject.net.intent.Intent;
25 import org.onosproject.net.intent.IntentService; 26 import org.onosproject.net.intent.IntentService;
26 import org.onosproject.net.intent.PointToPointIntent; 27 import org.onosproject.net.intent.PointToPointIntent;
28 +import org.onosproject.net.intent.constraint.ProtectionConstraint;
27 29
28 import java.util.List; 30 import java.util.List;
29 31
...@@ -44,6 +46,11 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { ...@@ -44,6 +46,11 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand {
44 required = true, multiValued = false) 46 required = true, multiValued = false)
45 String egressDeviceString = null; 47 String egressDeviceString = null;
46 48
49 + @Option(name = "-p", aliases = "--protect",
50 + description = "Utilize path protection",
51 + required = false, multiValued = false)
52 + private boolean backup = false;
53 +
47 @Override 54 @Override
48 protected void execute() { 55 protected void execute() {
49 IntentService service = get(IntentService.class); 56 IntentService service = get(IntentService.class);
...@@ -56,6 +63,9 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { ...@@ -56,6 +63,9 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand {
56 TrafficTreatment treatment = buildTrafficTreatment(); 63 TrafficTreatment treatment = buildTrafficTreatment();
57 64
58 List<Constraint> constraints = buildConstraints(); 65 List<Constraint> constraints = buildConstraints();
66 + if (backup) {
67 + constraints.add(new ProtectionConstraint());
68 + }
59 69
60 Intent intent = PointToPointIntent.builder() 70 Intent intent = PointToPointIntent.builder()
61 .appId(appId()) 71 .appId(appId())
......
...@@ -35,6 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -35,6 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
35 public class FlowRuleIntent extends Intent { 35 public class FlowRuleIntent extends Intent {
36 36
37 private final Collection<FlowRule> flowRules; 37 private final Collection<FlowRule> flowRules;
38 + private PathIntent.ProtectionType type;
38 39
39 /** 40 /**
40 * Creates a flow rule intent with the specified flow rules and resources. 41 * Creates a flow rule intent with the specified flow rules and resources.
...@@ -48,7 +49,19 @@ public class FlowRuleIntent extends Intent { ...@@ -48,7 +49,19 @@ public class FlowRuleIntent extends Intent {
48 } 49 }
49 50
50 /** 51 /**
51 - * Creates an flow rule intent with the specified key, flow rules to be set, and 52 + * Creates a flow rule intent with the specified flow rules, resources, and type.
53 + *
54 + * @param appId application id
55 + * @param flowRules flow rules to be set
56 + * @param resources network resource to be set
57 + */
58 + public FlowRuleIntent(ApplicationId appId, List<FlowRule> flowRules, Collection<NetworkResource> resources,
59 + PathIntent.ProtectionType type) {
60 + this(appId, null, flowRules, resources, type);
61 + }
62 +
63 + /**
64 + * Creates a flow rule intent with the specified key, flow rules to be set, and
52 * required network resources. 65 * required network resources.
53 * 66 *
54 * @param appId application id 67 * @param appId application id
...@@ -58,8 +71,32 @@ public class FlowRuleIntent extends Intent { ...@@ -58,8 +71,32 @@ public class FlowRuleIntent extends Intent {
58 */ 71 */
59 public FlowRuleIntent(ApplicationId appId, Key key, Collection<FlowRule> flowRules, 72 public FlowRuleIntent(ApplicationId appId, Key key, Collection<FlowRule> flowRules,
60 Collection<NetworkResource> resources) { 73 Collection<NetworkResource> resources) {
74 + this(appId, key, flowRules, resources, PathIntent.ProtectionType.PRIMARY);
75 + }
76 +
77 + /**
78 + * Creates a flow rule intent with the specified key, flow rules to be set, and
79 + * required network resources.
80 + *
81 + * @param appId application id
82 + * @param key key
83 + * @param flowRules flow rules
84 + * @param resources network resources
85 + */
86 + public FlowRuleIntent(ApplicationId appId, Key key, Collection<FlowRule> flowRules,
87 + Collection<NetworkResource> resources, PathIntent.ProtectionType primary) {
61 super(appId, key, resources, DEFAULT_INTENT_PRIORITY); 88 super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
62 this.flowRules = ImmutableList.copyOf(checkNotNull(flowRules)); 89 this.flowRules = ImmutableList.copyOf(checkNotNull(flowRules));
90 + this.type = primary;
91 + }
92 +
93 + /**
94 + * Creates a flow rule intent with all the same characteristics as the given
95 + * one except for the flow rule type.
96 + */
97 + public FlowRuleIntent(FlowRuleIntent intent, PathIntent.ProtectionType type) {
98 + this(intent.appId(), intent.key(), intent.flowRules(),
99 + intent.resources(), type);
63 } 100 }
64 101
65 /** 102 /**
...@@ -68,6 +105,7 @@ public class FlowRuleIntent extends Intent { ...@@ -68,6 +105,7 @@ public class FlowRuleIntent extends Intent {
68 protected FlowRuleIntent() { 105 protected FlowRuleIntent() {
69 super(); 106 super();
70 this.flowRules = null; 107 this.flowRules = null;
108 + this.type = PathIntent.ProtectionType.PRIMARY;
71 } 109 }
72 110
73 /** 111 /**
...@@ -84,6 +122,10 @@ public class FlowRuleIntent extends Intent { ...@@ -84,6 +122,10 @@ public class FlowRuleIntent extends Intent {
84 return true; 122 return true;
85 } 123 }
86 124
125 + public PathIntent.ProtectionType type() {
126 + return type;
127 + }
128 +
87 @Override 129 @Override
88 public String toString() { 130 public String toString() {
89 return MoreObjects.toStringHelper(this) 131 return MoreObjects.toStringHelper(this)
......
...@@ -31,7 +31,7 @@ public interface IntentCompiler<T extends Intent> { ...@@ -31,7 +31,7 @@ public interface IntentCompiler<T extends Intent> {
31 * Compiles the specified intent into other intents. 31 * Compiles the specified intent into other intents.
32 * 32 *
33 * @param intent intent to be compiled 33 * @param intent intent to be compiled
34 - * @param installable previously compilation result; optional 34 + * @param installable previous compilation result; optional
35 * @return list of resulting intents 35 * @return list of resulting intents
36 * @throws IntentException if issues are encountered while compiling the intent 36 * @throws IntentException if issues are encountered while compiling the intent
37 */ 37 */
......
...@@ -36,10 +36,11 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -36,10 +36,11 @@ import static com.google.common.base.Preconditions.checkArgument;
36 public class PathIntent extends ConnectivityIntent { 36 public class PathIntent extends ConnectivityIntent {
37 37
38 private final Path path; 38 private final Path path;
39 + private ProtectionType type;
39 40
40 /** 41 /**
41 * Creates a new point-to-point intent with the supplied ingress/egress 42 * Creates a new point-to-point intent with the supplied ingress/egress
42 - * ports and using the specified explicit path. 43 + * ports and using the specified explicit path. Path is primary by default.
43 * 44 *
44 * @param appId application identifier 45 * @param appId application identifier
45 * @param key intent key 46 * @param key intent key
...@@ -57,10 +58,38 @@ public class PathIntent extends ConnectivityIntent { ...@@ -57,10 +58,38 @@ public class PathIntent extends ConnectivityIntent {
57 Path path, 58 Path path,
58 List<Constraint> constraints, 59 List<Constraint> constraints,
59 int priority) { 60 int priority) {
61 + this(appId, key, selector, treatment, path, constraints, priority,
62 + ProtectionType.PRIMARY);
63 + }
64 +
65 + /**
66 + * Creates a new point-to-point intent with the supplied ingress/egress
67 + * ports and using the specified explicit path, which can be classified
68 + * as PRIMARY or BACKUP.
69 + *
70 + * @param appId application identifier
71 + * @param key intent key
72 + * @param selector traffic selector
73 + * @param treatment treatment
74 + * @param path traversed links
75 + * @param constraints optional list of constraints
76 + * @param priority priority to use for the generated flows
77 + * @param type PRIMARY or BACKUP
78 + * @throws NullPointerException {@code path} is null
79 + */
80 + protected PathIntent(ApplicationId appId,
81 + Key key,
82 + TrafficSelector selector,
83 + TrafficTreatment treatment,
84 + Path path,
85 + List<Constraint> constraints,
86 + int priority,
87 + ProtectionType type) {
60 super(appId, key, resources(path.links()), selector, treatment, constraints, 88 super(appId, key, resources(path.links()), selector, treatment, constraints,
61 priority); 89 priority);
62 PathIntent.validate(path.links()); 90 PathIntent.validate(path.links());
63 this.path = path; 91 this.path = path;
92 + this.type = type;
64 } 93 }
65 94
66 /** 95 /**
...@@ -69,6 +98,7 @@ public class PathIntent extends ConnectivityIntent { ...@@ -69,6 +98,7 @@ public class PathIntent extends ConnectivityIntent {
69 protected PathIntent() { 98 protected PathIntent() {
70 super(); 99 super();
71 this.path = null; 100 this.path = null;
101 + this.type = ProtectionType.PRIMARY;
72 } 102 }
73 103
74 /** 104 /**
...@@ -85,6 +115,7 @@ public class PathIntent extends ConnectivityIntent { ...@@ -85,6 +115,7 @@ public class PathIntent extends ConnectivityIntent {
85 */ 115 */
86 public static class Builder extends ConnectivityIntent.Builder { 116 public static class Builder extends ConnectivityIntent.Builder {
87 Path path; 117 Path path;
118 + ProtectionType type;
88 119
89 protected Builder() { 120 protected Builder() {
90 // Hide default constructor 121 // Hide default constructor
...@@ -131,6 +162,11 @@ public class PathIntent extends ConnectivityIntent { ...@@ -131,6 +162,11 @@ public class PathIntent extends ConnectivityIntent {
131 return this; 162 return this;
132 } 163 }
133 164
165 + public Builder setType(ProtectionType type) {
166 + this.type = type;
167 + return this;
168 + }
169 +
134 /** 170 /**
135 * Builds a path intent from the accumulated parameters. 171 * Builds a path intent from the accumulated parameters.
136 * 172 *
...@@ -145,7 +181,8 @@ public class PathIntent extends ConnectivityIntent { ...@@ -145,7 +181,8 @@ public class PathIntent extends ConnectivityIntent {
145 treatment, 181 treatment,
146 path, 182 path,
147 constraints, 183 constraints,
148 - priority 184 + priority,
185 + type == null ? ProtectionType.PRIMARY : type
149 ); 186 );
150 } 187 }
151 } 188 }
...@@ -183,6 +220,10 @@ public class PathIntent extends ConnectivityIntent { ...@@ -183,6 +220,10 @@ public class PathIntent extends ConnectivityIntent {
183 return path; 220 return path;
184 } 221 }
185 222
223 + public ProtectionType type() {
224 + return type;
225 + }
226 +
186 @Override 227 @Override
187 public String toString() { 228 public String toString() {
188 return MoreObjects.toStringHelper(getClass()) 229 return MoreObjects.toStringHelper(getClass())
...@@ -195,7 +236,25 @@ public class PathIntent extends ConnectivityIntent { ...@@ -195,7 +236,25 @@ public class PathIntent extends ConnectivityIntent {
195 .add("treatment", treatment()) 236 .add("treatment", treatment())
196 .add("constraints", constraints()) 237 .add("constraints", constraints())
197 .add("path", path) 238 .add("path", path)
239 + .add("type", type)
198 .toString(); 240 .toString();
199 } 241 }
200 242
243 + // for path protection purposes
244 + public enum ProtectionType {
245 + /**
246 + * Intent within primary path.
247 + */
248 + PRIMARY,
249 + /**
250 + * Intent within backup path.
251 + */
252 + BACKUP,
253 + /**
254 + * Intent whose flow rule serves as the fast failover
255 + * between primary and backup paths.
256 + */
257 + FAILOVER
258 + }
259 +
201 } 260 }
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.intent.constraint;
18 +
19 +import com.google.common.annotations.Beta;
20 +import org.onosproject.net.Link;
21 +import org.onosproject.net.Path;
22 +import org.onosproject.net.intent.Constraint;
23 +import org.onosproject.net.intent.Intent;
24 +import org.onosproject.net.intent.PointToPointIntent;
25 +import org.onosproject.net.intent.ResourceContext;
26 +
27 +/**
28 + * Constraint that determines whether to employ path protection.
29 + */
30 +@Beta
31 +public class ProtectionConstraint implements Constraint {
32 + // doesn't use LinkResourceService
33 + @Override
34 + public double cost(Link link, ResourceContext context) {
35 + return 1;
36 + }
37 +
38 + // doesn't use LinkResourceService
39 + @Override
40 + public boolean validate(Path path, ResourceContext context) {
41 + return true;
42 + }
43 +
44 + /**
45 + * Determines whether to utilize path protection for the given intent.
46 + *
47 + * @param intent intent to be inspected
48 + * @return whether the intent has a ProtectionConstraint
49 + */
50 + public static boolean requireProtectedPath(Intent intent) {
51 + if (intent instanceof PointToPointIntent) {
52 + PointToPointIntent pointToPointIntent = (PointToPointIntent) intent;
53 + return pointToPointIntent.constraints().stream()
54 + .anyMatch(p -> p instanceof ProtectionConstraint);
55 + }
56 + return false;
57 + }
58 +}
...@@ -26,7 +26,7 @@ import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBa ...@@ -26,7 +26,7 @@ import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBa
26 public class PointToPointIntentTest extends ConnectivityIntentTest { 26 public class PointToPointIntentTest extends ConnectivityIntentTest {
27 27
28 /** 28 /**
29 - * Checks that the MultiPointToSinglePointIntent class is immutable. 29 + * Checks that the PointToPointIntent class is immutable.
30 */ 30 */
31 @Test 31 @Test
32 public void checkImmutability() { 32 public void checkImmutability() {
......
...@@ -28,8 +28,11 @@ import org.onosproject.cfg.ComponentConfigService; ...@@ -28,8 +28,11 @@ import org.onosproject.cfg.ComponentConfigService;
28 import org.onosproject.core.CoreService; 28 import org.onosproject.core.CoreService;
29 import org.onosproject.core.IdGenerator; 29 import org.onosproject.core.IdGenerator;
30 import org.onosproject.event.AbstractListenerManager; 30 import org.onosproject.event.AbstractListenerManager;
31 +import org.onosproject.net.DeviceId;
31 import org.onosproject.net.flow.FlowRuleService; 32 import org.onosproject.net.flow.FlowRuleService;
32 import org.onosproject.net.flowobjective.FlowObjectiveService; 33 import org.onosproject.net.flowobjective.FlowObjectiveService;
34 +import org.onosproject.net.group.GroupKey;
35 +import org.onosproject.net.group.GroupService;
33 import org.onosproject.net.intent.Intent; 36 import org.onosproject.net.intent.Intent;
34 import org.onosproject.net.intent.IntentBatchDelegate; 37 import org.onosproject.net.intent.IntentBatchDelegate;
35 import org.onosproject.net.intent.IntentCompiler; 38 import org.onosproject.net.intent.IntentCompiler;
...@@ -42,6 +45,8 @@ import org.onosproject.net.intent.IntentState; ...@@ -42,6 +45,8 @@ import org.onosproject.net.intent.IntentState;
42 import org.onosproject.net.intent.IntentStore; 45 import org.onosproject.net.intent.IntentStore;
43 import org.onosproject.net.intent.IntentStoreDelegate; 46 import org.onosproject.net.intent.IntentStoreDelegate;
44 import org.onosproject.net.intent.Key; 47 import org.onosproject.net.intent.Key;
48 +import org.onosproject.net.intent.PointToPointIntent;
49 +import org.onosproject.net.intent.impl.compiler.PointToPointIntentCompiler;
45 import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase; 50 import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
46 import org.onosproject.net.intent.impl.phase.IntentProcessPhase; 51 import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
47 import org.osgi.service.component.ComponentContext; 52 import org.osgi.service.component.ComponentContext;
...@@ -123,6 +128,9 @@ public class IntentManager ...@@ -123,6 +128,9 @@ public class IntentManager
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected ComponentConfigService configService; 129 protected ComponentConfigService configService;
125 130
131 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 + protected GroupService groupService;
133 +
126 private ExecutorService batchExecutor; 134 private ExecutorService batchExecutor;
127 private ExecutorService workerExecutor; 135 private ExecutorService workerExecutor;
128 136
...@@ -234,6 +242,15 @@ public class IntentManager ...@@ -234,6 +242,15 @@ public class IntentManager
234 checkNotNull(intent, INTENT_NULL); 242 checkNotNull(intent, INTENT_NULL);
235 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null); 243 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
236 store.addPending(data); 244 store.addPending(data);
245 +
246 + // remove associated group if there is one
247 + if (intent instanceof PointToPointIntent) {
248 + PointToPointIntent pointIntent = (PointToPointIntent) intent;
249 + DeviceId deviceId = pointIntent.ingressPoint().deviceId();
250 + GroupKey groupKey = PointToPointIntentCompiler.makeGroupKey(intent.id());
251 + groupService.removeGroup(deviceId, groupKey,
252 + intent.appId());
253 + }
237 } 254 }
238 255
239 @Override 256 @Override
......
...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; ...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList;
20 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Reference; 21 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.onosproject.net.DisjointPath;
23 import org.onosproject.net.ElementId; 24 import org.onosproject.net.ElementId;
24 import org.onosproject.net.Path; 25 import org.onosproject.net.Path;
25 import org.onosproject.net.intent.ConnectivityIntent; 26 import org.onosproject.net.intent.ConnectivityIntent;
...@@ -108,6 +109,29 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> ...@@ -108,6 +109,29 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
108 } 109 }
109 110
110 /** 111 /**
112 + * Computes a disjoint path between two ConnectPoints.
113 + *
114 + * @param intent intent on which behalf path is being computed
115 + * @param one start of the path
116 + * @param two end of the path
117 + * @return DisjointPath between the two
118 + * @throws PathNotFoundException if two paths cannot be found
119 + */
120 + protected DisjointPath getDisjointPath(ConnectivityIntent intent,
121 + ElementId one, ElementId two) {
122 + Set<DisjointPath> paths = pathService.getDisjointPaths(one, two, weight(intent.constraints()));
123 + final List<Constraint> constraints = intent.constraints();
124 + ImmutableList<DisjointPath> filtered = FluentIterable.from(paths)
125 + .filter(path -> checkPath(path, constraints))
126 + .toList();
127 + if (filtered.isEmpty()) {
128 + throw new PathNotFoundException(one, two);
129 + }
130 + // TODO: let's be more intelligent about this eventually
131 + return filtered.iterator().next();
132 + }
133 +
134 + /**
111 * Edge-weight capable of evaluating link cost using a set of constraints. 135 * Edge-weight capable of evaluating link cost using a set of constraints.
112 */ 136 */
113 protected class ConstraintBasedLinkWeight implements LinkWeight { 137 protected class ConstraintBasedLinkWeight implements LinkWeight {
......
...@@ -82,7 +82,7 @@ public class PathIntentCompiler ...@@ -82,7 +82,7 @@ public class PathIntentCompiler
82 compile(this, intent, rules, devices); 82 compile(this, intent, rules, devices);
83 83
84 84
85 - return ImmutableList.of(new FlowRuleIntent(appId, null, rules, intent.resources())); 85 + return ImmutableList.of(new FlowRuleIntent(appId, null, rules, intent.resources(), intent.type()));
86 } 86 }
87 87
88 @Override 88 @Override
......