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