blob: 7c88fdef727c7bb85cb42e022d35e1aaaf1ef557 [file] [log] [blame]
Andrea Campanellad8d92db2016-01-14 16:24:41 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Andrea Campanellad8d92db2016-01-14 16:24:41 -08003 *
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
Andrea Campanella238d96e2016-01-20 11:52:02 -080017package org.onosproject.drivers.utilities;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080018
19import com.google.common.collect.Lists;
20import org.apache.commons.configuration.ConfigurationException;
21import org.apache.commons.configuration.HierarchicalConfiguration;
22import org.apache.commons.configuration.XMLConfiguration;
23import org.apache.commons.configuration.tree.ConfigurationNode;
24import org.onlab.packet.IpAddress;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080025import org.onosproject.net.AnnotationKeys;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080026import org.onosproject.net.ChannelSpacing;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080027import org.onosproject.net.CltSignalType;
28import org.onosproject.net.DefaultAnnotations;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080029import org.onosproject.net.GridType;
30import org.onosproject.net.OchSignal;
31import org.onosproject.net.OduSignalType;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.SparseAnnotations;
34import org.onosproject.net.behaviour.ControllerInfo;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080035import org.onosproject.net.device.PortDescription;
36import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080039import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070040import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080041
Andrea Campanellad8d92db2016-01-14 16:24:41 -080042import java.io.InputStream;
43import java.io.StringWriter;
44import java.util.ArrayList;
45import java.util.List;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080046import java.util.concurrent.atomic.AtomicInteger;
47
Andrea Campanellad8d92db2016-01-14 16:24:41 -080048
49/**
50 * Parser for Netconf XML configurations and replys.
51 */
52public final class XmlConfigParser {
53 public static final Logger log = LoggerFactory
54 .getLogger(XmlConfigParser.class);
55
56 private XmlConfigParser() {
57 //not called, preventing any allocation
58 }
59
60
61 public static HierarchicalConfiguration loadXml(InputStream xmlStream) {
62 XMLConfiguration cfg = new XMLConfiguration();
63 try {
64 cfg.load(xmlStream);
65 return cfg;
66 } catch (ConfigurationException e) {
67 throw new IllegalArgumentException("Cannot load xml from Stream", e);
68 }
69 }
70
71 public static List<ControllerInfo> parseStreamControllers(HierarchicalConfiguration cfg) {
72 List<ControllerInfo> controllers = new ArrayList<>();
73 List<HierarchicalConfiguration> fields =
74 cfg.configurationsAt("data.capable-switch." +
75 "logical-switches." +
76 "switch.controllers.controller");
77 for (HierarchicalConfiguration sub : fields) {
78 controllers.add(new ControllerInfo(
79 IpAddress.valueOf(sub.getString("ip-address")),
80 Integer.parseInt(sub.getString("port")),
81 sub.getString("protocol")));
82 }
83 return controllers;
84 }
85
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080086 /**
87 * Parses a configuration and returns a set of ports for the fujitsu T100.
88 * @param cfg a hierarchical configuration
89 * @return a list of port descriptions
90 */
91 public static List<PortDescription> parseFujitsuT100Ports(HierarchicalConfiguration cfg) {
92 AtomicInteger counter = new AtomicInteger(1);
93 List<PortDescription> portDescriptions = Lists.newArrayList();
94 List<HierarchicalConfiguration> subtrees =
95 cfg.configurationsAt("data.interfaces.interface");
96 for (HierarchicalConfiguration portConfig : subtrees) {
97 if (!portConfig.getString("name").contains("LCN") &&
98 !portConfig.getString("name").contains("LMP") &&
99 portConfig.getString("type").equals("ianaift:ethernetCsmacd")) {
100 portDescriptions.add(parseT100OduPort(portConfig, counter.getAndIncrement()));
101 } else if (portConfig.getString("type").equals("ianaift:otnOtu")) {
102 portDescriptions.add(parseT100OchPort(portConfig, counter.getAndIncrement()));
103 }
104 }
105 return portDescriptions;
106 }
107
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800108 private static PortDescription parseT100OchPort(HierarchicalConfiguration cfg, long count) {
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800109 PortNumber portNumber = PortNumber.portNumber(count);
110 HierarchicalConfiguration otuConfig = cfg.configurationAt("otu");
111 boolean enabled = otuConfig.getString("administrative-state").equals("up");
112 OduSignalType signalType = otuConfig.getString("rate").equals("OTU4") ? OduSignalType.ODU4 : null;
113 //Unsure how to retreive, outside knowledge it is tunable.
114 boolean isTunable = true;
115 OchSignal lambda = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4);
116 DefaultAnnotations annotations = DefaultAnnotations.builder().
117 set(AnnotationKeys.PORT_NAME, cfg.getString("name")).
118 build();
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800119 return ochPortDescription(portNumber, enabled, signalType, isTunable, lambda, annotations);
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800120 }
121
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700122 private static PortDescription parseT100OduPort(HierarchicalConfiguration cfg, long count) {
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800123 PortNumber portNumber = PortNumber.portNumber(count);
124 HierarchicalConfiguration ethernetConfig = cfg.configurationAt("ethernet");
125 boolean enabled = ethernetConfig.getString("administrative-state").equals("up");
126 //Rate is in kbps
127 CltSignalType signalType = ethernetConfig.getString("rate").equals("100000000") ?
128 CltSignalType.CLT_100GBE : null;
129 DefaultAnnotations annotations = DefaultAnnotations.builder().
130 set(AnnotationKeys.PORT_NAME, cfg.getString("name")).
131 build();
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700132 return oduCltPortDescription(portNumber, enabled, signalType, annotations);
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800133 }
134
135 protected static String parseSwitchId(HierarchicalConfiguration cfg) {
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800136 HierarchicalConfiguration field =
137 cfg.configurationAt("data.capable-switch." +
138 "logical-switches." +
139 "switch");
140 return field.getProperty("id").toString();
141 }
142
143 public static String parseCapableSwitchId(HierarchicalConfiguration cfg) {
144 HierarchicalConfiguration field =
145 cfg.configurationAt("data.capable-switch");
146 return field.getProperty("id").toString();
147 }
148
149 public static String createControllersConfig(HierarchicalConfiguration cfg,
150 HierarchicalConfiguration actualCfg,
151 String target, String netconfOperation,
152 String controllerOperation,
153 List<ControllerInfo> controllers) {
154 //cfg.getKeys().forEachRemaining(key -> System.out.println(key));
155 cfg.setProperty("edit-config.target", target);
156 cfg.setProperty("edit-config.default-operation", netconfOperation);
157 cfg.setProperty("edit-config.config.capable-switch.id",
158 parseCapableSwitchId(actualCfg));
159 cfg.setProperty("edit-config.config.capable-switch." +
160 "logical-switches.switch.id", parseSwitchId(actualCfg));
161 List<ConfigurationNode> newControllers = new ArrayList<>();
162 for (ControllerInfo ci : controllers) {
163 XMLConfiguration controller = new XMLConfiguration();
164 controller.setRoot(new HierarchicalConfiguration.Node("controller"));
165 String id = ci.type() + ":" + ci.ip() + ":" + ci.port();
166 controller.setProperty("id", id);
167 controller.setProperty("ip-address", ci.ip());
168 controller.setProperty("port", ci.port());
169 controller.setProperty("protocol", ci.type());
170 newControllers.add(controller.getRootNode());
171 }
172 cfg.addNodes("edit-config.config.capable-switch.logical-switches." +
173 "switch.controllers", newControllers);
174 XMLConfiguration editcfg = (XMLConfiguration) cfg;
175 StringWriter stringWriter = new StringWriter();
176 try {
177 editcfg.save(stringWriter);
178 } catch (ConfigurationException e) {
179 log.error("createControllersConfig()", e);
180 }
181 String s = stringWriter.toString()
182 .replaceAll("<controller>",
183 "<controller nc:operation=\"" + controllerOperation + "\">");
184 s = s.replace("<target>" + target + "</target>",
185 "<target><" + target + "/></target>");
186 return s;
187
188 }
189
190 public static List<HierarchicalConfiguration> parseWaveServerCienaPorts(HierarchicalConfiguration cfg) {
191 return cfg.configurationsAt("ws-ports.port-interface");
192 }
193
Jonathan Hart51539b82015-10-29 09:53:04 -0700194 public static PortDescription parseWaveServerCienaOchPorts(long portNumber, long oduPortSpeed,
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800195 HierarchicalConfiguration config,
196 SparseAnnotations annotations) {
197 final List<String> tunableType = Lists.newArrayList("Performance-Optimized", "Accelerated");
198 final String transmitterPath = "ptp-config.transmitter-state";
199 final String tunablePath = "ptp-config.adv-config.tx-tuning-mode";
200 final String gridTypePath = "ptp-config.adv-config.wl-spacing";
201 final String frequencyPath = "ptp-config.adv-config.frequency";
202
203 boolean isEnabled = config.getString(transmitterPath).equals("enabled");
204 boolean isTunable = tunableType.contains(config.getString(tunablePath));
205
206 //FIXME change when all optical types have two way information methods, see jira tickets
207 final int speed100GbpsinMbps = 100000;
208 OduSignalType oduSignalType = oduPortSpeed == speed100GbpsinMbps ? OduSignalType.ODU4 : null;
209 GridType gridType = config.getString(gridTypePath).equals("FlexGrid") ? GridType.FLEX : null;
210 ChannelSpacing chSpacing = gridType == GridType.FLEX ? ChannelSpacing.CHL_6P25GHZ : null;
211
212 //Working in Ghz //(Nominal central frequency - 193.1)/channelSpacing = spacingMultiplier
213 final int baseFrequency = 193100;
214 int spacingMult = (int) (toGbps((Integer.parseInt(config.getString(frequencyPath)) -
215 baseFrequency)) / toGbpsFromHz(chSpacing.frequency().asHz())); //FIXME is there a better way ?
216
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800217 return ochPortDescription(PortNumber.portNumber(portNumber), isEnabled, oduSignalType, isTunable,
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800218 new OchSignal(gridType, chSpacing, spacingMult, 1), annotations);
219 }
220
221 //FIXME remove when all optical types have two way information methods, see jira tickets
222 private static long toGbps(long speed) {
223 return speed * 1000;
224 }
225
226 private static long toGbpsFromHz(long speed) {
227 return speed / 1000;
228 }
229 //TODO implement mor methods for parsing configuration when you need them
Andreas Papazois1dff77c2016-02-16 16:27:33 +0200230
231 /**
232 * Parses a config reply and returns the result.
233 * @param reply a tree-like source
234 * @return the configuration result
235 */
236 public static boolean configSuccess(HierarchicalConfiguration reply) {
237 if (reply != null) {
238 if (reply.containsKey("ok")) {
239 return true;
240 }
241 }
242 return false;
243 }
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800244}