yjimmyy
Committed by Gerrit Code Review

Add Oplink attenuation extension and channel power drivers.

Change-Id: I2558595b03cbb6cc58237dc48b8a03e83357fe1f
...@@ -61,7 +61,8 @@ public final class ExtensionTreatmentType { ...@@ -61,7 +61,8 @@ public final class ExtensionTreatmentType {
61 NICIRA_ENCAP_ETH_SRC(121), 61 NICIRA_ENCAP_ETH_SRC(121),
62 NICIRA_ENCAP_ETH_DST(122), 62 NICIRA_ENCAP_ETH_DST(122),
63 NICIRA_ENCAP_ETH_TYPE(123), 63 NICIRA_ENCAP_ETH_TYPE(123),
64 - BMV2_ACTION(128); 64 + BMV2_ACTION(128),
65 + OPLINK_ATTENUATION(130);
65 66
66 private ExtensionTreatmentType type; 67 private ExtensionTreatmentType type;
67 68
......
...@@ -32,6 +32,7 @@ import org.onosproject.driver.extensions.NiciraSetNshSpi; ...@@ -32,6 +32,7 @@ import org.onosproject.driver.extensions.NiciraSetNshSpi;
32 import org.onosproject.driver.extensions.NiciraSetTunnelDst; 32 import org.onosproject.driver.extensions.NiciraSetTunnelDst;
33 import org.onosproject.driver.extensions.OfdpaMatchVlanVid; 33 import org.onosproject.driver.extensions.OfdpaMatchVlanVid;
34 import org.onosproject.driver.extensions.OfdpaSetVlanVid; 34 import org.onosproject.driver.extensions.OfdpaSetVlanVid;
35 +import org.onosproject.driver.extensions.OplinkAttenuation;
35 import org.onosproject.driver.extensions.codec.MoveExtensionTreatmentCodec; 36 import org.onosproject.driver.extensions.codec.MoveExtensionTreatmentCodec;
36 import org.onosproject.driver.extensions.codec.NiciraMatchNshSiCodec; 37 import org.onosproject.driver.extensions.codec.NiciraMatchNshSiCodec;
37 import org.onosproject.driver.extensions.codec.NiciraMatchNshSpiCodec; 38 import org.onosproject.driver.extensions.codec.NiciraMatchNshSpiCodec;
...@@ -43,6 +44,7 @@ import org.onosproject.driver.extensions.codec.NiciraSetNshSpiCodec; ...@@ -43,6 +44,7 @@ import org.onosproject.driver.extensions.codec.NiciraSetNshSpiCodec;
43 import org.onosproject.driver.extensions.codec.NiciraSetTunnelDstCodec; 44 import org.onosproject.driver.extensions.codec.NiciraSetTunnelDstCodec;
44 import org.onosproject.driver.extensions.codec.OfdpaMatchVlanVidCodec; 45 import org.onosproject.driver.extensions.codec.OfdpaMatchVlanVidCodec;
45 import org.onosproject.driver.extensions.codec.OfdpaSetVlanVidCodec; 46 import org.onosproject.driver.extensions.codec.OfdpaSetVlanVidCodec;
47 +import org.onosproject.driver.extensions.codec.OplinkAttenuationCodec;
46 import org.slf4j.Logger; 48 import org.slf4j.Logger;
47 49
48 import static org.slf4j.LoggerFactory.getLogger; 50 import static org.slf4j.LoggerFactory.getLogger;
...@@ -71,6 +73,7 @@ public class DefaultCodecRegister { ...@@ -71,6 +73,7 @@ public class DefaultCodecRegister {
71 codecService.registerCodec(NiciraSetNshContextHeader.class, new NiciraSetNshContextHeaderCodec()); 73 codecService.registerCodec(NiciraSetNshContextHeader.class, new NiciraSetNshContextHeaderCodec());
72 codecService.registerCodec(OfdpaMatchVlanVid.class, new OfdpaMatchVlanVidCodec()); 74 codecService.registerCodec(OfdpaMatchVlanVid.class, new OfdpaMatchVlanVidCodec());
73 codecService.registerCodec(OfdpaSetVlanVid.class, new OfdpaSetVlanVidCodec()); 75 codecService.registerCodec(OfdpaSetVlanVid.class, new OfdpaSetVlanVidCodec());
76 + codecService.registerCodec(OplinkAttenuation.class, new OplinkAttenuationCodec());
74 log.info("Registered default driver codecs."); 77 log.info("Registered default driver codecs.");
75 } 78 }
76 79
...@@ -87,6 +90,7 @@ public class DefaultCodecRegister { ...@@ -87,6 +90,7 @@ public class DefaultCodecRegister {
87 codecService.unregisterCodec(NiciraSetNshContextHeader.class); 90 codecService.unregisterCodec(NiciraSetNshContextHeader.class);
88 codecService.unregisterCodec(OfdpaMatchVlanVid.class); 91 codecService.unregisterCodec(OfdpaMatchVlanVid.class);
89 codecService.unregisterCodec(OfdpaSetVlanVid.class); 92 codecService.unregisterCodec(OfdpaSetVlanVid.class);
93 + codecService.unregisterCodec(OplinkAttenuation.class);
90 log.info("Unregistered default driver codecs."); 94 log.info("Unregistered default driver codecs.");
91 } 95 }
92 } 96 }
......
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.driver.extensions;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import com.google.common.collect.Maps;
21 +import org.onlab.util.KryoNamespace;
22 +import org.onosproject.net.flow.AbstractExtension;
23 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
24 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
25 +
26 +import java.util.Map;
27 +import java.util.Objects;
28 +
29 +/**
30 + * Instruction for Oplink channel attenuation.
31 + */
32 +public class OplinkAttenuation extends AbstractExtension implements ExtensionTreatment {
33 + private static final String KEY_ATT = "attenuation";
34 +
35 + private int attenuation;
36 +
37 + private final KryoNamespace appKryo = new KryoNamespace.Builder()
38 + .register(Map.class)
39 + .build("OplinkAttenuation");
40 +
41 + /**
42 + * Creates new attenuation instruction.
43 + * @param attenuation attenuation value
44 + */
45 + public OplinkAttenuation(int attenuation) {
46 + this.attenuation = attenuation;
47 + }
48 +
49 + /**
50 + * Gets the attenuation value.
51 + * @return attenuation
52 + */
53 + public int getAttenuation() {
54 + return attenuation;
55 + }
56 +
57 + /**
58 + * Modify the attenuation value.
59 + * @param attenuation new attenuation value
60 + */
61 + public void setAttenuation(int attenuation) {
62 + this.attenuation = attenuation;
63 + }
64 +
65 + @Override
66 + public ExtensionTreatmentType type() {
67 + return ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type();
68 + }
69 +
70 + @Override
71 + public byte[] serialize() {
72 + Map<String, Object> values = Maps.newHashMap();
73 + values.put(KEY_ATT, attenuation);
74 + return appKryo.serialize(values);
75 + }
76 +
77 + @Override
78 + public void deserialize(byte[] data) {
79 + Map<String, Object> values = appKryo.deserialize(data);
80 + attenuation = (int) values.get(KEY_ATT);
81 + }
82 +
83 + @Override
84 + public int hashCode() {
85 + return Objects.hash(attenuation);
86 + }
87 +
88 + @Override
89 + public boolean equals(Object obj) {
90 + if (this == obj) {
91 + return true;
92 + }
93 + if (obj instanceof OplinkAttenuation) {
94 + OplinkAttenuation that = (OplinkAttenuation) obj;
95 + return Objects.equals(attenuation, that.attenuation);
96 + }
97 + return false;
98 + }
99 +
100 + @Override
101 + public String toString() {
102 + return MoreObjects.toStringHelper(getClass())
103 + .add(KEY_ATT, attenuation)
104 + .toString();
105 + }
106 +}
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.driver.extensions;
18 +
19 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
20 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
21 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
22 +import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
23 +import org.projectfloodlight.openflow.protocol.OFActionType;
24 +import org.projectfloodlight.openflow.protocol.OFFactory;
25 +import org.projectfloodlight.openflow.protocol.action.OFAction;
26 +import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
27 +import org.projectfloodlight.openflow.protocol.action.OFActionOplinkAtt;
28 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
29 +import org.projectfloodlight.openflow.types.U32;
30 +
31 +/**
32 + * Interpreter for Oplink OpenFlow treatment extensions.
33 + */
34 +public class OplinkExtensionTreatmentInterpreter extends AbstractHandlerBehaviour
35 + implements ExtensionTreatmentInterpreter {
36 +
37 + private static final long ATTENUATION_EXP = 0xff000088L;
38 +
39 + @Override
40 + public boolean supported(ExtensionTreatmentType extensionTreatmentType) {
41 + if (extensionTreatmentType.equals(
42 + ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type())) {
43 + return true;
44 + }
45 + return false;
46 + }
47 +
48 + @Override
49 + public OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment) {
50 + ExtensionTreatmentType type = extensionTreatment.type();
51 + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type())) {
52 + int att = ((OplinkAttenuation) extensionTreatment).getAttenuation();
53 + return factory.actions().oplinkAtt(factory.oxms().ochSigatt(U32.ofRaw(att)));
54 + }
55 + return null;
56 + }
57 +
58 + @Override
59 + public ExtensionTreatment mapAction(OFAction action) throws UnsupportedOperationException {
60 + if (action.getType().equals(OFActionType.EXPERIMENTER)) {
61 + OFActionExperimenter actionExp = (OFActionExperimenter) action;
62 + if (actionExp.getExperimenter() == ATTENUATION_EXP) {
63 + OFActionOplinkAtt actionAtt = (OFActionOplinkAtt) action;
64 + return new OplinkAttenuation(((OFOxm<U32>) actionAtt.getField()).getValue().getRaw());
65 + }
66 + }
67 + return null;
68 + }
69 +}
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.driver.extensions.codec;
18 +
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.onosproject.codec.CodecContext;
21 +import org.onosproject.codec.JsonCodec;
22 +import org.onosproject.driver.extensions.OplinkAttenuation;
23 +
24 +import static org.onlab.util.Tools.nullIsIllegal;
25 +
26 +/**
27 + * JSON Codec for OplinkAttenuation class.
28 + */
29 +public class OplinkAttenuationCodec extends JsonCodec<OplinkAttenuation> {
30 + private static final String ATTENUATION = "attenuation";
31 + private static final String MISSING_ATT = "Missing value for \"attenuation\"";
32 +
33 + @Override
34 + public OplinkAttenuation decode(ObjectNode json, CodecContext context) {
35 + if (json == null || !json.isObject()) {
36 + return null;
37 + }
38 + String att = nullIsIllegal(json.get(ATTENUATION), MISSING_ATT).asText();
39 + return new OplinkAttenuation(Integer.valueOf(att));
40 + }
41 +}
1 +package org.onosproject.driver.optical.extensions;
2 +
3 +import com.fasterxml.jackson.databind.node.ObjectNode;
4 +import org.onlab.osgi.DefaultServiceDirectory;
5 +import org.onlab.osgi.ServiceDirectory;
6 +import org.onosproject.codec.CodecContext;
7 +import org.onosproject.codec.CodecService;
8 +import org.onosproject.codec.ExtensionTreatmentCodec;
9 +import org.onosproject.driver.extensions.OplinkAttenuation;
10 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
11 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
12 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
13 +
14 +import static org.onlab.util.Tools.nullIsIllegal;
15 +
16 +/**
17 + * Codec for Oplink extensions.
18 + */
19 +public class OplinkExtensionTreatmentCodec extends AbstractHandlerBehaviour
20 + implements ExtensionTreatmentCodec {
21 +
22 + private static final String TYPE = "type";
23 + private static final String MISSING_TYPE = "Missing extension type";
24 + private static final String UNSUPPORTED_TYPE = "Extension type is not supported: ";
25 +
26 + @Override
27 + public ExtensionTreatment decode(ObjectNode objectNode, CodecContext context) {
28 + if (objectNode == null || !objectNode.isObject()) {
29 + return null;
30 + }
31 +
32 + int typeInt = nullIsIllegal(objectNode.get(TYPE), MISSING_TYPE).asInt();
33 + ExtensionTreatmentType type = new ExtensionTreatmentType(typeInt);
34 +
35 + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type())) {
36 + return decodeTreatment(objectNode, context, OplinkAttenuation.class);
37 + } else {
38 + throw new UnsupportedOperationException(UNSUPPORTED_TYPE + type.toString());
39 + }
40 + }
41 +
42 + private <T extends ExtensionTreatment> ExtensionTreatment decodeTreatment(
43 + ObjectNode objectNode, CodecContext context, Class<T> entityClass) {
44 + if (context == null) {
45 + ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
46 + return serviceDirectory.get(CodecService.class).getCodec(entityClass).decode(objectNode, null);
47 + } else {
48 + return context.codec(entityClass).decode(objectNode, context);
49 + }
50 + }
51 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +/**
17 + * Implementations of extension behaviours for optical devices.
18 + */
19 +package org.onosproject.driver.optical.extensions;
...@@ -41,6 +41,7 @@ import org.onosproject.net.device.DefaultPortDescription; ...@@ -41,6 +41,7 @@ import org.onosproject.net.device.DefaultPortDescription;
41 import org.onosproject.net.device.DeviceService; 41 import org.onosproject.net.device.DeviceService;
42 import org.onosproject.net.device.PortDescription; 42 import org.onosproject.net.device.PortDescription;
43 import org.onosproject.net.link.DefaultLinkDescription; 43 import org.onosproject.net.link.DefaultLinkDescription;
44 +import org.onosproject.net.link.LinkService;
44 import org.onosproject.net.optical.OpticalAnnotations; 45 import org.onosproject.net.optical.OpticalAnnotations;
45 import org.onosproject.openflow.controller.Dpid; 46 import org.onosproject.openflow.controller.Dpid;
46 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; 47 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
...@@ -190,17 +191,19 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic ...@@ -190,17 +191,19 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic
190 public final void sendMsg(OFMessage m) { 191 public final void sendMsg(OFMessage m) {
191 List<OFMessage> messages = new ArrayList<>(); 192 List<OFMessage> messages = new ArrayList<>();
192 messages.add(m); 193 messages.add(m);
194 +
193 if (m.getType() == OFType.STATS_REQUEST) { 195 if (m.getType() == OFType.STATS_REQUEST) {
194 OFStatsRequest sr = (OFStatsRequest) m; 196 OFStatsRequest sr = (OFStatsRequest) m;
195 log.debug("OPLK ROADM rebuilding stats request type {}", sr.getStatsType()); 197 log.debug("OPLK ROADM rebuilding stats request type {}", sr.getStatsType());
196 switch (sr.getStatsType()) { 198 switch (sr.getStatsType()) {
197 case PORT: 199 case PORT:
198 - //replace with Oplink experiment stats message to get the port current power 200 + //add Oplink experiment stats message to get the port's current power
199 OFOplinkPortPowerRequest powerRequest = this.factory().buildOplinkPortPowerRequest() 201 OFOplinkPortPowerRequest powerRequest = this.factory().buildOplinkPortPowerRequest()
200 .setXid(sr.getXid()) 202 .setXid(sr.getXid())
201 .setFlags(sr.getFlags()) 203 .setFlags(sr.getFlags())
202 .build(); 204 .build();
203 messages.add(powerRequest); 205 messages.add(powerRequest);
206 + // add experiment message to get adjacent ports
204 OFExpPortAdjacencyRequest adjacencyRequest = this.factory().buildExpPortAdjacencyRequest() 207 OFExpPortAdjacencyRequest adjacencyRequest = this.factory().buildExpPortAdjacencyRequest()
205 .setXid(sr.getXid()) 208 .setXid(sr.getXid())
206 .setFlags(sr.getFlags()) 209 .setFlags(sr.getFlags())
...@@ -335,7 +338,7 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic ...@@ -335,7 +338,7 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic
335 338
336 private void addLink(PortNumber portNumber, OplinkPortAdjacency neighbor) { 339 private void addLink(PortNumber portNumber, OplinkPortAdjacency neighbor) {
337 ConnectPoint dst = new ConnectPoint(handler().data().deviceId(), portNumber); 340 ConnectPoint dst = new ConnectPoint(handler().data().deviceId(), portNumber);
338 - ConnectPoint src = new ConnectPoint(neighbor.getDeviceId(), neighbor.portNumber); 341 + ConnectPoint src = new ConnectPoint(neighbor.getDeviceId(), neighbor.getPort());
339 OpticalAdjacencyLinkService adService = 342 OpticalAdjacencyLinkService adService =
340 this.handler().get(OpticalAdjacencyLinkService.class); 343 this.handler().get(OpticalAdjacencyLinkService.class);
341 adService.linkDetected(new DefaultLinkDescription(src, dst, Link.Type.OPTICAL)); 344 adService.linkDetected(new DefaultLinkDescription(src, dst, Link.Type.OPTICAL));
...@@ -344,10 +347,14 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic ...@@ -344,10 +347,14 @@ public class OplinkRoadm extends AbstractOpenFlowSwitch implements OpenFlowOptic
344 // Remove incoming link with port if there are any. 347 // Remove incoming link with port if there are any.
345 private void removeLink(PortNumber portNumber) { 348 private void removeLink(PortNumber portNumber) {
346 ConnectPoint dst = new ConnectPoint(handler().data().deviceId(), portNumber); 349 ConnectPoint dst = new ConnectPoint(handler().data().deviceId(), portNumber);
350 + // Check so only incoming links are removed
351 + Set<Link> links = this.handler().get(LinkService.class).getIngressLinks(dst);
352 + if (!links.isEmpty()) {
347 OpticalAdjacencyLinkService adService = 353 OpticalAdjacencyLinkService adService =
348 this.handler().get(OpticalAdjacencyLinkService.class); 354 this.handler().get(OpticalAdjacencyLinkService.class);
349 adService.linksVanished(dst); 355 adService.linksVanished(dst);
350 } 356 }
357 + }
351 358
352 private class OplinkPortAdjacency { 359 private class OplinkPortAdjacency {
353 private DeviceId deviceId; 360 private DeviceId deviceId;
......
...@@ -16,14 +16,31 @@ ...@@ -16,14 +16,31 @@
16 16
17 package org.onosproject.driver.optical.power; 17 package org.onosproject.driver.optical.power;
18 18
19 +import java.util.List;
19 import java.util.Optional; 20 import java.util.Optional;
20 21
22 +import org.onosproject.driver.extensions.OplinkAttenuation;
23 +import org.onosproject.net.OchSignal;
21 import org.onosproject.net.driver.AbstractHandlerBehaviour; 24 import org.onosproject.net.driver.AbstractHandlerBehaviour;
22 import org.onosproject.net.Direction; 25 import org.onosproject.net.Direction;
23 import org.onosproject.net.Port; 26 import org.onosproject.net.Port;
24 import org.onosproject.net.PortNumber; 27 import org.onosproject.net.PortNumber;
25 import org.onosproject.net.behaviour.PowerConfig; 28 import org.onosproject.net.behaviour.PowerConfig;
26 import org.onosproject.net.device.DeviceService; 29 import org.onosproject.net.device.DeviceService;
30 +import org.onosproject.net.flow.DefaultFlowRule;
31 +import org.onosproject.net.flow.DefaultTrafficTreatment;
32 +import org.onosproject.net.flow.FlowEntry;
33 +import org.onosproject.net.flow.FlowRule;
34 +import org.onosproject.net.flow.FlowRuleService;
35 +import org.onosproject.net.flow.TrafficSelector;
36 +import org.onosproject.net.flow.TrafficTreatment;
37 +import org.onosproject.net.flow.criteria.Criterion;
38 +import org.onosproject.net.flow.criteria.OchSignalCriterion;
39 +import org.onosproject.net.flow.criteria.PortCriterion;
40 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
41 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
42 +import org.onosproject.net.flow.instructions.Instruction;
43 +import org.onosproject.net.flow.instructions.Instructions;
27 import org.onosproject.net.optical.OpticalAnnotations; 44 import org.onosproject.net.optical.OpticalAnnotations;
28 import org.onosproject.openflow.controller.Dpid; 45 import org.onosproject.openflow.controller.Dpid;
29 import org.onosproject.openflow.controller.OpenFlowController; 46 import org.onosproject.openflow.controller.OpenFlowController;
...@@ -40,9 +57,28 @@ import org.slf4j.LoggerFactory; ...@@ -40,9 +57,28 @@ import org.slf4j.LoggerFactory;
40 */ 57 */
41 58
42 public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour 59 public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour
43 - implements PowerConfig<Direction> { 60 + implements PowerConfig<Object> {
61 +
44 protected final Logger log = LoggerFactory.getLogger(getClass()); 62 protected final Logger log = LoggerFactory.getLogger(getClass());
45 63
64 + // Component type
65 + private enum Type {
66 + NONE,
67 + PORT,
68 + CHANNEL
69 + }
70 +
71 + // Get the type if component is valid
72 + private Type getType(Object component) {
73 + if (component == null || component instanceof Direction) {
74 + return Type.PORT;
75 + } else if (component instanceof OchSignal) {
76 + return Type.CHANNEL;
77 + } else {
78 + return Type.NONE;
79 + }
80 + }
81 +
46 private OpenFlowSwitch getOpenFlowDevice() { 82 private OpenFlowSwitch getOpenFlowDevice() {
47 final OpenFlowController controller = this.handler().get(OpenFlowController.class); 83 final OpenFlowController controller = this.handler().get(OpenFlowController.class);
48 final Dpid dpid = Dpid.dpid(this.data().deviceId().uri()); 84 final Dpid dpid = Dpid.dpid(this.data().deviceId().uri());
...@@ -54,41 +90,177 @@ public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour ...@@ -54,41 +90,177 @@ public class OplinkRoadmPowerConfig extends AbstractHandlerBehaviour
54 } 90 }
55 } 91 }
56 92
93 + // Find matching flow on device
94 + private FlowEntry findFlow(PortNumber portNum, OchSignal och) {
95 + FlowRuleService service = this.handler().get(FlowRuleService.class);
96 + Iterable<FlowEntry> flowEntries = service.getFlowEntries(this.data().deviceId());
97 +
98 + // Return first matching flow
99 + for (FlowEntry entry : flowEntries) {
100 + TrafficSelector selector = entry.selector();
101 + OchSignalCriterion entrySigid =
102 + (OchSignalCriterion) selector.getCriterion(Criterion.Type.OCH_SIGID);
103 + if (entrySigid != null && och.equals(entrySigid.lambda())) {
104 + PortCriterion entryPort =
105 + (PortCriterion) selector.getCriterion(Criterion.Type.IN_PORT);
106 + if (entryPort != null && portNum.equals(entryPort.port())) {
107 + return entry;
108 + }
109 + }
110 + }
111 + log.warn("No matching flow found");
112 + return null;
113 + }
114 +
57 @Override 115 @Override
58 - public Optional<Long> getTargetPower(PortNumber portNum, Direction component) { 116 + public Optional<Long> getTargetPower(PortNumber portNum, Object component) {
117 + Long returnVal = null;
118 + // Check if switch is connected, otherwise do not return value in store,
119 + // which is obsolete.
120 + if (getOpenFlowDevice() != null) {
121 + switch (getType(component)) {
122 + case PORT:
59 // Will be implemented in the future. 123 // Will be implemented in the future.
60 - return Optional.empty(); 124 + break;
125 + case CHANNEL:
126 + returnVal = getChannelAttenuation(portNum, (OchSignal) component);
127 + break;
128 + default:
129 + break;
130 + }
131 + }
132 + return Optional.ofNullable(returnVal);
61 } 133 }
62 134
63 @Override 135 @Override
64 - public Optional<Long> currentPower(PortNumber portNum, Direction component) { 136 + public Optional<Long> currentPower(PortNumber portNum, Object component) {
65 Long returnVal = null; 137 Long returnVal = null;
66 // Check if switch is connected, otherwise do not return value in store, 138 // Check if switch is connected, otherwise do not return value in store,
67 // which is obsolete. 139 // which is obsolete.
68 if (getOpenFlowDevice() != null) { 140 if (getOpenFlowDevice() != null) {
141 + switch (getType(component)) {
142 + case PORT:
143 + returnVal = getCurrentPortPower(portNum);
144 + break;
145 + case CHANNEL:
146 + returnVal = getCurrentChannelPower(portNum, (OchSignal) component);
147 + break;
148 + default:
149 + break;
150 + }
151 + }
152 + return Optional.ofNullable(returnVal);
153 + }
154 +
155 + @Override
156 + public void setTargetPower(PortNumber portNum, Object component, long power) {
157 + if (getOpenFlowDevice() != null) {
158 + switch (getType(component)) {
159 + case PORT:
160 + setTargetPortPower(portNum, power);
161 + break;
162 + case CHANNEL:
163 + setChannelAttenuation(portNum, (OchSignal) component, power);
164 + break;
165 + default:
166 + break;
167 + }
168 + } else {
169 + log.warn("OpenFlow handshaker driver not found or device is not connected");
170 + }
171 + }
172 +
173 + private Long getChannelAttenuation(PortNumber portNum, OchSignal och) {
174 + FlowEntry flowEntry = findFlow(portNum, och);
175 + if (flowEntry != null) {
176 + List<Instruction> instructions = flowEntry.treatment().allInstructions();
177 + for (Instruction ins : instructions) {
178 + if (ins.type() == Instruction.Type.EXTENSION) {
179 + ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
180 + if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
181 + return (long) ((OplinkAttenuation) ext).getAttenuation();
182 + }
183 + }
184 + }
185 + }
186 + return null;
187 + }
188 +
189 + private Long getCurrentPortPower(PortNumber portNum) {
69 DeviceService deviceService = this.handler().get(DeviceService.class); 190 DeviceService deviceService = this.handler().get(DeviceService.class);
70 Port port = deviceService.getPort(this.data().deviceId(), portNum); 191 Port port = deviceService.getPort(this.data().deviceId(), portNum);
71 if (port != null) { 192 if (port != null) {
72 String currentPower = port.annotations().value(OpticalAnnotations.CURRENT_POWER); 193 String currentPower = port.annotations().value(OpticalAnnotations.CURRENT_POWER);
73 if (currentPower != null) { 194 if (currentPower != null) {
74 - returnVal = Long.valueOf(currentPower); 195 + return Long.valueOf(currentPower);
75 } 196 }
76 } 197 }
198 + return null;
77 } 199 }
78 - return Optional.ofNullable(returnVal); 200 +
201 + private Long getCurrentChannelPower(PortNumber portNum, OchSignal och) {
202 + FlowEntry flowEntry = findFlow(portNum, och);
203 + if (flowEntry != null) {
204 + // TODO put somewhere else if possible
205 + // We put channel power in packets
206 + return flowEntry.packets();
207 + }
208 + return null;
79 } 209 }
80 210
81 - @Override 211 + private void setTargetPortPower(PortNumber portNum, long power) {
82 - public void setTargetPower(PortNumber portNum, Direction component, long power) {
83 OpenFlowSwitch device = getOpenFlowDevice(); 212 OpenFlowSwitch device = getOpenFlowDevice();
84 - if (device != null) {
85 device.sendMsg(device.factory().buildOplinkPortPowerSet() 213 device.sendMsg(device.factory().buildOplinkPortPowerSet()
86 .setXid(0) 214 .setXid(0)
87 .setPort((int) portNum.toLong()) 215 .setPort((int) portNum.toLong())
88 .setPowerValue((int) power) 216 .setPowerValue((int) power)
89 .build()); 217 .build());
218 + }
219 +
220 + private void setChannelAttenuation(PortNumber portNum, OchSignal och, long power) {
221 + FlowEntry flowEntry = findFlow(portNum, och);
222 + if (flowEntry != null) {
223 + List<Instruction> instructions = flowEntry.treatment().allInstructions();
224 + for (Instruction ins : instructions) {
225 + if (ins.type() == Instruction.Type.EXTENSION) {
226 + ExtensionTreatment ext = ((Instructions.ExtensionInstructionWrapper) ins).extensionInstruction();
227 + if (ext.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.OPLINK_ATTENUATION.type()) {
228 + ((OplinkAttenuation) ext).setAttenuation((int) power);
229 + FlowRuleService service = this.handler().get(FlowRuleService.class);
230 + service.applyFlowRules(flowEntry);
231 + return;
232 + }
233 + }
234 + }
235 + addAttenuation(flowEntry, power);
90 } else { 236 } else {
91 - log.warn("OpenFlow handshaker driver not found or device is not connected"); 237 + log.warn("Target channel power not set");
92 } 238 }
93 } 239 }
240 +
241 + // Replace flow with new flow containing Oplink attenuation extension instruction. Also resets
242 + // metrics.
243 + private void addAttenuation(FlowEntry flowEntry, long power) {
244 + FlowRule.Builder flowBuilder = new DefaultFlowRule.Builder();
245 + flowBuilder.withCookie(flowEntry.id().value());
246 + flowBuilder.withPriority(flowEntry.priority());
247 + flowBuilder.forDevice(flowEntry.deviceId());
248 + flowBuilder.forTable(flowEntry.tableId());
249 + if (flowEntry.isPermanent()) {
250 + flowBuilder.makePermanent();
251 + } else {
252 + flowBuilder.makeTemporary(flowEntry.timeout());
253 + }
254 +
255 + flowBuilder.withSelector(flowEntry.selector());
256 +
257 + // Copy original instructions and add attenuation instruction
258 + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
259 + flowEntry.treatment().allInstructions().forEach(ins -> treatmentBuilder.add(ins));
260 + treatmentBuilder.add(Instructions.extension(new OplinkAttenuation((int) power), this.data().deviceId()));
261 + flowBuilder.withTreatment(treatmentBuilder.build());
262 +
263 + FlowRuleService service = this.handler().get(FlowRuleService.class);
264 + service.applyFlowRules(flowBuilder.build());
265 + }
94 } 266 }
......
...@@ -58,6 +58,10 @@ ...@@ -58,6 +58,10 @@
58 impl="org.onosproject.net.optical.DefaultOpticalDevice"/> 58 impl="org.onosproject.net.optical.DefaultOpticalDevice"/>
59 <behaviour api="org.onosproject.net.behaviour.PowerConfig" 59 <behaviour api="org.onosproject.net.behaviour.PowerConfig"
60 impl="org.onosproject.driver.optical.power.OplinkRoadmPowerConfig"/> 60 impl="org.onosproject.driver.optical.power.OplinkRoadmPowerConfig"/>
61 + <behaviour api="org.onosproject.codec.ExtensionTreatmentCodec"
62 + impl="org.onosproject.driver.optical.extensions.OplinkExtensionTreatmentCodec"/>
63 + <behaviour api="org.onosproject.openflow.controller.ExtensionTreatmentInterpreter"
64 + impl="org.onosproject.driver.extensions.OplinkExtensionTreatmentInterpreter"/>
61 </driver> 65 </driver>
62 66
63 </drivers> 67 </drivers>
......