Committed by
Gerrit Code Review
SinglePoint to MultiPoint Intent initial implementation
Change-Id: I1010997ce4ea993ae34afb8dab4b6c0ae112448d
Showing
9 changed files
with
293 additions
and
49 deletions
1 | +package org.onlab.onos.cli.net; | ||
2 | + | ||
3 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
4 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
5 | + | ||
6 | +import java.util.HashSet; | ||
7 | +import java.util.List; | ||
8 | +import java.util.Set; | ||
9 | + | ||
10 | +import org.apache.karaf.shell.commands.Argument; | ||
11 | +import org.apache.karaf.shell.commands.Command; | ||
12 | +import org.onlab.onos.net.ConnectPoint; | ||
13 | +import org.onlab.onos.net.DeviceId; | ||
14 | +import org.onlab.onos.net.PortNumber; | ||
15 | +import org.onlab.onos.net.flow.DefaultTrafficTreatment; | ||
16 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
17 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
18 | +import org.onlab.onos.net.intent.Constraint; | ||
19 | +import org.onlab.onos.net.intent.IntentService; | ||
20 | +import org.onlab.onos.net.intent.SinglePointToMultiPointIntent; | ||
21 | + | ||
22 | + | ||
23 | +@Command(scope = "onos", name = "add-single-to-multi-intent", | ||
24 | + description = "Installs connectivity intent between multiple egress devices and a single ingress device") | ||
25 | +public class AddSinglePointToMultiPointIntentCommand extends ConnectivityIntentCommand { | ||
26 | + @Argument(index = 0, name = "egressDevices ingressDevice", | ||
27 | + description = "egress Device/Port...egress Device/Port ingressDevice/port", | ||
28 | + required = true, multiValued = true) | ||
29 | + String[] deviceStrings = null; | ||
30 | + | ||
31 | + @Override | ||
32 | + protected void execute() { | ||
33 | + IntentService service = get(IntentService.class); | ||
34 | + | ||
35 | + if (deviceStrings.length < 2) { | ||
36 | + return; | ||
37 | + } | ||
38 | + | ||
39 | + String ingressDeviceString = deviceStrings[deviceStrings.length - 1]; | ||
40 | + DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString)); | ||
41 | + PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString)); | ||
42 | + ConnectPoint ingressPoint = new ConnectPoint(ingressDeviceId, | ||
43 | + ingressPortNumber); | ||
44 | + | ||
45 | + Set<ConnectPoint> egressPoints = new HashSet<>(); | ||
46 | + for (int index = 0; index < deviceStrings.length - 1; index++) { | ||
47 | + String egressDeviceString = deviceStrings[index]; | ||
48 | + DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString)); | ||
49 | + PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString)); | ||
50 | + ConnectPoint egress = new ConnectPoint(egressDeviceId, | ||
51 | + egressPortNumber); | ||
52 | + egressPoints.add(egress); | ||
53 | + } | ||
54 | + | ||
55 | + TrafficSelector selector = buildTrafficSelector(); | ||
56 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | ||
57 | + List<Constraint> constraints = buildConstraints(); | ||
58 | + | ||
59 | + SinglePointToMultiPointIntent intent = new SinglePointToMultiPointIntent( | ||
60 | + appId(), | ||
61 | + selector, | ||
62 | + treatment, | ||
63 | + ingressPoint, | ||
64 | + egressPoints, | ||
65 | + constraints); | ||
66 | + service.submit(intent); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * Extracts the port number portion of the ConnectPoint. | ||
71 | + * | ||
72 | + * @param deviceString string representing the device/port | ||
73 | + * @return port number as a string, empty string if the port is not found | ||
74 | + */ | ||
75 | + private String getPortNumber(String deviceString) { | ||
76 | + int slash = deviceString.indexOf('/'); | ||
77 | + if (slash <= 0) { | ||
78 | + return ""; | ||
79 | + } | ||
80 | + return deviceString.substring(slash + 1, deviceString.length()); | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Extracts the device ID portion of the ConnectPoint. | ||
85 | + * | ||
86 | + * @param deviceString string representing the device/port | ||
87 | + * @return device ID string | ||
88 | + */ | ||
89 | + private String getDeviceId(String deviceString) { | ||
90 | + int slash = deviceString.indexOf('/'); | ||
91 | + if (slash <= 0) { | ||
92 | + return ""; | ||
93 | + } | ||
94 | + return deviceString.substring(0, slash); | ||
95 | + } | ||
96 | + | ||
97 | +} |
... | @@ -340,7 +340,7 @@ public class IntentsListCommand extends AbstractShellCommand { | ... | @@ -340,7 +340,7 @@ public class IntentsListCommand extends AbstractShellCommand { |
340 | } else if (intent instanceof LinkCollectionIntent) { | 340 | } else if (intent instanceof LinkCollectionIntent) { |
341 | LinkCollectionIntent li = (LinkCollectionIntent) intent; | 341 | LinkCollectionIntent li = (LinkCollectionIntent) intent; |
342 | print(" links=%s", li.links()); | 342 | print(" links=%s", li.links()); |
343 | - print(" egress=%s", li.egressPoint()); | 343 | + print(" egress=%s", li.egressPoints()); |
344 | } | 344 | } |
345 | 345 | ||
346 | List<Intent> installable = service.getInstallableIntents(intent.id()); | 346 | List<Intent> installable = service.getInstallableIntents(intent.id()); | ... | ... |
... | @@ -161,6 +161,15 @@ | ... | @@ -161,6 +161,15 @@ |
161 | </optional-completers> | 161 | </optional-completers> |
162 | </command> | 162 | </command> |
163 | <command> | 163 | <command> |
164 | + <action class="org.onlab.onos.cli.net.AddSinglePointToMultiPointIntentCommand"/> | ||
165 | + <completers> | ||
166 | + <ref component-id="connectPointCompleter"/> | ||
167 | + </completers> | ||
168 | + <optional-completers> | ||
169 | + <entry key="-t" value-ref="ethTypeCompleter"/> | ||
170 | + </optional-completers> | ||
171 | + </command> | ||
172 | + <command> | ||
164 | <action class="org.onlab.onos.cli.net.IntentPushTestCommand"/> | 173 | <action class="org.onlab.onos.cli.net.IntentPushTestCommand"/> |
165 | <completers> | 174 | <completers> |
166 | <ref component-id="connectPointCompleter"/> | 175 | <ref component-id="connectPointCompleter"/> | ... | ... |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | import com.google.common.base.MoreObjects; | 18 | import com.google.common.base.MoreObjects; |
19 | +import com.google.common.collect.ImmutableSet; | ||
20 | + | ||
19 | import org.onlab.onos.core.ApplicationId; | 21 | import org.onlab.onos.core.ApplicationId; |
20 | import org.onlab.onos.net.ConnectPoint; | 22 | import org.onlab.onos.net.ConnectPoint; |
21 | import org.onlab.onos.net.Link; | 23 | import org.onlab.onos.net.Link; |
... | @@ -34,11 +36,11 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -34,11 +36,11 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
34 | 36 | ||
35 | private final Set<Link> links; | 37 | private final Set<Link> links; |
36 | 38 | ||
37 | - private final ConnectPoint egressPoint; | 39 | + private final Set<ConnectPoint> egressPoints; |
38 | 40 | ||
39 | /** | 41 | /** |
40 | - * Creates a new actionable intent capable of funneling the selected | 42 | + * Creates a new actionable intent capable of funneling the selected traffic |
41 | - * traffic along the specified convergent tree and out the given egress point. | 43 | + * along the specified convergent tree and out the given egress point. |
42 | * | 44 | * |
43 | * @param appId application identifier | 45 | * @param appId application identifier |
44 | * @param selector traffic match | 46 | * @param selector traffic match |
... | @@ -77,7 +79,31 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -77,7 +79,31 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
77 | super(id(LinkCollectionIntent.class, selector, treatment, links, egressPoint, constraints), | 79 | super(id(LinkCollectionIntent.class, selector, treatment, links, egressPoint, constraints), |
78 | appId, resources(links), selector, treatment, constraints); | 80 | appId, resources(links), selector, treatment, constraints); |
79 | this.links = links; | 81 | this.links = links; |
80 | - this.egressPoint = egressPoint; | 82 | + this.egressPoints = ImmutableSet.of(egressPoint); |
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Creates a new actionable intent capable of funneling the selected traffic | ||
87 | + * along the specified convergent tree and out the given egress point. | ||
88 | + * | ||
89 | + * @param appId application identifier | ||
90 | + * @param selector traffic match | ||
91 | + * @param treatment action | ||
92 | + * @param links traversed links | ||
93 | + * @param egressPoints Set of egress point | ||
94 | + * @throws NullPointerException {@code path} is null | ||
95 | + */ | ||
96 | + public LinkCollectionIntent(ApplicationId appId, | ||
97 | + TrafficSelector selector, | ||
98 | + TrafficTreatment treatment, | ||
99 | + Set<Link> links, | ||
100 | + Set<ConnectPoint> egressPoints, | ||
101 | + List<Constraint> constraints) { | ||
102 | + super(id(LinkCollectionIntent.class, selector, treatment, links, | ||
103 | + egressPoints), appId, resources(links), selector, treatment); | ||
104 | + | ||
105 | + this.links = links; | ||
106 | + this.egressPoints = ImmutableSet.copyOf(egressPoints); | ||
81 | } | 107 | } |
82 | 108 | ||
83 | /** | 109 | /** |
... | @@ -86,7 +112,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -86,7 +112,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
86 | protected LinkCollectionIntent() { | 112 | protected LinkCollectionIntent() { |
87 | super(); | 113 | super(); |
88 | this.links = null; | 114 | this.links = null; |
89 | - this.egressPoint = null; | 115 | + this.egressPoints = null; |
90 | } | 116 | } |
91 | 117 | ||
92 | /** | 118 | /** |
... | @@ -104,8 +130,8 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -104,8 +130,8 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
104 | * | 130 | * |
105 | * @return the egress point | 131 | * @return the egress point |
106 | */ | 132 | */ |
107 | - public ConnectPoint egressPoint() { | 133 | + public Set<ConnectPoint> egressPoints() { |
108 | - return egressPoint; | 134 | + return egressPoints; |
109 | } | 135 | } |
110 | 136 | ||
111 | @Override | 137 | @Override |
... | @@ -121,7 +147,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -121,7 +147,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
121 | .add("selector", selector()) | 147 | .add("selector", selector()) |
122 | .add("treatment", treatment()) | 148 | .add("treatment", treatment()) |
123 | .add("links", links()) | 149 | .add("links", links()) |
124 | - .add("egress", egressPoint()) | 150 | + .add("egress", egressPoints()) |
125 | .toString(); | 151 | .toString(); |
126 | } | 152 | } |
127 | } | 153 | } | ... | ... |
... | @@ -17,12 +17,15 @@ package org.onlab.onos.net.intent; | ... | @@ -17,12 +17,15 @@ package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | import com.google.common.base.MoreObjects; | 18 | import com.google.common.base.MoreObjects; |
19 | import com.google.common.collect.Sets; | 19 | import com.google.common.collect.Sets; |
20 | + | ||
20 | import org.onlab.onos.core.ApplicationId; | 21 | import org.onlab.onos.core.ApplicationId; |
21 | import org.onlab.onos.net.ConnectPoint; | 22 | import org.onlab.onos.net.ConnectPoint; |
22 | import org.onlab.onos.net.flow.TrafficSelector; | 23 | import org.onlab.onos.net.flow.TrafficSelector; |
23 | import org.onlab.onos.net.flow.TrafficTreatment; | 24 | import org.onlab.onos.net.flow.TrafficTreatment; |
24 | 25 | ||
26 | +import java.util.Collections; | ||
25 | import java.util.Set; | 27 | import java.util.Set; |
28 | +import java.util.List; | ||
26 | 29 | ||
27 | import static com.google.common.base.Preconditions.checkArgument; | 30 | import static com.google.common.base.Preconditions.checkArgument; |
28 | import static com.google.common.base.Preconditions.checkNotNull; | 31 | import static com.google.common.base.Preconditions.checkNotNull; |
... | @@ -49,19 +52,39 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { | ... | @@ -49,19 +52,39 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { |
49 | * not more than 1 | 52 | * not more than 1 |
50 | */ | 53 | */ |
51 | public SinglePointToMultiPointIntent(ApplicationId appId, | 54 | public SinglePointToMultiPointIntent(ApplicationId appId, |
52 | - TrafficSelector selector, | 55 | + TrafficSelector selector, TrafficTreatment treatment, |
53 | - TrafficTreatment treatment, | 56 | + ConnectPoint ingressPoint, Set<ConnectPoint> egressPoints) { |
54 | - ConnectPoint ingressPoint, | 57 | + this(appId, selector, treatment, ingressPoint, egressPoints, Collections.emptyList()); |
55 | - Set<ConnectPoint> egressPoints) { | 58 | + } |
59 | + | ||
60 | + /** | ||
61 | + * Creates a new single-to-multi point connectivity intent. | ||
62 | + * | ||
63 | + * @param appId application identifier | ||
64 | + * @param selector traffic selector | ||
65 | + * @param treatment treatment | ||
66 | + * @param ingressPoint port on which traffic will ingress | ||
67 | + * @param egressPoints set of ports on which traffic will egress | ||
68 | + * @param constraints constraints to apply to the intent | ||
69 | + * @throws NullPointerException if {@code ingressPoint} or | ||
70 | + * {@code egressPoints} is null | ||
71 | + * @throws IllegalArgumentException if the size of {@code egressPoints} is | ||
72 | + * not more than 1 | ||
73 | + */ | ||
74 | + public SinglePointToMultiPointIntent(ApplicationId appId, | ||
75 | + TrafficSelector selector, TrafficTreatment treatment, | ||
76 | + ConnectPoint ingressPoint, Set<ConnectPoint> egressPoints, | ||
77 | + List<Constraint> constraints) { | ||
56 | super(id(SinglePointToMultiPointIntent.class, selector, treatment, | 78 | super(id(SinglePointToMultiPointIntent.class, selector, treatment, |
57 | - ingressPoint, egressPoints), appId, null, selector, treatment); | 79 | + ingressPoint, egressPoints), appId, null, selector, treatment, |
80 | + constraints); | ||
58 | checkNotNull(egressPoints); | 81 | checkNotNull(egressPoints); |
59 | checkNotNull(ingressPoint); | 82 | checkNotNull(ingressPoint); |
60 | checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty"); | 83 | checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty"); |
61 | checkArgument(!egressPoints.contains(ingressPoint), | 84 | checkArgument(!egressPoints.contains(ingressPoint), |
62 | "Set of egresses should not contain ingress (ingress: %s)", ingressPoint); | 85 | "Set of egresses should not contain ingress (ingress: %s)", ingressPoint); |
63 | 86 | ||
64 | - this.ingressPoint = ingressPoint; | 87 | + this.ingressPoint = checkNotNull(ingressPoint); |
65 | this.egressPoints = Sets.newHashSet(egressPoints); | 88 | this.egressPoints = Sets.newHashSet(egressPoints); |
66 | } | 89 | } |
67 | 90 | ||
... | @@ -75,7 +98,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { | ... | @@ -75,7 +98,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { |
75 | } | 98 | } |
76 | 99 | ||
77 | /** | 100 | /** |
78 | - * Returns the port on which the ingress traffic should be connected to the egress. | 101 | + * Returns the port on which the ingress traffic should be connected to the |
102 | + * egress. | ||
79 | * | 103 | * |
80 | * @return ingress port | 104 | * @return ingress port |
81 | */ | 105 | */ |
... | @@ -101,6 +125,7 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { | ... | @@ -101,6 +125,7 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { |
101 | .add("treatment", treatment()) | 125 | .add("treatment", treatment()) |
102 | .add("ingress", ingressPoint) | 126 | .add("ingress", ingressPoint) |
103 | .add("egress", egressPoints) | 127 | .add("egress", egressPoints) |
128 | + .add("constraints", constraints()) | ||
104 | .toString(); | 129 | .toString(); |
105 | } | 130 | } |
106 | 131 | ... | ... |
... | @@ -28,6 +28,7 @@ import org.onlab.onos.net.flow.TrafficSelector; | ... | @@ -28,6 +28,7 @@ import org.onlab.onos.net.flow.TrafficSelector; |
28 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; | 28 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; |
29 | import org.onlab.onos.net.resource.Lambda; | 29 | import org.onlab.onos.net.resource.Lambda; |
30 | 30 | ||
31 | +import com.google.common.collect.ImmutableSet; | ||
31 | import com.google.common.testing.EqualsTester; | 32 | import com.google.common.testing.EqualsTester; |
32 | 33 | ||
33 | import static org.hamcrest.MatcherAssert.assertThat; | 34 | import static org.hamcrest.MatcherAssert.assertThat; |
... | @@ -111,7 +112,7 @@ public class LinkCollectionIntentTest { | ... | @@ -111,7 +112,7 @@ public class LinkCollectionIntentTest { |
111 | assertThat(collectionIntent.isInstallable(), is(true)); | 112 | assertThat(collectionIntent.isInstallable(), is(true)); |
112 | assertThat(collectionIntent.treatment(), is(treatment)); | 113 | assertThat(collectionIntent.treatment(), is(treatment)); |
113 | assertThat(collectionIntent.selector(), is(selector)); | 114 | assertThat(collectionIntent.selector(), is(selector)); |
114 | - assertThat(collectionIntent.egressPoint(), is(egress)); | 115 | + assertThat(collectionIntent.egressPoints(), is(ImmutableSet.of(egress))); |
115 | assertThat(collectionIntent.resources(), hasSize(1)); | 116 | assertThat(collectionIntent.resources(), hasSize(1)); |
116 | final List<Constraint> createdConstraints = collectionIntent.constraints(); | 117 | final List<Constraint> createdConstraints = collectionIntent.constraints(); |
117 | assertThat(createdConstraints, hasSize(0)); | 118 | assertThat(createdConstraints, hasSize(0)); |
... | @@ -140,7 +141,7 @@ public class LinkCollectionIntentTest { | ... | @@ -140,7 +141,7 @@ public class LinkCollectionIntentTest { |
140 | assertThat(collectionIntent.isInstallable(), is(true)); | 141 | assertThat(collectionIntent.isInstallable(), is(true)); |
141 | assertThat(collectionIntent.treatment(), is(treatment)); | 142 | assertThat(collectionIntent.treatment(), is(treatment)); |
142 | assertThat(collectionIntent.selector(), is(selector)); | 143 | assertThat(collectionIntent.selector(), is(selector)); |
143 | - assertThat(collectionIntent.egressPoint(), is(egress)); | 144 | + assertThat(collectionIntent.egressPoints(), is(ImmutableSet.of(egress))); |
144 | 145 | ||
145 | final List<Constraint> createdConstraints = collectionIntent.constraints(); | 146 | final List<Constraint> createdConstraints = collectionIntent.constraints(); |
146 | assertThat(createdConstraints, hasSize(1)); | 147 | assertThat(createdConstraints, hasSize(1)); |
... | @@ -161,7 +162,7 @@ public class LinkCollectionIntentTest { | ... | @@ -161,7 +162,7 @@ public class LinkCollectionIntentTest { |
161 | assertThat(collectionIntent.isInstallable(), is(true)); | 162 | assertThat(collectionIntent.isInstallable(), is(true)); |
162 | assertThat(collectionIntent.treatment(), nullValue()); | 163 | assertThat(collectionIntent.treatment(), nullValue()); |
163 | assertThat(collectionIntent.selector(), nullValue()); | 164 | assertThat(collectionIntent.selector(), nullValue()); |
164 | - assertThat(collectionIntent.egressPoint(), nullValue()); | 165 | + assertThat(collectionIntent.egressPoints(), nullValue()); |
165 | 166 | ||
166 | final List<Constraint> createdConstraints = collectionIntent.constraints(); | 167 | final List<Constraint> createdConstraints = collectionIntent.constraints(); |
167 | assertThat(createdConstraints, hasSize(0)); | 168 | assertThat(createdConstraints, hasSize(0)); | ... | ... |
... | @@ -15,9 +15,12 @@ | ... | @@ -15,9 +15,12 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent.impl; | 16 | package org.onlab.onos.net.intent.impl; |
17 | 17 | ||
18 | -import static org.slf4j.LoggerFactory.getLogger; | 18 | +import java.util.HashMap; |
19 | - | 19 | +import java.util.HashSet; |
20 | import java.util.List; | 20 | import java.util.List; |
21 | +import java.util.Map; | ||
22 | +import java.util.Map.Entry; | ||
23 | +import java.util.Set; | ||
21 | 24 | ||
22 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
23 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
... | @@ -26,6 +29,7 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -26,6 +29,7 @@ import org.apache.felix.scr.annotations.Reference; |
26 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 29 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
27 | import org.onlab.onos.core.ApplicationId; | 30 | import org.onlab.onos.core.ApplicationId; |
28 | import org.onlab.onos.core.CoreService; | 31 | import org.onlab.onos.core.CoreService; |
32 | +import org.onlab.onos.net.ConnectPoint; | ||
29 | import org.onlab.onos.net.DeviceId; | 33 | import org.onlab.onos.net.DeviceId; |
30 | import org.onlab.onos.net.Link; | 34 | import org.onlab.onos.net.Link; |
31 | import org.onlab.onos.net.PortNumber; | 35 | import org.onlab.onos.net.PortNumber; |
... | @@ -42,18 +46,16 @@ import org.onlab.onos.net.intent.IntentExtensionService; | ... | @@ -42,18 +46,16 @@ import org.onlab.onos.net.intent.IntentExtensionService; |
42 | import org.onlab.onos.net.intent.IntentInstaller; | 46 | import org.onlab.onos.net.intent.IntentInstaller; |
43 | import org.onlab.onos.net.intent.LinkCollectionIntent; | 47 | import org.onlab.onos.net.intent.LinkCollectionIntent; |
44 | import org.onlab.onos.net.intent.PathIntent; | 48 | import org.onlab.onos.net.intent.PathIntent; |
45 | -import org.slf4j.Logger; | ||
46 | 49 | ||
47 | import com.google.common.collect.Lists; | 50 | import com.google.common.collect.Lists; |
48 | 51 | ||
49 | /** | 52 | /** |
50 | - * Installer for {@link org.onlab.onos.net.intent.LinkCollectionIntent} | 53 | + * Installer for {@link org.onlab.onos.net.intent.LinkCollectionIntent} path |
51 | - * path segment intents. | 54 | + * segment intents. |
52 | */ | 55 | */ |
53 | @Component(immediate = true) | 56 | @Component(immediate = true) |
54 | -public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollectionIntent> { | 57 | +public class LinkCollectionIntentInstaller |
55 | - | 58 | + implements IntentInstaller<LinkCollectionIntent> { |
56 | - private final Logger log = getLogger(getClass()); | ||
57 | 59 | ||
58 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 60 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
59 | protected IntentExtensionService intentManager; | 61 | protected IntentExtensionService intentManager; |
... | @@ -76,37 +78,58 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec | ... | @@ -76,37 +78,58 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec |
76 | 78 | ||
77 | @Override | 79 | @Override |
78 | public List<FlowRuleBatchOperation> install(LinkCollectionIntent intent) { | 80 | public List<FlowRuleBatchOperation> install(LinkCollectionIntent intent) { |
81 | + Map<DeviceId, Set<PortNumber>> outputMap = new HashMap<DeviceId, Set<PortNumber>>(); | ||
79 | List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); | 82 | List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); |
83 | + | ||
80 | for (Link link : intent.links()) { | 84 | for (Link link : intent.links()) { |
81 | - rules.add(createBatchEntry(FlowRuleOperation.ADD, | 85 | + if (outputMap.get(link.src().deviceId()) == null) { |
82 | - intent, | 86 | + outputMap.put(link.src().deviceId(), new HashSet<PortNumber>()); |
83 | - link.src().deviceId(), | 87 | + } |
84 | - link.src().port())); | 88 | + outputMap.get(link.src().deviceId()).add(link.src().port()); |
89 | + | ||
90 | + } | ||
91 | + | ||
92 | + for (ConnectPoint egressPoint : intent.egressPoints()) { | ||
93 | + if (outputMap.get(egressPoint.deviceId()) == null) { | ||
94 | + outputMap | ||
95 | + .put(egressPoint.deviceId(), new HashSet<PortNumber>()); | ||
96 | + } | ||
97 | + outputMap.get(egressPoint.deviceId()).add(egressPoint.port()); | ||
98 | + | ||
85 | } | 99 | } |
86 | 100 | ||
87 | - rules.add(createBatchEntry(FlowRuleOperation.ADD, | 101 | + for (Entry<DeviceId, Set<PortNumber>> entry : outputMap.entrySet()) { |
88 | - intent, | 102 | + rules.add(createBatchEntry(FlowRuleOperation.ADD, intent, |
89 | - intent.egressPoint().deviceId(), | 103 | + entry.getKey(), entry.getValue())); |
90 | - intent.egressPoint().port())); | 104 | + } |
91 | 105 | ||
92 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); | 106 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); |
93 | } | 107 | } |
94 | 108 | ||
95 | @Override | 109 | @Override |
96 | public List<FlowRuleBatchOperation> uninstall(LinkCollectionIntent intent) { | 110 | public List<FlowRuleBatchOperation> uninstall(LinkCollectionIntent intent) { |
111 | + Map<DeviceId, Set<PortNumber>> outputMap = new HashMap<DeviceId, Set<PortNumber>>(); | ||
97 | List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); | 112 | List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); |
98 | 113 | ||
99 | for (Link link : intent.links()) { | 114 | for (Link link : intent.links()) { |
100 | - rules.add(createBatchEntry(FlowRuleOperation.REMOVE, | 115 | + if (outputMap.get(link.src().deviceId()) == null) { |
101 | - intent, | 116 | + outputMap.put(link.src().deviceId(), new HashSet<PortNumber>()); |
102 | - link.src().deviceId(), | 117 | + } |
103 | - link.src().port())); | 118 | + outputMap.get(link.src().deviceId()).add(link.src().port()); |
119 | + } | ||
120 | + | ||
121 | + for (ConnectPoint egressPoint : intent.egressPoints()) { | ||
122 | + if (outputMap.get(egressPoint.deviceId()) == null) { | ||
123 | + outputMap | ||
124 | + .put(egressPoint.deviceId(), new HashSet<PortNumber>()); | ||
125 | + } | ||
126 | + outputMap.get(egressPoint.deviceId()).add(egressPoint.port()); | ||
104 | } | 127 | } |
105 | 128 | ||
106 | - rules.add(createBatchEntry(FlowRuleOperation.REMOVE, | 129 | + for (Entry<DeviceId, Set<PortNumber>> entry : outputMap.entrySet()) { |
107 | - intent, | 130 | + rules.add(createBatchEntry(FlowRuleOperation.REMOVE, intent, |
108 | - intent.egressPoint().deviceId(), | 131 | + entry.getKey(), entry.getValue())); |
109 | - intent.egressPoint().port())); | 132 | + } |
110 | 133 | ||
111 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); | 134 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); |
112 | } | 135 | } |
... | @@ -130,15 +153,18 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec | ... | @@ -130,15 +153,18 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec |
130 | private FlowRuleBatchEntry createBatchEntry(FlowRuleOperation operation, | 153 | private FlowRuleBatchEntry createBatchEntry(FlowRuleOperation operation, |
131 | LinkCollectionIntent intent, | 154 | LinkCollectionIntent intent, |
132 | DeviceId deviceId, | 155 | DeviceId deviceId, |
133 | - PortNumber outPort) { | 156 | + Set<PortNumber> outPorts) { |
134 | 157 | ||
135 | - TrafficTreatment.Builder treatmentBuilder = | 158 | + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment |
136 | - DefaultTrafficTreatment.builder(intent.treatment()); | 159 | + .builder(intent.treatment()); |
137 | 160 | ||
138 | - TrafficTreatment treatment = treatmentBuilder.setOutput(outPort).build(); | 161 | + for (PortNumber outPort : outPorts) { |
162 | + treatmentBuilder.setOutput(outPort); | ||
163 | + } | ||
164 | + TrafficTreatment treatment = treatmentBuilder.build(); | ||
139 | 165 | ||
140 | - TrafficSelector selector = DefaultTrafficSelector.builder(intent.selector()) | 166 | + TrafficSelector selector = DefaultTrafficSelector |
141 | - .build(); | 167 | + .builder(intent.selector()).build(); |
142 | 168 | ||
143 | FlowRule rule = new DefaultFlowRule(deviceId, | 169 | FlowRule rule = new DefaultFlowRule(deviceId, |
144 | selector, treatment, 123, | 170 | selector, treatment, 123, | ... | ... |
core/net/src/main/java/org/onlab/onos/net/intent/impl/SinglePointToMultiPointIntentCompiler.java
0 → 100644
1 | +package org.onlab.onos.net.intent.impl; | ||
2 | + | ||
3 | +import java.util.Arrays; | ||
4 | +import java.util.HashSet; | ||
5 | +import java.util.List; | ||
6 | +import java.util.Set; | ||
7 | + | ||
8 | +import org.apache.felix.scr.annotations.Activate; | ||
9 | +import org.apache.felix.scr.annotations.Component; | ||
10 | +import org.apache.felix.scr.annotations.Deactivate; | ||
11 | +import org.onlab.onos.net.ConnectPoint; | ||
12 | +import org.onlab.onos.net.Link; | ||
13 | +import org.onlab.onos.net.Path; | ||
14 | +import org.onlab.onos.net.intent.Intent; | ||
15 | +import org.onlab.onos.net.intent.LinkCollectionIntent; | ||
16 | +import org.onlab.onos.net.intent.SinglePointToMultiPointIntent; | ||
17 | +import org.onlab.onos.net.provider.ProviderId; | ||
18 | +import org.onlab.onos.net.resource.LinkResourceAllocations; | ||
19 | + | ||
20 | +@Component(immediate = true) | ||
21 | +public class SinglePointToMultiPointIntentCompiler | ||
22 | + extends ConnectivityIntentCompiler<SinglePointToMultiPointIntent> { | ||
23 | + | ||
24 | + // TODO: use off-the-shell core provider ID | ||
25 | + private static final ProviderId PID = | ||
26 | + new ProviderId("core", "org.onlab.onos.core", true); | ||
27 | + | ||
28 | + @Activate | ||
29 | + public void activate() { | ||
30 | + intentManager.registerCompiler(SinglePointToMultiPointIntent.class, | ||
31 | + this); | ||
32 | + } | ||
33 | + | ||
34 | + @Deactivate | ||
35 | + public void deactivate() { | ||
36 | + intentManager.unregisterCompiler(SinglePointToMultiPointIntent.class); | ||
37 | + } | ||
38 | + | ||
39 | + | ||
40 | + @Override | ||
41 | + public List<Intent> compile(SinglePointToMultiPointIntent intent, | ||
42 | + List<Intent> installable, | ||
43 | + Set<LinkResourceAllocations> resources) { | ||
44 | + Set<Link> links = new HashSet<>(); | ||
45 | + //FIXME: need to handle the case where ingress/egress points are on same switch | ||
46 | + for (ConnectPoint egressPoint : intent.egressPoints()) { | ||
47 | + Path path = getPath(intent, intent.ingressPoint().deviceId(), egressPoint.deviceId()); | ||
48 | + links.addAll(path.links()); | ||
49 | + } | ||
50 | + | ||
51 | + Intent result = new LinkCollectionIntent(intent.appId(), | ||
52 | + intent.selector(), | ||
53 | + intent.treatment(), links, | ||
54 | + intent.egressPoints(), null); | ||
55 | + | ||
56 | + return Arrays.asList(result); | ||
57 | + } | ||
58 | +} |
... | @@ -80,6 +80,7 @@ import org.onlab.onos.net.intent.OpticalPathIntent; | ... | @@ -80,6 +80,7 @@ import org.onlab.onos.net.intent.OpticalPathIntent; |
80 | import org.onlab.onos.net.intent.PathIntent; | 80 | import org.onlab.onos.net.intent.PathIntent; |
81 | import org.onlab.onos.net.intent.PointToPointIntent; | 81 | import org.onlab.onos.net.intent.PointToPointIntent; |
82 | import org.onlab.onos.net.intent.constraint.AnnotationConstraint; | 82 | import org.onlab.onos.net.intent.constraint.AnnotationConstraint; |
83 | +import org.onlab.onos.net.intent.SinglePointToMultiPointIntent; | ||
83 | import org.onlab.onos.net.intent.constraint.BandwidthConstraint; | 84 | import org.onlab.onos.net.intent.constraint.BandwidthConstraint; |
84 | import org.onlab.onos.net.intent.constraint.BooleanConstraint; | 85 | import org.onlab.onos.net.intent.constraint.BooleanConstraint; |
85 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; | 86 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; |
... | @@ -251,6 +252,7 @@ public final class KryoNamespaces { | ... | @@ -251,6 +252,7 @@ public final class KryoNamespaces { |
251 | HostToHostIntent.class, | 252 | HostToHostIntent.class, |
252 | PointToPointIntent.class, | 253 | PointToPointIntent.class, |
253 | MultiPointToSinglePointIntent.class, | 254 | MultiPointToSinglePointIntent.class, |
255 | + SinglePointToMultiPointIntent.class, | ||
254 | LinkCollectionIntent.class, | 256 | LinkCollectionIntent.class, |
255 | OpticalConnectivityIntent.class, | 257 | OpticalConnectivityIntent.class, |
256 | OpticalPathIntent.class, | 258 | OpticalPathIntent.class, | ... | ... |
-
Please register or login to post a comment