blob: 063988479dc2cfac31e771bd183b0a6fb834906f [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 {
171 StringBuilder sb = new StringBuilder();
172 sb.append(
173 "<components xmlns='http://openconfig.net/yang/platform'>"
174 + "<component operation='merge'>"
175 + "<name>" + optChannel + "</name>"
176 + "<oc-opt-term:optical-channel "
177 +
178 " xmlns:oc-opt-term='http://openconfig.net/yang/terminal-device'>"
179 + " <oc-opt-term:config>"
180 + " <oc-opt-term:frequency>" + (long) freq.asMHz() +
181 "</oc-opt-term:frequency>"
182 + " </oc-opt-term:config>"
183 + " </oc-opt-term:optical-channel>"
184 + "</component>"
185 + "</components>");
186
187 boolean ok =
188 session.editConfig(DatastoreId.RUNNING, null, sb.toString());
189 if (!ok) {
190 throw new NetconfException("error writing channel frequency");
191 }
192 }
193
194 /**
195 * Get the OpenConfig component name for the OpticalChannel component.
196 *
197 * @param portNumber ONOS port number of the Line port ().
198 * @return the channel component name or null
199 */
200 private String getOpticalChannel(PortNumber portNumber) {
201 Port clientPort = handler().get(DeviceService.class).getPort(did(), portNumber);
202 return clientPort.annotations().value(OC_NAME);
203 }
204
205 /**
206 * Apply the flowrule.
207 *
208 * Note: only bidirectional are supported as of now,
209 * given OpenConfig note (below). In consequence, only the
210 * TX rules are actually mapped to netconf ops.
211 * <p>
212 * https://github.com/openconfig/public/blob/master/release/models
213 * /optical-transport/openconfig-terminal-device.yang
214 * <p>
215 * Directionality:
216 * To maintain simplicity in the model, the configuration is
217 * described from client-to-line direction. The assumption is that
218 * equivalent reverse configuration is implicit, resulting in
219 * the same line-to-client configuration.
220 *
221 * @param session The Netconf session.
222 * @param r Flow Rules to be applied.
223 * @return the optical channel + the frequency or just channel as identifier fo the config installed on the device
224 * @throws NetconfException if exchange goes wrong
225 */
226 protected String applyFlowRule(NetconfSession session, FlowRule r) throws NetconfException {
227 FlowRuleParser frp = new FlowRuleParser(r);
228 if (!frp.isReceiver()) {
229 String optChannel = getOpticalChannel(frp.getPortNumber());
230 setOpticalChannelFrequency(session, optChannel,
231 frp.getCentralFrequency());
232 return optChannel + ":" + frp.getCentralFrequency().asGHz();
233 }
234 return String.valueOf(frp.getCentralFrequency().asGHz());
235 }
236
237
238 protected String removeFlowRule(NetconfSession session, FlowRule r)
239 throws NetconfException {
240 FlowRuleParser frp = new FlowRuleParser(r);
241 if (!frp.isReceiver()) {
242 String optChannel = getOpticalChannel(frp.getPortNumber());
243 setOpticalChannelFrequency(session, optChannel, Frequency.ofMHz(0));
244 return optChannel + ":" + frp.getCentralFrequency().asGHz();
245 }
246 return String.valueOf(frp.getCentralFrequency().asGHz());
247 }
248}