Rimon Ashkenazy
Committed by Gerrit Code Review

Add Optical ODU cross-connect Intent

Create a new intent: OpticalOduIntent in the OTN Topology.
 - This intent finds a path of OTU links, and
 - Allocates TributarySlots resources on the OTU ports (in the path)
 - also add a utility for converting various SignalTypes to
   OduSignalType, and to build the OduSignalId.

Note: this patch follows the example given in patch
https://gerrit.onosproject.org/#/c/7321 of
separate resource search from resource allocation.

Change-Id: Id9808f61aebb80a21481f3882aff23b236b68078
...@@ -20,6 +20,7 @@ import org.apache.karaf.shell.commands.Command; ...@@ -20,6 +20,7 @@ import org.apache.karaf.shell.commands.Command;
20 import org.apache.karaf.shell.commands.Option; 20 import org.apache.karaf.shell.commands.Option;
21 import org.onosproject.net.CltSignalType; 21 import org.onosproject.net.CltSignalType;
22 import org.onosproject.net.ConnectPoint; 22 import org.onosproject.net.ConnectPoint;
23 +import org.onosproject.net.Device;
23 import org.onosproject.net.OchPort; 24 import org.onosproject.net.OchPort;
24 import org.onosproject.net.OduCltPort; 25 import org.onosproject.net.OduCltPort;
25 import org.onosproject.net.DeviceId; 26 import org.onosproject.net.DeviceId;
...@@ -30,6 +31,7 @@ import org.onosproject.net.intent.Intent; ...@@ -30,6 +31,7 @@ import org.onosproject.net.intent.Intent;
30 import org.onosproject.net.intent.IntentService; 31 import org.onosproject.net.intent.IntentService;
31 import org.onosproject.net.intent.OpticalCircuitIntent; 32 import org.onosproject.net.intent.OpticalCircuitIntent;
32 import org.onosproject.net.intent.OpticalConnectivityIntent; 33 import org.onosproject.net.intent.OpticalConnectivityIntent;
34 +import org.onosproject.net.intent.OpticalOduIntent;
33 35
34 import java.util.List; 36 import java.util.List;
35 37
...@@ -96,27 +98,52 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand { ...@@ -96,27 +98,52 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
96 Port dstPort = deviceService.getPort(egress.deviceId(), egress.port()); 98 Port dstPort = deviceService.getPort(egress.deviceId(), egress.port());
97 99
98 Intent intent; 100 Intent intent;
99 - // FIXME: Hardcoded signal types 101 +
100 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) { 102 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
101 - intent = OpticalCircuitIntent.builder() 103 + Device srcDevice = deviceService.getDevice(ingress.deviceId());
102 - .appId(appId()) 104 + Device dstDevice = deviceService.getDevice(egress.deviceId());
103 - .key(key()) 105 +
104 - .src(ingress) 106 + // continue only if both OduClt port's Devices are of the same type
105 - .dst(egress) 107 + if (!(srcDevice.type().equals(dstDevice.type()))) {
106 - .signalType(CltSignalType.CLT_10GBE) 108 + print("Devices without same deviceType: SRC=%s and DST=%s", srcDevice.type(), dstDevice.type());
107 - .bidirectional(bidirectional) 109 + return;
108 - .build(); 110 + }
111 +
112 + CltSignalType signalType = ((OduCltPort) srcPort).signalType();
113 + if (Device.Type.ROADM.equals(srcDevice.type())) {
114 + intent = OpticalCircuitIntent.builder()
115 + .appId(appId())
116 + .key(key())
117 + .src(ingress)
118 + .dst(egress)
119 + .signalType(signalType)
120 + .bidirectional(bidirectional)
121 + .build();
122 + } else if (Device.Type.OTN.equals(srcDevice.type())) {
123 + intent = OpticalOduIntent.builder()
124 + .appId(appId())
125 + .key(key())
126 + .src(ingress)
127 + .dst(egress)
128 + .signalType(signalType)
129 + .bidirectional(bidirectional)
130 + .build();
131 + } else {
132 + print("Wrong Device Type for connect points %s and %s", ingress, egress);
133 + return;
134 + }
109 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) { 135 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
136 + OduSignalType signalType = ((OchPort) srcPort).signalType();
110 intent = OpticalConnectivityIntent.builder() 137 intent = OpticalConnectivityIntent.builder()
111 .appId(appId()) 138 .appId(appId())
112 .key(key()) 139 .key(key())
113 .src(ingress) 140 .src(ingress)
114 .dst(egress) 141 .dst(egress)
115 - .signalType(OduSignalType.ODU4) 142 + .signalType(signalType)
116 .bidirectional(bidirectional) 143 .bidirectional(bidirectional)
117 .build(); 144 .build();
118 } else { 145 } else {
119 - print("Unable to create optical intent between connect points {} and {}", ingress, egress); 146 + print("Unable to create optical intent between connect points %s and %s", ingress, egress);
120 return; 147 return;
121 } 148 }
122 149
......
...@@ -29,6 +29,7 @@ import org.onosproject.net.intent.LinkCollectionIntent; ...@@ -29,6 +29,7 @@ import org.onosproject.net.intent.LinkCollectionIntent;
29 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 29 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
30 import org.onosproject.net.intent.OpticalCircuitIntent; 30 import org.onosproject.net.intent.OpticalCircuitIntent;
31 import org.onosproject.net.intent.OpticalConnectivityIntent; 31 import org.onosproject.net.intent.OpticalConnectivityIntent;
32 +import org.onosproject.net.intent.OpticalOduIntent;
32 import org.onosproject.net.intent.PathIntent; 33 import org.onosproject.net.intent.PathIntent;
33 import org.onosproject.net.intent.PointToPointIntent; 34 import org.onosproject.net.intent.PointToPointIntent;
34 import org.onosproject.net.intent.SinglePointToMultiPointIntent; 35 import org.onosproject.net.intent.SinglePointToMultiPointIntent;
...@@ -118,6 +119,7 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -118,6 +119,7 @@ public class IntentsListCommand extends AbstractShellCommand {
118 private IntentSummary summaryLinkCollection; 119 private IntentSummary summaryLinkCollection;
119 private IntentSummary summaryOpticalCircuit; 120 private IntentSummary summaryOpticalCircuit;
120 private IntentSummary summaryOpticalConnectivity; 121 private IntentSummary summaryOpticalConnectivity;
122 + private IntentSummary summaryOpticalOdu;
121 private IntentSummary summaryUnknownType; 123 private IntentSummary summaryUnknownType;
122 124
123 /** 125 /**
...@@ -136,6 +138,7 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -136,6 +138,7 @@ public class IntentsListCommand extends AbstractShellCommand {
136 summaryLinkCollection = new IntentSummary("LinkCollection"); 138 summaryLinkCollection = new IntentSummary("LinkCollection");
137 summaryOpticalCircuit = new IntentSummary("OpticalCircuit"); 139 summaryOpticalCircuit = new IntentSummary("OpticalCircuit");
138 summaryOpticalConnectivity = new IntentSummary("OpticalConnectivity"); 140 summaryOpticalConnectivity = new IntentSummary("OpticalConnectivity");
141 + summaryOpticalOdu = new IntentSummary("OpticalOdu");
139 summaryUnknownType = new IntentSummary("UnknownType"); 142 summaryUnknownType = new IntentSummary("UnknownType");
140 } 143 }
141 144
...@@ -196,6 +199,10 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -196,6 +199,10 @@ public class IntentsListCommand extends AbstractShellCommand {
196 summaryOpticalConnectivity.update(intentState); 199 summaryOpticalConnectivity.update(intentState);
197 continue; 200 continue;
198 } 201 }
202 + if (intent instanceof OpticalOduIntent) {
203 + summaryOpticalOdu.update(intentState);
204 + continue;
205 + }
199 summaryUnknownType.update(intentState); 206 summaryUnknownType.update(intentState);
200 } 207 }
201 } 208 }
...@@ -219,6 +226,7 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -219,6 +226,7 @@ public class IntentsListCommand extends AbstractShellCommand {
219 result.set("linkCollection", summaryLinkCollection.json(mapper)); 226 result.set("linkCollection", summaryLinkCollection.json(mapper));
220 result.set("opticalCircuit", summaryOpticalCircuit.json(mapper)); 227 result.set("opticalCircuit", summaryOpticalCircuit.json(mapper));
221 result.set("opticalConnectivity", summaryOpticalConnectivity.json(mapper)); 228 result.set("opticalConnectivity", summaryOpticalConnectivity.json(mapper));
229 + result.set("opticalOdu", summaryOpticalOdu.json(mapper));
222 result.set("unknownType", summaryUnknownType.json(mapper)); 230 result.set("unknownType", summaryUnknownType.json(mapper));
223 result.set("all", summaryAll.json(mapper)); 231 result.set("all", summaryAll.json(mapper));
224 return result; 232 return result;
...@@ -237,6 +245,7 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -237,6 +245,7 @@ public class IntentsListCommand extends AbstractShellCommand {
237 summaryLinkCollection.printState(); 245 summaryLinkCollection.printState();
238 summaryOpticalCircuit.printState(); 246 summaryOpticalCircuit.printState();
239 summaryOpticalConnectivity.printState(); 247 summaryOpticalConnectivity.printState();
248 + summaryOpticalOdu.printState();
240 summaryUnknownType.printState(); 249 summaryUnknownType.printState();
241 summaryAll.printState(); 250 summaryAll.printState();
242 } 251 }
...@@ -401,6 +410,9 @@ public class IntentsListCommand extends AbstractShellCommand { ...@@ -401,6 +410,9 @@ public class IntentsListCommand extends AbstractShellCommand {
401 } else if (intent instanceof OpticalConnectivityIntent) { 410 } else if (intent instanceof OpticalConnectivityIntent) {
402 OpticalConnectivityIntent ci = (OpticalConnectivityIntent) intent; 411 OpticalConnectivityIntent ci = (OpticalConnectivityIntent) intent;
403 print(" src=%s, dst=%s", ci.getSrc(), ci.getDst()); 412 print(" src=%s, dst=%s", ci.getSrc(), ci.getDst());
413 + } else if (intent instanceof OpticalOduIntent) {
414 + OpticalOduIntent ci = (OpticalOduIntent) intent;
415 + print(" src=%s, dst=%s", ci.getSrc(), ci.getDst());
404 } 416 }
405 417
406 List<Intent> installable = service.getInstallableIntents(intent.key()); 418 List<Intent> installable = service.getInstallableIntents(intent.key());
......
1 +/*
2 + * Copyright 2016 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;
18 +
19 +import java.util.Set;
20 +
21 +import org.slf4j.Logger;
22 +import org.slf4j.LoggerFactory;
23 +
24 +/**
25 + * Collection of helper methods to convert various SignalTypes to OduSignalType, and to build OduSignalId.
26 + */
27 +public final class OduSignalUtils {
28 +
29 + private static final Logger log = LoggerFactory.getLogger(OduSignalUtils.class);
30 +
31 + // prohibit instantiation
32 + private OduSignalUtils() {}
33 +
34 + /**
35 + * Maps from OduClt SignalType to OduSignalType.
36 + *
37 + * @param cltSignalType OduClt port signal type
38 + * @return OduSignalType the result of mapping CltSignalType to OduSignalType
39 + */
40 + public static OduSignalType mappingCltSignalTypeToOduSignalType(CltSignalType cltSignalType) {
41 + switch (cltSignalType) {
42 + case CLT_1GBE:
43 + return OduSignalType.ODU0;
44 + case CLT_10GBE:
45 + return OduSignalType.ODU2;
46 + case CLT_40GBE:
47 + return OduSignalType.ODU3;
48 + case CLT_100GBE:
49 + return OduSignalType.ODU4;
50 + default:
51 + log.error("Unsupported CltSignalType {}", cltSignalType);
52 + return OduSignalType.ODU0;
53 + }
54 + }
55 +
56 + /**
57 + * Maps from OtuPort SignalType to OduSignalType.
58 + *
59 + * @param otuSignalType Otu port signal type
60 + * @return OduSignalType the result of mapping OtuSignalType to OduSignalType
61 + */
62 + public static OduSignalType mappingOtuSignalTypeToOduSignalType(OtuSignalType otuSignalType) {
63 + switch (otuSignalType) {
64 + case OTU2:
65 + return OduSignalType.ODU2;
66 + case OTU4:
67 + return OduSignalType.ODU4;
68 + default:
69 + log.error("Unsupported OtuSignalType {}", otuSignalType);
70 + return OduSignalType.ODU0;
71 + }
72 + }
73 +
74 + /**
75 + * Creates OduSignalId from OduSignalType and TributarySlots.
76 + * @param oduSignalType - OduSignalType
77 + * @param slots - a set of TributarySlots
78 + * @return OduSignalId
79 + */
80 + public static OduSignalId buildOduSignalId(OduSignalType oduSignalType, Set<TributarySlot> slots) {
81 + int tributaryPortNumber = (int) slots.stream().findFirst().get().index();
82 + int tributarySlotLen = oduSignalType.tributarySlots();
83 + byte[] tributarySlotBitmap = new byte[OduSignalId.TRIBUTARY_SLOT_BITMAP_SIZE];
84 +
85 + slots.forEach(ts -> tributarySlotBitmap[(byte) (ts.index() - 1) / 8] |= 0x1 << ((ts.index() - 1) % 8));
86 + return OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap);
87 + }
88 +
89 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 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 +package org.onosproject.net.intent;
17 +
18 +import com.google.common.annotations.Beta;
19 +import com.google.common.base.MoreObjects;
20 +import org.onosproject.core.ApplicationId;
21 +import org.onosproject.net.CltSignalType;
22 +import org.onosproject.net.ConnectPoint;
23 +
24 +import java.util.Collections;
25 +
26 +import static com.google.common.base.Preconditions.checkNotNull;
27 +
28 +/**
29 + * An optical layer intent between two OduClt ports - in an OTN Topology.
30 + * No traffic selector or traffic treatment are needed.
31 + */
32 +@Beta
33 +public final class OpticalOduIntent extends Intent {
34 + private final ConnectPoint src;
35 + private final ConnectPoint dst;
36 + private final CltSignalType signalType;
37 + private final boolean isBidirectional;
38 +
39 + /**
40 + * Creates an optical ODU intent between the specified connection points.
41 + *
42 + * @param appId application identification
43 + * @param key intent key
44 + * @param src the source transponder port
45 + * @param dst the destination transponder port
46 + * @param signalType CltSignalType signal type
47 + * @param isBidirectional indicate if intent is bidirectional
48 + * @param priority priority to use for flows from this intent
49 + */
50 + protected OpticalOduIntent(ApplicationId appId,
51 + Key key,
52 + ConnectPoint src,
53 + ConnectPoint dst,
54 + CltSignalType signalType,
55 + boolean isBidirectional,
56 + int priority) {
57 + super(appId, key, Collections.emptyList(), priority);
58 + this.src = checkNotNull(src);
59 + this.dst = checkNotNull(dst);
60 + this.signalType = checkNotNull(signalType);
61 + this.isBidirectional = isBidirectional;
62 + }
63 +
64 + /**
65 + * Returns a new optical ODU intent builder.
66 + *
67 + * @return intent builder
68 + */
69 + public static Builder builder() {
70 + return new Builder();
71 + }
72 +
73 +
74 + /**
75 + * Builder for optical ODU intents.
76 + */
77 + public static class Builder extends Intent.Builder {
78 + private ConnectPoint src;
79 + private ConnectPoint dst;
80 + private CltSignalType signalType;
81 + private boolean isBidirectional;
82 +
83 + @Override
84 + public Builder appId(ApplicationId appId) {
85 + return (Builder) super.appId(appId);
86 + }
87 +
88 + @Override
89 + public Builder key(Key key) {
90 + return (Builder) super.key(key);
91 + }
92 +
93 + @Override
94 + public Builder priority(int priority) {
95 + return (Builder) super.priority(priority);
96 + }
97 +
98 + /**
99 + * Sets the source for the intent that will be built.
100 + *
101 + * @param src source to use for built intent
102 + * @return this builder
103 + */
104 + public Builder src(ConnectPoint src) {
105 + this.src = src;
106 + return this;
107 + }
108 +
109 + /**
110 + * Sets the destination for the intent that will be built.
111 + *
112 + * @param dst dest to use for built intent
113 + * @return this builder
114 + */
115 + public Builder dst(ConnectPoint dst) {
116 + this.dst = dst;
117 + return this;
118 + }
119 +
120 + /**
121 + * Sets the ODU signal type for the intent that will be built.
122 + *
123 + * @param signalType signal type to use for built intent
124 + * @return this builder
125 + */
126 + public Builder signalType(CltSignalType signalType) {
127 + this.signalType = signalType;
128 + return this;
129 + }
130 +
131 + /**
132 + * Sets the directionality of the intent.
133 + *
134 + * @param isBidirectional true if bidirectional, false if unidirectional
135 + * @return this builder
136 + */
137 + public Builder bidirectional(boolean isBidirectional) {
138 + this.isBidirectional = isBidirectional;
139 + return this;
140 + }
141 +
142 + /**
143 + * Builds an optical ODU intent from the accumulated parameters.
144 + *
145 + * @return point to point intent
146 + */
147 + public OpticalOduIntent build() {
148 +
149 + return new OpticalOduIntent(
150 + appId,
151 + key,
152 + src,
153 + dst,
154 + signalType,
155 + isBidirectional,
156 + priority
157 + );
158 + }
159 + }
160 +
161 + /**
162 + * Constructor for serializer.
163 + */
164 + protected OpticalOduIntent() {
165 + super();
166 + this.src = null;
167 + this.dst = null;
168 + this.signalType = null;
169 + this.isBidirectional = false;
170 + }
171 +
172 + /**
173 + * Returns the source transponder port.
174 + *
175 + * @return source transponder port
176 + */
177 + public ConnectPoint getSrc() {
178 + return src;
179 + }
180 +
181 + /**
182 + * Returns the destination transponder port.
183 + *
184 + * @return source transponder port
185 + */
186 + public ConnectPoint getDst() {
187 + return dst;
188 + }
189 +
190 + /**
191 + * Returns the CltSignalType signal type.
192 + *
193 + * @return CltSignalType signal type
194 + */
195 + public CltSignalType getSignalType() {
196 + return signalType;
197 + }
198 +
199 + /**
200 + * Returns the directionality of the intent.
201 + *
202 + * @return true if bidirectional, false if unidirectional
203 + */
204 + public boolean isBidirectional() {
205 + return isBidirectional;
206 + }
207 +
208 + @Override
209 + public String toString() {
210 + return MoreObjects.toStringHelper(this)
211 + .add("id", id())
212 + .add("key", key())
213 + .add("appId", appId())
214 + .add("priority", priority())
215 + .add("resources", resources())
216 + .add("src", src)
217 + .add("dst", dst)
218 + .add("signalType", signalType)
219 + .add("isBidirectional", isBidirectional)
220 + .toString();
221 + }
222 +
223 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -36,6 +36,7 @@ import org.onosproject.net.OchPort; ...@@ -36,6 +36,7 @@ import org.onosproject.net.OchPort;
36 import org.onosproject.net.OduCltPort; 36 import org.onosproject.net.OduCltPort;
37 import org.onosproject.net.OduSignalId; 37 import org.onosproject.net.OduSignalId;
38 import org.onosproject.net.OduSignalType; 38 import org.onosproject.net.OduSignalType;
39 +import org.onosproject.net.OduSignalUtils;
39 import org.onosproject.net.Port; 40 import org.onosproject.net.Port;
40 import org.onosproject.net.TributarySlot; 41 import org.onosproject.net.TributarySlot;
41 import org.onosproject.net.behaviour.TributarySlotQuery; 42 import org.onosproject.net.behaviour.TributarySlotQuery;
...@@ -276,7 +277,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -276,7 +277,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
276 } 277 }
277 278
278 private List<Resource> availableSlotResources(ConnectPoint src, ConnectPoint dst, CltSignalType signalType) { 279 private List<Resource> availableSlotResources(ConnectPoint src, ConnectPoint dst, CltSignalType signalType) {
279 - OduSignalType oduSignalType = mappingCltSignalTypeToOduSignalType(signalType); 280 + OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(signalType);
280 int requestedTsNum = oduSignalType.tributarySlots(); 281 int requestedTsNum = oduSignalType.tributarySlots();
281 Set<TributarySlot> commonTributarySlots = findCommonTributarySlotsOnCps(src, dst); 282 Set<TributarySlot> commonTributarySlots = findCommonTributarySlotsOnCps(src, dst);
282 if (commonTributarySlots.isEmpty()) { 283 if (commonTributarySlots.isEmpty()) {
...@@ -339,7 +340,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -339,7 +340,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
339 CltSignalType signalType, 340 CltSignalType signalType,
340 boolean multiplexingSupported) { 341 boolean multiplexingSupported) {
341 342
342 - OduSignalType oduSignalType = mappingCltSignalTypeToOduSignalType(signalType); 343 + OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(signalType);
343 344
344 return Tools.stream(intentService.getIntents()) 345 return Tools.stream(intentService.getIntents())
345 .filter(x -> x instanceof OpticalConnectivityIntent) 346 .filter(x -> x instanceof OpticalConnectivityIntent)
...@@ -509,23 +510,25 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -509,23 +510,25 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
509 OduSignalType ochPortOduSignalType; 510 OduSignalType ochPortOduSignalType;
510 511
511 if (srcPort instanceof OduCltPort) { 512 if (srcPort instanceof OduCltPort) {
512 - oduCltPortOduSignalType = mappingCltSignalTypeToOduSignalType(((OduCltPort) srcPort).signalType()); 513 + oduCltPortOduSignalType =
514 + OduSignalUtils.mappingCltSignalTypeToOduSignalType(((OduCltPort) srcPort).signalType());
513 ochPortOduSignalType = ((OchPort) dstPort).signalType(); 515 ochPortOduSignalType = ((OchPort) dstPort).signalType();
514 516
515 selectorBuilder.add(Criteria.matchOduSignalType(oduCltPortOduSignalType)); 517 selectorBuilder.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));
516 // use Instruction of OduSignalId only in case of ODU Multiplexing 518 // use Instruction of OduSignalId only in case of ODU Multiplexing
517 if (oduCltPortOduSignalType != ochPortOduSignalType) { 519 if (oduCltPortOduSignalType != ochPortOduSignalType) {
518 - OduSignalId oduSignalId = buildOduSignalId(ochPortOduSignalType, slots); 520 + OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(ochPortOduSignalType, slots);
519 treatmentBuilder.add(Instructions.modL1OduSignalId(oduSignalId)); 521 treatmentBuilder.add(Instructions.modL1OduSignalId(oduSignalId));
520 } 522 }
521 } else { // srcPort is OchPort 523 } else { // srcPort is OchPort
522 - oduCltPortOduSignalType = mappingCltSignalTypeToOduSignalType(((OduCltPort) dstPort).signalType()); 524 + oduCltPortOduSignalType =
525 + OduSignalUtils.mappingCltSignalTypeToOduSignalType(((OduCltPort) dstPort).signalType());
523 ochPortOduSignalType = ((OchPort) srcPort).signalType(); 526 ochPortOduSignalType = ((OchPort) srcPort).signalType();
524 527
525 selectorBuilder.add(Criteria.matchOduSignalType(oduCltPortOduSignalType)); 528 selectorBuilder.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));
526 // use Criteria of OduSignalId only in case of ODU Multiplexing 529 // use Criteria of OduSignalId only in case of ODU Multiplexing
527 if (oduCltPortOduSignalType != ochPortOduSignalType) { 530 if (oduCltPortOduSignalType != ochPortOduSignalType) {
528 - OduSignalId oduSignalId = buildOduSignalId(ochPortOduSignalType, slots); 531 + OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(ochPortOduSignalType, slots);
529 selectorBuilder.add(Criteria.matchOduSignalId(oduSignalId)); 532 selectorBuilder.add(Criteria.matchOduSignalId(oduSignalId));
530 } 533 }
531 } 534 }
...@@ -544,19 +547,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -544,19 +547,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
544 return flowRule; 547 return flowRule;
545 } 548 }
546 549
547 - OduSignalId buildOduSignalId(OduSignalType ochPortSignalType, Set<TributarySlot> slots) {
548 - int tributaryPortNumber = findFirstTributarySlotIndex(slots);
549 - int tributarySlotLen = ochPortSignalType.tributarySlots();
550 - byte[] tributarySlotBitmap = new byte[OduSignalId.TRIBUTARY_SLOT_BITMAP_SIZE];
551 -
552 - slots.forEach(ts -> tributarySlotBitmap[(byte) (ts.index() - 1) / 8] |= 0x1 << ((ts.index() - 1) % 8));
553 - return OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap);
554 - }
555 -
556 - private int findFirstTributarySlotIndex(Set<TributarySlot> tributarySlots) {
557 - return (int) tributarySlots.stream().findFirst().get().index();
558 - }
559 -
560 private boolean isMultiplexingSupported(ConnectPoint cp) { 550 private boolean isMultiplexingSupported(ConnectPoint cp) {
561 Driver driver = driverService.getDriver(cp.deviceId()); 551 Driver driver = driverService.getDriver(cp.deviceId());
562 return driver != null 552 return driver != null
...@@ -565,28 +555,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -565,28 +555,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
565 } 555 }
566 556
567 /** 557 /**
568 - * Maps from Intent's OduClt SignalType to OduSignalType.
569 - *
570 - * @param cltSignalType OduClt port signal type
571 - * @return OduSignalType the result of mapping CltSignalType to OduSignalType
572 - */
573 - OduSignalType mappingCltSignalTypeToOduSignalType(CltSignalType cltSignalType) {
574 - switch (cltSignalType) {
575 - case CLT_1GBE:
576 - return OduSignalType.ODU0;
577 - case CLT_10GBE:
578 - return OduSignalType.ODU2;
579 - case CLT_40GBE:
580 - return OduSignalType.ODU3;
581 - case CLT_100GBE:
582 - return OduSignalType.ODU4;
583 - default:
584 - log.error("Unsupported CltSignalType {}", cltSignalType);
585 - return OduSignalType.ODU0;
586 - }
587 - }
588 -
589 - /**
590 * Finds the common TributarySlots available on the two connect points. 558 * Finds the common TributarySlots available on the two connect points.
591 * 559 *
592 * @param src source connect point 560 * @param src source connect point
......
1 +/*
2 + * Copyright 2016 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 +package org.onosproject.net.intent.impl.compiler;
17 +
18 +
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.core.CoreService;
26 +import org.onosproject.net.ConnectPoint;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.Link;
29 +import org.onosproject.net.LinkKey;
30 +import org.onosproject.net.OduCltPort;
31 +import org.onosproject.net.OduSignalId;
32 +import org.onosproject.net.OduSignalType;
33 +import org.onosproject.net.OduSignalUtils;
34 +import org.onosproject.net.OtuPort;
35 +import org.onosproject.net.Path;
36 +import org.onosproject.net.Port;
37 +import org.onosproject.net.TributarySlot;
38 +import org.onosproject.net.device.DeviceService;
39 +import org.onosproject.net.flow.DefaultFlowRule;
40 +import org.onosproject.net.flow.DefaultTrafficSelector;
41 +import org.onosproject.net.flow.DefaultTrafficTreatment;
42 +import org.onosproject.net.flow.FlowRule;
43 +import org.onosproject.net.flow.TrafficSelector;
44 +import org.onosproject.net.flow.TrafficTreatment;
45 +import org.onosproject.net.flow.criteria.Criteria;
46 +import org.onosproject.net.flow.instructions.Instructions;
47 +import org.onosproject.net.intent.FlowRuleIntent;
48 +import org.onosproject.net.intent.Intent;
49 +import org.onosproject.net.intent.IntentCompiler;
50 +import org.onosproject.net.intent.IntentExtensionService;
51 +import org.onosproject.net.intent.OpticalOduIntent;
52 +import org.onosproject.net.intent.impl.IntentCompilationException;
53 +import org.onosproject.net.resource.Resource;
54 +import org.onosproject.net.resource.ResourceService;
55 +import org.onosproject.net.resource.ResourceAllocation;
56 +import org.onosproject.net.resource.Resources;
57 +import org.onosproject.net.topology.LinkWeight;
58 +import org.onosproject.net.topology.Topology;
59 +import org.onosproject.net.topology.TopologyService;
60 +import org.slf4j.Logger;
61 +import org.slf4j.LoggerFactory;
62 +
63 +import com.google.common.collect.ImmutableList;
64 +import com.google.common.collect.ImmutableSet;
65 +import com.google.common.collect.Lists;
66 +import com.google.common.collect.Sets;
67 +
68 +import java.util.ArrayList;
69 +import java.util.Collections;
70 +import java.util.HashMap;
71 +import java.util.LinkedList;
72 +import java.util.List;
73 +import java.util.Map;
74 +import java.util.Set;
75 +import java.util.stream.Collectors;
76 +import java.util.stream.Stream;
77 +
78 +import static com.google.common.base.Preconditions.checkArgument;
79 +import static org.onosproject.net.LinkKey.linkKey;
80 +
81 +/**
82 + * An intent compiler for {@link org.onosproject.net.intent.OpticalOduIntent}.
83 + */
84 +@Component(immediate = true)
85 +public class OpticalOduIntentCompiler implements IntentCompiler<OpticalOduIntent> {
86 +
87 + private static final Logger log = LoggerFactory.getLogger(OpticalOduIntentCompiler.class);
88 +
89 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 + protected IntentExtensionService intentManager;
91 +
92 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 + protected CoreService coreService;
94 +
95 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 + protected TopologyService topologyService;
97 +
98 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 + protected DeviceService deviceService;
100 +
101 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 + protected ResourceService resourceService;
103 +
104 + private ApplicationId appId;
105 +
106 + @Activate
107 + public void activate() {
108 + appId = coreService.registerApplication("org.onosproject.net.intent");
109 + intentManager.registerCompiler(OpticalOduIntent.class, this);
110 + }
111 +
112 + @Deactivate
113 + public void deactivate() {
114 + intentManager.unregisterCompiler(OpticalOduIntent.class);
115 + }
116 +
117 + @Override
118 + public List<Intent> compile(OpticalOduIntent intent, List<Intent> installable) {
119 + // Check if ports are OduClt ports
120 + ConnectPoint src = intent.getSrc();
121 + ConnectPoint dst = intent.getDst();
122 + Port srcPort = deviceService.getPort(src.deviceId(), src.port());
123 + Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
124 + checkArgument(srcPort instanceof OduCltPort);
125 + checkArgument(dstPort instanceof OduCltPort);
126 +
127 + log.debug("Compiling optical ODU intent between {} and {}", src, dst);
128 +
129 + // Release of intent resources here is only a temporary solution for handling the
130 + // case of recompiling due to intent restoration (when intent state is FAILED).
131 + // TODO: try to release intent resources in IntentManager.
132 + resourceService.release(intent.id());
133 +
134 + // Check OduClt ports availability
135 + Resource srcPortResource = Resources.discrete(src.deviceId(), src.port()).resource();
136 + Resource dstPortResource = Resources.discrete(dst.deviceId(), dst.port()).resource();
137 + // If ports are not available, compilation fails
138 + if (!Stream.of(srcPortResource, dstPortResource).allMatch(resourceService::isAvailable)) {
139 + throw new IntentCompilationException("Ports for the intent are not available. Intent: " + intent);
140 + }
141 + List<Resource> intentResources = new ArrayList<>();
142 + intentResources.add(srcPortResource);
143 + intentResources.add(dstPortResource);
144 +
145 + // Calculate available light paths
146 + Set<Path> paths = getOpticalPaths(intent);
147 +
148 + if (paths.isEmpty()) {
149 + throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
150 + }
151 +
152 + // Use first path that can be successfully reserved
153 + for (Path path : paths) {
154 +
155 + // Find available Tributary Slots on both directions of path
156 + Map<LinkKey, Set<TributarySlot>> slotsMap = findAvailableTributarySlots(intent, path);
157 + if (slotsMap.isEmpty()) {
158 + continue;
159 + }
160 + List<Resource> tributarySlotResources = convertToResources(slotsMap);
161 + if (!tributarySlotResources.stream().allMatch(resourceService::isAvailable)) {
162 + continue;
163 + }
164 +
165 + intentResources.addAll(tributarySlotResources);
166 +
167 + allocateResources(intent, intentResources);
168 +
169 + List<FlowRule> rules = new LinkedList<>();
170 +
171 + // Create rules for forward and reverse path
172 + rules = createRules(intent, intent.getSrc(), intent.getDst(), path, slotsMap, false);
173 + if (intent.isBidirectional()) {
174 + rules.addAll(createRules(intent, intent.getDst(), intent.getSrc(), path, slotsMap, true));
175 + }
176 +
177 + return Collections.singletonList(new FlowRuleIntent(appId,
178 + rules, ImmutableSet.copyOf(path.links())));
179 + }
180 +
181 + throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
182 + }
183 +
184 + /**
185 + * Find available TributarySlots across path.
186 + *
187 + * @param intent
188 + * @param path path in OTU topology
189 + * @return Map of Linkey and Set of available TributarySlots on its ports
190 + */
191 + private Map<LinkKey, Set<TributarySlot>> findAvailableTributarySlots(OpticalOduIntent intent, Path path) {
192 + Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(path.links().size());
193 + for (int i = 0; i < path.links().size(); i++) {
194 + LinkKey link = linkKey(path.links().get(i));
195 + linkRequest.add(link);
196 + }
197 +
198 + return findTributarySlots(intent, linkRequest);
199 + }
200 +
201 + private List<Resource> convertToResources(Map<LinkKey, Set<TributarySlot>> slotsMap) {
202 + // Same TributarySlots are used for both directions
203 + Set<Resource> resources = slotsMap.entrySet().stream()
204 + .flatMap(x -> x.getValue()
205 + .stream()
206 + .flatMap(ts-> Stream.of(
207 + Resources.discrete(x.getKey().src().deviceId(), x.getKey().src().port())
208 + .resource().child(ts),
209 + Resources.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port())
210 + .resource().child(ts))))
211 + .collect(Collectors.toSet());
212 + return (ImmutableList.copyOf(resources));
213 + }
214 +
215 + private void allocateResources(Intent intent, List<Resource> resources) {
216 + // reserve all of required resources
217 + List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), resources);
218 + if (allocations.isEmpty()) {
219 + log.info("Resource allocation for {} failed (resource request: {})", intent, resources);
220 + throw new IntentCompilationException("Unable to allocate resources: " + resources);
221 + }
222 + }
223 +
224 + private Map<LinkKey, Set<TributarySlot>> findTributarySlots(OpticalOduIntent intent, Set<LinkKey> links) {
225 + OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
226 + int requestedTsNum = oduSignalType.tributarySlots();
227 +
228 + Map<LinkKey, Set<TributarySlot>> slotsMap = new HashMap<>();
229 + for (LinkKey link : links) {
230 + Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst());
231 + if (common.isEmpty() || (common.size() < requestedTsNum)) {
232 + log.debug("Failed to find TributarySlots on link {} requestedTsNum={}", link, requestedTsNum);
233 + return Collections.emptyMap(); // failed to find enough available TributarySlots on a link
234 + }
235 + slotsMap.put(link, common.stream()
236 + .limit(requestedTsNum)
237 + .collect(Collectors.toSet()));
238 + }
239 + return slotsMap;
240 + }
241 +
242 + /**
243 + * Calculates optical paths in OTU topology.
244 + *
245 + * @param intent optical ODU intent
246 + * @return set of paths in OTU topology
247 + */
248 + private Set<Path> getOpticalPaths(OpticalOduIntent intent) {
249 + // Route in OTU topology
250 + Topology topology = topologyService.currentTopology();
251 +
252 + LinkWeight weight = edge -> {
253 + // Disregard inactive or non-optical links
254 + if (edge.link().state() == Link.State.INACTIVE) {
255 + return -1;
256 + }
257 + if (edge.link().type() != Link.Type.OPTICAL) {
258 + return -1;
259 + }
260 + // Find path with available TributarySlots resources
261 + if (!isAvailableTributarySlots(intent, edge.link())) {
262 + return -1;
263 + }
264 + return 1;
265 + };
266 +
267 + ConnectPoint start = intent.getSrc();
268 + ConnectPoint end = intent.getDst();
269 +
270 + return topologyService.getPaths(topology, start.deviceId(), end.deviceId(), weight);
271 + }
272 +
273 + private boolean isAvailableTributarySlots(OpticalOduIntent intent, Link link) {
274 + OduSignalType oduSignalType = OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
275 + int requestedTsNum = oduSignalType.tributarySlots();
276 +
277 + Set<TributarySlot> common = findCommonTributarySlotsOnCps(link.src(), link.dst());
278 + if (common.isEmpty() || (common.size() < requestedTsNum)) {
279 + log.debug("Not enough available TributarySlots on link {} requestedTsNum={}", link, requestedTsNum);
280 + return false;
281 + }
282 + return true;
283 + }
284 +
285 + /**
286 + * Create rules for the forward (or the reverse) path of the intent.
287 + *
288 + * @param intent OpticalOduIntent intent
289 + * @param path path found for intent
290 + * @param slotsMap Map of LinkKey and TributarySlots resources
291 + * @return list of flow rules
292 + */
293 + private List<FlowRule> createRules(OpticalOduIntent intent, ConnectPoint src, ConnectPoint dst,
294 + Path path, Map<LinkKey, Set<TributarySlot>> slotsMap, boolean reverse) {
295 + // Build the ingress OTN rule
296 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
297 + selector.matchInPort(src.port());
298 + OduSignalType oduCltPortOduSignalType =
299 + OduSignalUtils.mappingCltSignalTypeToOduSignalType(intent.getSignalType());
300 + selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));
301 +
302 + List<FlowRule> rules = new LinkedList<>();
303 + ConnectPoint current = src;
304 +
305 + List<Link> links = ((!reverse) ? path.links() : Lists.reverse(path.links()));
306 +
307 + for (Link link : links) {
308 + Set<TributarySlot> slots = slotsMap.get(linkKey(link));
309 + OtuPort otuPort = (OtuPort) (deviceService.getPort(link.src().deviceId(), link.src().port()));
310 + OduSignalType otuPortOduSignalType =
311 + OduSignalUtils.mappingOtuSignalTypeToOduSignalType(otuPort.signalType());
312 +
313 + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
314 + OduSignalId oduSignalId = null;
315 + // use Instruction of OduSignalId only in case of ODU Multiplexing
316 + if (oduCltPortOduSignalType != otuPortOduSignalType) {
317 + oduSignalId = OduSignalUtils.buildOduSignalId(otuPortOduSignalType, slots);
318 + treat.add(Instructions.modL1OduSignalId(oduSignalId));
319 + }
320 + ConnectPoint next = ((!reverse) ? link.src() : link.dst());
321 + treat.setOutput(next.port());
322 +
323 + FlowRule rule = createFlowRule(intent, current.deviceId(), selector.build(), treat.build());
324 + rules.add(rule);
325 +
326 + current = ((!reverse) ? link.dst() : link.src());
327 + selector = DefaultTrafficSelector.builder();
328 + selector.matchInPort(current.port());
329 + selector.add(Criteria.matchOduSignalType(oduCltPortOduSignalType));
330 + // use Criteria of OduSignalId only in case of ODU Multiplexing
331 + if (oduCltPortOduSignalType != otuPortOduSignalType) {
332 + selector.add(Criteria.matchOduSignalId(oduSignalId));
333 + }
334 + }
335 +
336 + // Build the egress OTN rule
337 + TrafficTreatment.Builder treatLast = DefaultTrafficTreatment.builder();
338 + treatLast.setOutput(dst.port());
339 +
340 + FlowRule rule = createFlowRule(intent, dst.deviceId(), selector.build(), treatLast.build());
341 + rules.add(rule);
342 +
343 + return rules;
344 + }
345 +
346 + private FlowRule createFlowRule(OpticalOduIntent intent, DeviceId deviceId,
347 + TrafficSelector selector, TrafficTreatment treat) {
348 + return DefaultFlowRule.builder()
349 + .forDevice(deviceId)
350 + .withSelector(selector)
351 + .withTreatment(treat)
352 + .withPriority(intent.priority())
353 + .fromApp(appId)
354 + .makePermanent()
355 + .build();
356 + }
357 +
358 + /**
359 + * Finds the common TributarySlots available on the two connect points.
360 + *
361 + * @param src source connect point
362 + * @param dst dest connect point
363 + * @return set of common TributarySlots on both connect points
364 + */
365 + Set<TributarySlot> findCommonTributarySlotsOnCps(ConnectPoint src, ConnectPoint dst) {
366 + Set<TributarySlot> forward = findTributarySlotsOnCp(src);
367 + Set<TributarySlot> backward = findTributarySlotsOnCp(dst);
368 + return Sets.intersection(forward, backward);
369 + }
370 +
371 + /**
372 + * Finds the TributarySlots available on the connect point.
373 + *
374 + * @param cp connect point
375 + * @return set of TributarySlots available on the connect point
376 + */
377 + Set<TributarySlot> findTributarySlotsOnCp(ConnectPoint cp) {
378 + return resourceService.getAvailableResourceValues(
379 + Resources.discrete(cp.deviceId(), cp.port()).id(),
380 + TributarySlot.class);
381 + }
382 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -38,6 +38,7 @@ import org.onosproject.net.OchSignal; ...@@ -38,6 +38,7 @@ import org.onosproject.net.OchSignal;
38 import org.onosproject.net.OduCltPort; 38 import org.onosproject.net.OduCltPort;
39 import org.onosproject.net.OduSignalId; 39 import org.onosproject.net.OduSignalId;
40 import org.onosproject.net.OduSignalType; 40 import org.onosproject.net.OduSignalType;
41 +import org.onosproject.net.OduSignalUtils;
41 import org.onosproject.net.Port; 42 import org.onosproject.net.Port;
42 import org.onosproject.net.PortNumber; 43 import org.onosproject.net.PortNumber;
43 import org.onosproject.net.TributarySlot; 44 import org.onosproject.net.TributarySlot;
...@@ -429,7 +430,7 @@ public class OpticalCircuitIntentCompilerTest { ...@@ -429,7 +430,7 @@ public class OpticalCircuitIntentCompilerTest {
429 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder(); 430 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
430 Set<TributarySlot> slots = new HashSet<>(); 431 Set<TributarySlot> slots = new HashSet<>();
431 slots.add(TributarySlot.of(1)); 432 slots.add(TributarySlot.of(1));
432 - OduSignalId oduSignalId = sut.buildOduSignalId(D1P2.signalType(), slots); 433 + OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(D1P2.signalType(), slots);
433 treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId)); 434 treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
434 treatmentBuilder1.setOutput(ochSrcCP.port()); 435 treatmentBuilder1.setOutput(ochSrcCP.port());
435 assertThat(rule1.treatment(), is(treatmentBuilder1.build())); 436 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
......
1 +/*
2 + * Copyright 2016 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 +package org.onosproject.net.intent.impl.compiler;
17 +
18 +import org.junit.After;
19 +import org.junit.Before;
20 +import org.junit.Test;
21 +import org.onlab.packet.ChassisId;
22 +import org.onosproject.TestApplicationId;
23 +import org.onosproject.core.ApplicationId;
24 +import org.onosproject.core.CoreService;
25 +import org.onosproject.core.IdGenerator;
26 +import org.onosproject.net.Annotations;
27 +import org.onosproject.net.DefaultAnnotations;
28 +import org.onosproject.net.CltSignalType;
29 +import org.onosproject.net.ConnectPoint;
30 +import org.onosproject.net.DefaultDevice;
31 +import org.onosproject.net.DefaultLink;
32 +import org.onosproject.net.DefaultPath;
33 +import org.onosproject.net.Device;
34 +import org.onosproject.net.DeviceId;
35 +import org.onosproject.net.Link;
36 +import org.onosproject.net.OduCltPort;
37 +import org.onosproject.net.OduSignalId;
38 +import org.onosproject.net.OduSignalType;
39 +import org.onosproject.net.OduSignalUtils;
40 +import org.onosproject.net.OtuPort;
41 +import org.onosproject.net.OtuSignalType;
42 +import org.onosproject.net.Path;
43 +import org.onosproject.net.Port;
44 +import org.onosproject.net.PortNumber;
45 +import org.onosproject.net.TributarySlot;
46 +import org.onosproject.net.flow.DefaultTrafficSelector;
47 +import org.onosproject.net.flow.DefaultTrafficTreatment;
48 +import org.onosproject.net.flow.FlowRule;
49 +import org.onosproject.net.flow.TrafficSelector;
50 +import org.onosproject.net.flow.TrafficTreatment;
51 +import org.onosproject.net.flow.criteria.Criteria;
52 +import org.onosproject.net.flow.instructions.Instructions;
53 +import org.onosproject.net.intent.FlowRuleIntent;
54 +import org.onosproject.net.intent.Intent;
55 +import org.onosproject.net.intent.IntentExtensionService;
56 +import org.onosproject.net.intent.Key;
57 +import org.onosproject.net.intent.MockIdGenerator;
58 +import org.onosproject.net.intent.OpticalOduIntent;
59 +import org.onosproject.net.provider.ProviderId;
60 +import org.onosproject.net.topology.LinkWeight;
61 +import org.onosproject.net.topology.Topology;
62 +import org.onosproject.net.topology.TopologyServiceAdapter;
63 +import org.onosproject.net.device.DeviceServiceAdapter;
64 +
65 +import com.google.common.collect.ImmutableList;
66 +import com.google.common.collect.Sets;
67 +
68 +import java.util.Arrays;
69 +import java.util.Collection;
70 +import java.util.Collections;
71 +import java.util.HashSet;
72 +import java.util.List;
73 +import java.util.Set;
74 +
75 +import static org.easymock.EasyMock.createMock;
76 +import static org.easymock.EasyMock.expect;
77 +import static org.easymock.EasyMock.replay;
78 +import static org.hamcrest.MatcherAssert.assertThat;
79 +import static org.hamcrest.Matchers.hasSize;
80 +import static org.hamcrest.Matchers.is;
81 +import static org.junit.Assert.assertEquals;
82 +import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
83 +import static org.onosproject.net.AnnotationKeys.PORT_NAME;
84 +import static org.onosproject.net.Device.Type.OTN;
85 +import static org.onosproject.net.DeviceId.deviceId;
86 +import static org.onosproject.net.Link.Type.OPTICAL;
87 +import static org.onosproject.net.NetTestTools.APP_ID;
88 +import static org.onosproject.net.NetTestTools.PID;
89 +
90 +public class OpticalOduIntentCompilerTest {
91 +
92 + private static final String DEV1 = "of:1";
93 + private static final String DEV2 = "of:2";
94 + private static final String DEV3 = "of:3";
95 +
96 + static final Key KEY1 = Key.of(5L, APP_ID);
97 +
98 + private static final String STATIC_TRUE = "true";
99 + private static final String PNAME = "p2";
100 +
101 + private CoreService coreService;
102 + private IntentExtensionService intentExtensionService;
103 + private final IdGenerator idGenerator = new MockIdGenerator();
104 + private OpticalOduIntentCompiler sut;
105 +
106 + private final ApplicationId appId = new TestApplicationId("test");
107 + private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), OTN,
108 + "m", "h", "s", "n", new ChassisId(0L));
109 + private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), OTN,
110 + "m", "h", "s", "n", new ChassisId(1L));
111 + private static Device device3 = new DefaultDevice(ProviderId.NONE, deviceId(DEV3), OTN,
112 + "m", "h", "s", "n", new ChassisId(2L));
113 +
114 + private static Annotations annotations1 = DefaultAnnotations.builder().set(STATIC_PORT, STATIC_TRUE).build();
115 + private static Annotations annotations2 = DefaultAnnotations.builder().set(PORT_NAME, PNAME).build();
116 +
117 + // OduClt ports with signalType=1GBE
118 + private static final OduCltPort D1P1 =
119 + new OduCltPort(device1, PortNumber.portNumber(1), true, CltSignalType.CLT_1GBE, annotations1);
120 + private static final OduCltPort D3P2 =
121 + new OduCltPort(device3, PortNumber.portNumber(2), true, CltSignalType.CLT_1GBE, annotations1);
122 +
123 + // Otu ports with signalType=ODU2
124 + private static final OtuPort D1P2 =
125 + new OtuPort(device1, PortNumber.portNumber(2), true, OtuSignalType.OTU2, annotations2);
126 + private static final OtuPort D2P1 =
127 + new OtuPort(device2, PortNumber.portNumber(1), true, OtuSignalType.OTU2, annotations2);
128 + private static final OtuPort D2P2 =
129 + new OtuPort(device2, PortNumber.portNumber(2), true, OtuSignalType.OTU2, annotations2);
130 + private static final OtuPort D3P1 =
131 + new OtuPort(device3, PortNumber.portNumber(1), true, OtuSignalType.OTU2, annotations2);
132 +
133 + // OduClt ports with signalType=10GBE
134 + private static final OduCltPort D1P3 =
135 + new OduCltPort(device1, PortNumber.portNumber(3), true, CltSignalType.CLT_10GBE, annotations1);
136 + private static final OduCltPort D3P3 =
137 + new OduCltPort(device3, PortNumber.portNumber(3), true, CltSignalType.CLT_10GBE, annotations1);
138 +
139 + // OduCltPort ConnectPoints
140 + private final ConnectPoint d1p1 = new ConnectPoint(device1.id(), D1P1.number());
141 + private final ConnectPoint d1p3 = new ConnectPoint(device1.id(), D1P3.number());
142 + private final ConnectPoint d3p2 = new ConnectPoint(device3.id(), D3P2.number());
143 + private final ConnectPoint d3p3 = new ConnectPoint(device3.id(), D3P3.number());
144 +
145 + // OtuPort ConnectPoints
146 + private final ConnectPoint d1p2 = new ConnectPoint(device1.id(), D1P2.number());
147 + private final ConnectPoint d2p1 = new ConnectPoint(device2.id(), D2P1.number());
148 + private final ConnectPoint d2p2 = new ConnectPoint(device2.id(), D2P2.number());
149 + private final ConnectPoint d3p1 = new ConnectPoint(device3.id(), D3P1.number());
150 +
151 + private final List<Link> links = Arrays.asList(
152 + DefaultLink.builder().providerId(PID).src(d1p2).dst(d2p1).type(OPTICAL).build(),
153 + DefaultLink.builder().providerId(PID).src(d2p2).dst(d3p1).type(OPTICAL).build()
154 + );
155 + private final Path path = new DefaultPath(PID, links, 3);
156 +
157 + private OpticalOduIntent intent;
158 +
159 + /**
160 + * Mocks the topology service to give paths in the test.
161 + */
162 + private class MockTopologyService extends TopologyServiceAdapter {
163 + Set<Path> paths = Sets.newHashSet(path);
164 +
165 + @Override
166 + public Topology currentTopology() {
167 + return null;
168 + }
169 +
170 + @Override
171 + public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
172 + return paths;
173 + }
174 + }
175 +
176 + /**
177 + * Mocks the device service so that devices and ports appear available in the test.
178 + */
179 + private static class MockDeviceService extends DeviceServiceAdapter {
180 + @Override
181 + public boolean isAvailable(DeviceId deviceId) {
182 + return true;
183 + }
184 +
185 + @Override
186 + public List<Port> getPorts(DeviceId deviceId) {
187 + if (deviceId.equals(deviceId(DEV1))) {
188 + return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3);
189 + }
190 +
191 + if (deviceId.equals(deviceId(DEV2))) {
192 + return ImmutableList.of((Port) D2P1, (Port) D2P2);
193 + }
194 +
195 + if (deviceId.equals(deviceId(DEV3))) {
196 + return ImmutableList.of((Port) D3P1, (Port) D3P2, (Port) D3P3);
197 + }
198 +
199 + return Collections.emptyList();
200 + }
201 +
202 + @Override
203 + public Port getPort(DeviceId deviceId, PortNumber portNumber) {
204 + if (deviceId.equals(deviceId(DEV1))) {
205 + switch (portNumber.toString()) {
206 + case "1":
207 + return (Port) D1P1;
208 + case "2":
209 + return (Port) D1P2;
210 + case "3":
211 + return (Port) D1P3;
212 + default:
213 + return null;
214 + }
215 + }
216 + if (deviceId.equals(deviceId(DEV2))) {
217 + switch (portNumber.toString()) {
218 + case "1":
219 + return (Port) D2P1;
220 + case "2":
221 + return (Port) D2P2;
222 + default:
223 + return null;
224 + }
225 + }
226 + if (deviceId.equals(deviceId(DEV3))) {
227 + switch (portNumber.toString()) {
228 + case "1":
229 + return (Port) D3P1;
230 + case "2":
231 + return (Port) D3P2;
232 + case "3":
233 + return (Port) D3P3;
234 + default:
235 + return null;
236 + }
237 + }
238 + return null;
239 + }
240 + }
241 +
242 + @Before
243 + public void setUp() {
244 + sut = new OpticalOduIntentCompiler();
245 + coreService = createMock(CoreService.class);
246 + expect(coreService.registerApplication("org.onosproject.net.intent"))
247 + .andReturn(appId);
248 + sut.coreService = coreService;
249 + sut.deviceService = new MockDeviceService();
250 + sut.resourceService = new MockResourceService();
251 + sut.topologyService = new MockTopologyService();
252 +
253 + Intent.bindIdGenerator(idGenerator);
254 +
255 + intentExtensionService = createMock(IntentExtensionService.class);
256 + intentExtensionService.registerCompiler(OpticalOduIntent.class, sut);
257 + intentExtensionService.unregisterCompiler(OpticalOduIntent.class);
258 + sut.intentManager = intentExtensionService;
259 +
260 + replay(coreService, intentExtensionService);
261 + }
262 +
263 + @After
264 + public void tearDown() {
265 + Intent.unbindIdGenerator(idGenerator);
266 + }
267 +
268 + /**
269 + * Tests compile of OpticalOduIntent with allocation of TributarySlots.
270 + * Compile two ODUCLT ports (with CLT_1GBE), over OTU ports (with OTU2):
271 + * - only one TributarySlot is used
272 + */
273 + @Test
274 + public void test1GbeMultiplexOverOdu2() {
275 +
276 + intent = OpticalOduIntent.builder()
277 + .appId(APP_ID)
278 + .key(KEY1)
279 + .src(d1p1)
280 + .dst(d3p2)
281 + .signalType(D1P1.signalType())
282 + .bidirectional(false)
283 + .build();
284 +
285 + sut.activate();
286 +
287 + List<Intent> compiled = sut.compile(intent, Collections.emptyList());
288 + assertThat(compiled, hasSize(1));
289 +
290 + Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
291 +
292 + // 1st Device
293 + FlowRule rule1 = rules.stream()
294 + .filter(x -> x.deviceId().equals(device1.id()))
295 + .findFirst()
296 + .get();
297 + // validate SRC selector
298 + TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
299 + selectorBuilder1.matchInPort(d1p1.port());
300 + selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
301 + assertThat(rule1.selector(), is(selectorBuilder1.build()));
302 +
303 + // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
304 + TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
305 + Set<TributarySlot> slots = new HashSet<>();
306 + slots.add(TributarySlot.of(1));
307 + OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(OduSignalType.ODU2, slots);
308 + treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
309 + treatmentBuilder1.setOutput(d1p2.port());
310 + assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
311 +
312 + // 2nd Device
313 + FlowRule rule2 = rules.stream()
314 + .filter(x -> x.deviceId().equals(device2.id()))
315 + .findFirst()
316 + .get();
317 + // validate SRC selector
318 + TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
319 + selectorBuilder2.matchInPort(d2p1.port());
320 + selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
321 + selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId));
322 + assertThat(rule2.selector(), is(selectorBuilder2.build()));
323 +
324 + // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
325 + TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
326 + treatmentBuilder2.add(Instructions.modL1OduSignalId(oduSignalId));
327 + treatmentBuilder2.setOutput(d2p2.port());
328 + assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
329 +
330 +
331 + // 3rd Device
332 + FlowRule rule3 = rules.stream()
333 + .filter(x -> x.deviceId().equals(device3.id()))
334 + .findFirst()
335 + .get();
336 + // validate DST selector (with OduSignalId, where the same TributarySlot is used)
337 + TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
338 + selectorBuilder3.matchInPort(d3p1.port());
339 + selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
340 + selectorBuilder3.add(Criteria.matchOduSignalId(oduSignalId));
341 + assertThat(rule3.selector(), is(selectorBuilder3.build()));
342 +
343 + // validate DST treatment
344 + assertThat(rule3.treatment(), is(
345 + DefaultTrafficTreatment.builder().setOutput(d3p2.port()).build()
346 + ));
347 +
348 + rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
349 + intent.priority(), rule.priority()));
350 +
351 + sut.deactivate();
352 + }
353 +
354 + /**
355 + * Tests compile of OpticalOduIntent with allocation of TributarySlots.
356 + * Compile two ODUCLT ports (with CLT_10GBE), over OTU ports (with OTU2):
357 + * - All TributarySlots are used
358 + */
359 + @Test
360 + public void test10GbeMultiplexOverOdu2() {
361 +
362 + intent = OpticalOduIntent.builder()
363 + .appId(APP_ID)
364 + .key(KEY1)
365 + .src(d1p3)
366 + .dst(d3p3)
367 + .signalType(D1P3.signalType())
368 + .bidirectional(false)
369 + .build();
370 +
371 + sut.activate();
372 +
373 + List<Intent> compiled = sut.compile(intent, Collections.emptyList());
374 + assertThat(compiled, hasSize(1));
375 +
376 + Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
377 +
378 + // 1st Device
379 + FlowRule rule1 = rules.stream()
380 + .filter(x -> x.deviceId().equals(device1.id()))
381 + .findFirst()
382 + .get();
383 + // validate SRC selector
384 + TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
385 + selectorBuilder1.matchInPort(d1p3.port());
386 + selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
387 + assertThat(rule1.selector(), is(selectorBuilder1.build()));
388 +
389 + // validate SRC treatment (without OduSignalId - all TributarySlots are used)
390 + TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
391 + treatmentBuilder1.setOutput(d1p2.port());
392 + assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
393 +
394 + // 2nd Device
395 + FlowRule rule2 = rules.stream()
396 + .filter(x -> x.deviceId().equals(device2.id()))
397 + .findFirst()
398 + .get();
399 + // validate SRC selector
400 + TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
401 + selectorBuilder2.matchInPort(d2p1.port());
402 + selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
403 + assertThat(rule2.selector(), is(selectorBuilder2.build()));
404 +
405 + // validate SRC treatment (without OduSignalId - all TributarySlots are used)
406 + TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
407 + treatmentBuilder2.setOutput(d2p2.port());
408 + assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
409 +
410 +
411 + // 3rd Device
412 + FlowRule rule3 = rules.stream()
413 + .filter(x -> x.deviceId().equals(device3.id()))
414 + .findFirst()
415 + .get();
416 + // validate DST selector (without OduSignalId - all TributarySlots are used)
417 + TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
418 + selectorBuilder3.matchInPort(d3p1.port());
419 + selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
420 + assertThat(rule3.selector(), is(selectorBuilder3.build()));
421 +
422 + // validate DST treatment
423 + assertThat(rule3.treatment(), is(
424 + DefaultTrafficTreatment.builder().setOutput(d3p3.port()).build()
425 + ));
426 +
427 + rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
428 + intent.priority(), rule.priority()));
429 +
430 + sut.deactivate();
431 + }
432 +
433 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -163,6 +163,7 @@ import org.onosproject.net.intent.MplsPathIntent; ...@@ -163,6 +163,7 @@ import org.onosproject.net.intent.MplsPathIntent;
163 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 163 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
164 import org.onosproject.net.intent.OpticalCircuitIntent; 164 import org.onosproject.net.intent.OpticalCircuitIntent;
165 import org.onosproject.net.intent.OpticalConnectivityIntent; 165 import org.onosproject.net.intent.OpticalConnectivityIntent;
166 +import org.onosproject.net.intent.OpticalOduIntent;
166 import org.onosproject.net.intent.OpticalPathIntent; 167 import org.onosproject.net.intent.OpticalPathIntent;
167 import org.onosproject.net.intent.PathIntent; 168 import org.onosproject.net.intent.PathIntent;
168 import org.onosproject.net.intent.PointToPointIntent; 169 import org.onosproject.net.intent.PointToPointIntent;
...@@ -422,6 +423,7 @@ public final class KryoNamespaces { ...@@ -422,6 +423,7 @@ public final class KryoNamespaces {
422 OpticalConnectivityIntent.class, 423 OpticalConnectivityIntent.class,
423 OpticalPathIntent.class, 424 OpticalPathIntent.class,
424 OpticalCircuitIntent.class, 425 OpticalCircuitIntent.class,
426 + OpticalOduIntent.class,
425 DiscreteResource.class, 427 DiscreteResource.class,
426 ContinuousResource.class, 428 ContinuousResource.class,
427 DiscreteResourceId.class, 429 DiscreteResourceId.class,
......