blob: f446848af89a34ebaddfb8d02d501fe264fac3b6 [file] [log] [blame]
qphamvan9aedb562019-02-19 14:38:53 +01001/*
2 * Copyright 2018-present Open Networking Foundation
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
18package org.onosproject.drivers.odtn;
19
20import com.google.common.collect.ImmutableList;
21import org.onlab.util.Frequency;
22import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
23import org.onosproject.drivers.odtn.impl.FlowRuleParser;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.Port;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.device.DeviceService;
28import org.onosproject.net.driver.AbstractHandlerBehaviour;
29import org.onosproject.net.flow.DefaultFlowEntry;
30import org.onosproject.net.flow.FlowEntry;
31import org.onosproject.net.flow.FlowRule;
32import org.onosproject.net.flow.FlowRuleProgrammable;
33import org.onosproject.netconf.DatastoreId;
34import org.onosproject.netconf.NetconfController;
35import org.onosproject.netconf.NetconfException;
36import org.onosproject.netconf.NetconfSession;
37import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.ArrayList;
41import java.util.Collection;
42import java.util.List;
43
44import static com.google.common.base.Preconditions.checkNotNull;
45import static org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery.OC_NAME;
46
47/**
48 * Implementation of FlowRuleProgrammable interface for
49 * OpenConfig terminal devices.
50 */
51public class NokiaFlowRuleProgrammable
52 extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
53
54 private static final Logger log =
55 LoggerFactory.getLogger(NokiaFlowRuleProgrammable.class);
56
57 /**
58 * Apply the flow entries specified in the collection rules.
59 *
60 * @param rules A collection of Flow Rules to be applied
61 * @return The collection of added Flow Entries
62 */
63 @Override
64 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
65 NetconfSession session = getNetconfSession();
66 if (session == null) {
67 openConfigError("null session");
68 return ImmutableList.of();
69 }
70 List<FlowRule> added = new ArrayList<>();
71 for (FlowRule r : rules) {
72 try {
73 String connectionId = applyFlowRule(session, r);
74 getConnectionCache().add(did(), connectionId, r);
75 added.add(r);
76 } catch (Exception e) {
77 openConfigError("Error {}", e);
78 continue;
79 }
80 }
81 openConfigLog("applyFlowRules added {}", added.size());
82 return added;
83 }
84
85 /**
86 * Get the flow entries that are present on the device.
87 *
88 * @return A collection of Flow Entries
89 */
90 @Override
91 public Collection<FlowEntry> getFlowEntries() {
92 DeviceConnectionCache cache = getConnectionCache();
93 if (cache.get(did()) == null) {
94 return ImmutableList.of();
95 }
96
97 List<FlowEntry> entries = new ArrayList<>();
98 for (FlowRule r : cache.get(did())) {
99 entries.add(
100 new DefaultFlowEntry(r, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
101 }
102 return entries;
103 }
104
105 /**
106 * Remove the specified flow rules.
107 *
108 * @param rules A collection of Flow Rules to be removed
109 * @return The collection of removed Flow Entries
110 */
111 @Override
112 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
113 NetconfSession session = getNetconfSession();
114 if (session == null) {
115 openConfigError("null session");
116 return ImmutableList.of();
117 }
118 List<FlowRule> removed = new ArrayList<>();
119 for (FlowRule r : rules) {
120 try {
121 String connectionId = removeFlowRule(session, r);
122 getConnectionCache().remove(did(), connectionId);
123 removed.add(r);
124 } catch (Exception e) {
125 openConfigError("Error {}", e);
126 continue;
127 }
128 }
129 openConfigLog("removedFlowRules removed {}", removed.size());
130 return removed;
131 }
132
133 private DeviceConnectionCache getConnectionCache() {
134 return DeviceConnectionCache.init();
135 }
136
137 /**
138 * Helper method to get the device id.
139 */
140 private DeviceId did() {
141 return data().deviceId();
142 }
143
144 /**
145 * Helper method to log from this class adding DeviceId.
146 */
147 private void openConfigLog(String format, Object... arguments) {
148 log.info("OPENCONFIG {}: " + format, did(), arguments);
149 }
150
151 /**
152 * Helper method to log an error from this class adding DeviceId.
153 */
154 private void openConfigError(String format, Object... arguments) {
155 log.error("OPENCONFIG {}: " + format, did(), arguments);
156 }
157
158
159 /**
160 * Helper method to get the Netconf Session.
161 */
162 private NetconfSession getNetconfSession() {
163 NetconfController controller =
164 checkNotNull(handler().get(NetconfController.class));
165 return controller.getNetconfDevice(did()).getSession();
166 }
167
168 private void setOpticalChannelFrequency(NetconfSession session,
169 String optChannel, Frequency freq)
170 throws NetconfException {
Quan PHAM VAN84ac1812019-02-28 16:22:45 +0100171 String[] textStr = optChannel.split("-");
qphamvan9aedb562019-02-19 14:38:53 +0100172 StringBuilder sb = new StringBuilder();
173 sb.append(
174 "<components xmlns='http://openconfig.net/yang/platform'>"
175 + "<component operation='merge'>"
Quan PHAM VAN84ac1812019-02-28 16:22:45 +0100176 + "<name>" + "OCH-" + textStr[1] + "-" + textStr[2] + "-" + textStr[3] + "</name>"
qphamvan9aedb562019-02-19 14:38:53 +0100177 + "<oc-opt-term:optical-channel "
178 +
179 " xmlns:oc-opt-term='http://openconfig.net/yang/terminal-device'>"
180 + " <oc-opt-term:config>"
181 + " <oc-opt-term:frequency>" + (long) freq.asMHz() +
182 "</oc-opt-term:frequency>"
183 + " </oc-opt-term:config>"
184 + " </oc-opt-term:optical-channel>"
185 + "</component>"
186 + "</components>");
187
188 boolean ok =
189 session.editConfig(DatastoreId.RUNNING, null, sb.toString());
190 if (!ok) {
191 throw new NetconfException("error writing channel frequency");
192 }
193 }
194
195 /**
196 * Get the OpenConfig component name for the OpticalChannel component.
197 *
198 * @param portNumber ONOS port number of the Line port ().
199 * @return the channel component name or null
200 */
201 private String getOpticalChannel(PortNumber portNumber) {
202 Port clientPort = handler().get(DeviceService.class).getPort(did(), portNumber);
203 return clientPort.annotations().value(OC_NAME);
204 }
205
206 /**
207 * Apply the flowrule.
208 *
209 * Note: only bidirectional are supported as of now,
210 * given OpenConfig note (below). In consequence, only the
211 * TX rules are actually mapped to netconf ops.
212 * <p>
213 * https://github.com/openconfig/public/blob/master/release/models
214 * /optical-transport/openconfig-terminal-device.yang
215 * <p>
216 * Directionality:
217 * To maintain simplicity in the model, the configuration is
218 * described from client-to-line direction. The assumption is that
219 * equivalent reverse configuration is implicit, resulting in
220 * the same line-to-client configuration.
221 *
222 * @param session The Netconf session.
223 * @param r Flow Rules to be applied.
224 * @return the optical channel + the frequency or just channel as identifier fo the config installed on the device
225 * @throws NetconfException if exchange goes wrong
226 */
227 protected String applyFlowRule(NetconfSession session, FlowRule r) throws NetconfException {
228 FlowRuleParser frp = new FlowRuleParser(r);
229 if (!frp.isReceiver()) {
230 String optChannel = getOpticalChannel(frp.getPortNumber());
231 setOpticalChannelFrequency(session, optChannel,
232 frp.getCentralFrequency());
233 return optChannel + ":" + frp.getCentralFrequency().asGHz();
234 }
235 return String.valueOf(frp.getCentralFrequency().asGHz());
236 }
237
238
239 protected String removeFlowRule(NetconfSession session, FlowRule r)
240 throws NetconfException {
241 FlowRuleParser frp = new FlowRuleParser(r);
242 if (!frp.isReceiver()) {
243 String optChannel = getOpticalChannel(frp.getPortNumber());
244 setOpticalChannelFrequency(session, optChannel, Frequency.ofMHz(0));
245 return optChannel + ":" + frp.getCentralFrequency().asGHz();
246 }
247 return String.valueOf(frp.getCentralFrequency().asGHz());
248 }
249}