blob: 92847f957a71910b865da18544267c935496f4e0 [file] [log] [blame]
MaoLu819fde22017-04-20 17:17:49 -07001/*
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
17package org.onosproject.drivers.oplink;
18
19import com.google.common.collect.Range;
20import org.apache.commons.configuration.HierarchicalConfiguration;
21import org.onosproject.driver.extensions.OplinkAttenuation;
22import org.onosproject.net.Direction;
23import org.onosproject.net.OchSignal;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.behaviour.PowerConfig;
26import org.onosproject.net.driver.AbstractHandlerBehaviour;
27import org.onosproject.net.flow.DefaultFlowRule;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.FlowEntry;
30import org.onosproject.net.flow.FlowRuleService;
31import org.onosproject.net.flow.TrafficTreatment;
32import org.slf4j.Logger;
33
34import java.util.Optional;
35
36import static org.onosproject.drivers.oplink.OplinkOpticalUtility.MAX_ATTENUATION;
37import static org.onosproject.drivers.oplink.OplinkOpticalUtility.MIN_ATTENUATION;
38import static org.onosproject.drivers.oplink.OplinkOpticalUtility.POWER_MULTIPLIER;
39import static org.slf4j.LoggerFactory.getLogger;
40import static org.onosproject.drivers.oplink.OplinkNetconfUtility.*;
41
42/**
43 * Get current or target port/channel power from an Oplink optical netconf device.
44 * Set target port power or channel attenuation to an optical netconf device.
45 */
46public class OplinkOpticalPowerConfig<T> extends AbstractHandlerBehaviour
47 implements PowerConfig<T> {
48
49 // key
50 public static final String KEY_CHNUM = "wavelength-number";
51 public static final String KEY_CHPWR = "wavelength-power";
52 public static final String KEY_CHSTATS = "wavelength-stats";
53 public static final String KEY_OCMSTATS = "ocm-stats";
54 public static final String KEY_PORTDIRECT_RX = "rx";
55 public static final String KEY_PORTDIRECT_TX = "tx";
56 public static final String KEY_PORTTARPWR = "port-target-power";
57 public static final String KEY_PORTCURPWR = "port-current-power";
58 public static final String KEY_PORTPROPERTY = "port-property";
59 public static final String KEY_PORTPWRCAPMINRX = "port-power-capability-min-rx";
60 public static final String KEY_PORTPWRCAPMAXRX = "port-power-capability-max-rx";
61 public static final String KEY_PORTPWRCAPMINTX = "port-power-capability-min-tx";
62 public static final String KEY_PORTPWRCAPMAXTX = "port-power-capability-max-tx";
63 public static final String KEY_PORTS_PORT = String.format("%s.%s", KEY_DATA_PORTS, KEY_PORT);
64 public static final String KEY_PORTS_PORT_PROPERTY = String.format("%s.%s", KEY_PORTS_PORT, KEY_PORTPROPERTY);
65 // log
66 private static final Logger log = getLogger(OplinkOpticalPowerConfig.class);
67
68
69 @Override
70 public Optional<Long> getTargetPower(PortNumber port, T component) {
71 return Optional.ofNullable(acquireTargetPower(port, component));
72 }
73
74 @Override
75 public void setTargetPower(PortNumber port, T component, long power) {
76 if (component instanceof OchSignal) {
77 setChannelTargetPower(port, (OchSignal) component, power);
78 } else {
79 setPortTargetPower(port, power);
80 }
81 }
82
83 @Override
84 public Optional<Long> currentPower(PortNumber port, T component) {
85 return Optional.ofNullable(acquireCurrentPower(port, component));
86 }
87
88 @Override
89 public Optional<Range<Long>> getTargetPowerRange(PortNumber port, T component) {
90 return Optional.ofNullable(getTxPowerRange(port, component));
91 }
92
93 @Override
94 public Optional<Range<Long>> getInputPowerRange(PortNumber port, T component) {
95 return Optional.ofNullable(getRxPowerRange(port, component));
96 }
97
98 private String getPortPowerFilter(PortNumber port, String selection) {
99 return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
100 .append(xmlOpen(KEY_PORTS))
101 .append(xml(KEY_PORTID, Long.toString(port.toLong())))
102 .append(xmlOpen(KEY_PORT))
103 .append(xmlEmpty(selection))
104 .append(xmlClose(KEY_PORT))
105 .append(xmlClose(KEY_PORTS))
106 .append(xmlClose(KEY_OPENOPTICALDEV))
107 .toString();
108 }
109
110 private String getChannelPowerFilter(PortNumber port, OchSignal channel) {
111 return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
112 .append(xmlOpen(KEY_PORTS))
113 .append(xml(KEY_PORTID, Long.toString(port.toLong())))
114 .append(xmlOpen(KEY_PORT))
115 .append(xmlOpen(KEY_OCMSTATS))
116 .append(xml(KEY_CHNUM, Integer.toString(channel.spacingMultiplier())))
117 .append(xmlEmpty(KEY_CHSTATS))
118 .append(xmlClose(KEY_OCMSTATS))
119 .append(xmlClose(KEY_PORT))
120 .append(xmlClose(KEY_PORTS))
121 .append(xmlClose(KEY_OPENOPTICALDEV))
122 .toString();
123 }
124
125 private String getChannelAttenuationFilter(PortNumber port, OchSignal channel) {
126 return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
127 .append(xmlOpen(KEY_CONNS))
128 .append(xml(KEY_CONNID, Integer.toString(channel.spacingMultiplier())))
129 .append(xmlEmpty(KEY_CHATT))
130 .append(xmlClose(KEY_CONNS))
131 .append(xmlClose(KEY_OPENOPTICALDEV))
132 .toString();
133 }
134
135 private String getPowerRangeFilter(PortNumber port, String direction) {
136 return new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
137 .append(xmlOpen(KEY_PORTS))
138 .append(xml(KEY_PORTID, Long.toString(port.toLong())))
139 .append(xmlOpen(KEY_PORT))
140 .append(xml(KEY_PORTDIRECT, direction))
141 .append(xmlEmpty(KEY_PORTPROPERTY))
142 .append(xmlClose(KEY_PORT))
143 .append(xmlClose(KEY_PORTS))
144 .append(xmlClose(KEY_OPENOPTICALDEV))
145 .toString();
146 }
147
148 private Long acquireTargetPower(PortNumber port, T component) {
149 if (component instanceof OchSignal) {
150 return acquireChannelAttenuation(port, (OchSignal) component);
151 }
152 log.debug("Get port{} target power...", port);
153 return acquirePortPower(port, KEY_PORTTARPWR);
154 }
155
156 private Long acquireCurrentPower(PortNumber port, T component) {
157 if (component instanceof OchSignal) {
158 return acquireChannelPower(port, (OchSignal) component);
159 }
160 log.debug("Get port{} current power...", port);
161 return acquirePortPower(port, KEY_PORTCURPWR);
162 }
163
164 private Long acquirePortPower(PortNumber port, String selection) {
165 String reply = netconfGetConfig(handler(), getPortPowerFilter(port, selection));
166 HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT);
167 if (info == null) {
168 return null;
169 }
170 return (long) (info.getDouble(selection) * POWER_MULTIPLIER);
171 }
172
173 private Long acquireChannelAttenuation(PortNumber port, OchSignal channel) {
174 log.debug("Get port{} channel{} attenuation...", port, channel.channelSpacing());
175 String reply = netconfGetConfig(handler(), getChannelAttenuationFilter(port, channel));
176 HierarchicalConfiguration info = configAt(reply, KEY_CONNS);
177 if (info == null) {
178 return null;
179 }
180 return (long) (info.getDouble(KEY_CHATT) * POWER_MULTIPLIER);
181 }
182
183 private Long acquireChannelPower(PortNumber port, OchSignal channel) {
184 log.debug("Get port{} channel{} power...", port, channel.channelSpacing());
185 String reply = netconfGetConfig(handler(), getChannelPowerFilter(port, channel));
186 HierarchicalConfiguration info = configAt(reply, KEY_DATA_CONNS);
187 if (info == null) {
188 return null;
189 }
190 return (long) (info.getDouble(KEY_CHPWR) * POWER_MULTIPLIER);
191 }
192
193 private boolean setPortTargetPower(PortNumber port, long power) {
194 log.debug("Set port{} target power...", port);
195 String cfg = new StringBuilder(xmlOpen(KEY_OPENOPTICALDEV_XMLNS))
196 .append(xmlOpen(KEY_PORTS))
197 .append(xml(KEY_PORTID, Long.toString(port.toLong())))
198 .append(xmlOpen(KEY_PORT))
199 .append(xml(KEY_PORTTARPWR, Long.toString(power)))
200 .append(xmlClose(KEY_PORT))
201 .append(xmlClose(KEY_PORTS))
202 .append(xmlClose(KEY_OPENOPTICALDEV))
203 .toString();
204 return netconfEditConfig(handler(), CFG_MODE_MERGE, cfg);
205 }
206
207 private boolean setChannelTargetPower(PortNumber port, OchSignal channel, long power) {
208 log.debug("Set port{} channel{} attenuation.", port, channel.channelSpacing());
209 FlowRuleService service = handler().get(FlowRuleService.class);
210 Iterable<FlowEntry> entries = service.getFlowEntries(data().deviceId());
211 for (FlowEntry entry : entries) {
212 OplinkCrossConnect crossConnect = OplinkOpticalUtility.fromFlowRule(this, entry);
213 // The channel port might be input port or output port.
214 if ((port.equals(crossConnect.getInPort()) || port.equals(crossConnect.getOutPort())) &&
215 channel.spacingMultiplier() == crossConnect.getChannel()) {
216 log.debug("Flow is found, modify the flow with attenuation.");
217 // Modify attenuation in treatment
218 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
219 .setOutput(crossConnect.getOutPort())
220 .extension(new OplinkAttenuation((int) power), data().deviceId())
221 .build();
222 // Apply the new flow rule
223 service.applyFlowRules(DefaultFlowRule.builder()
224 .forDevice(data().deviceId())
225 .makePermanent()
226 .withSelector(entry.selector())
227 .withTreatment(treatment)
228 .withPriority(entry.priority())
229 .withCookie(entry.id().value())
230 .build());
231 return true;
232 }
233 }
234 return false;
235 }
236
237 private Range<Long> getPowerRange(PortNumber port, String directionKey, String minKey, String maxKey) {
238 String reply = netconfGetConfig(handler(), getPowerRangeFilter(port, directionKey));
239 HierarchicalConfiguration info = configAt(reply, KEY_PORTS_PORT_PROPERTY);
240 if (info == null) {
241 return null;
242 }
243 long minPower = (long) (info.getDouble(minKey) * POWER_MULTIPLIER);
244 long maxPower = (long) (info.getDouble(maxKey) * POWER_MULTIPLIER);
245 return Range.closed(minPower, maxPower);
246 }
247
248 private Range<Long> getTxPowerRange(PortNumber port, T component) {
249 if (component instanceof Direction) {
250 log.debug("Get target port{} power range...", port);
251 return getPowerRange(port, KEY_PORTDIRECT_TX, KEY_PORTPWRCAPMINTX, KEY_PORTPWRCAPMAXTX);
252 } else {
253 log.debug("Get channel attenuation range...");
254 return Range.closed(MIN_ATTENUATION, MAX_ATTENUATION);
255 }
256 }
257
258 private Range<Long> getRxPowerRange(PortNumber port, T component) {
259 log.debug("Get input port{} power range...", port);
260 return getPowerRange(port, KEY_PORTDIRECT_RX, KEY_PORTPWRCAPMINRX, KEY_PORTPWRCAPMAXRX);
261 }
262}