blob: f31c8b0cf10a5ef03dc0e21174def44e282292f1 [file] [log] [blame]
Andreas Papazois92e4a042016-02-24 15:29:30 +02001/*
2 *
Brian O'Connor5ab426f2016-04-09 01:19:45 -07003 * * Copyright 2016-present Open Networking Laboratory
Andreas Papazois92e4a042016-02-24 15:29:30 +02004 * *
5 * * Licensed under the Apache License, Version 2.0 (the "License");
6 * * you may not use this file except in compliance with the License.
7 * * You may obtain a copy of the License at
8 * *
9 * * http://www.apache.org/licenses/LICENSE-2.0
10 * *
11 * * Unless required by applicable law or agreed to in writing, software
12 * * distributed under the License is distributed on an "AS IS" BASIS,
13 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * * See the License for the specific language governing permissions and
15 * * limitations under the License.
16 *
17 */
18
19package org.onosproject.drivers.cisco;
20
21import org.onlab.packet.VlanId;
22import org.onosproject.drivers.utilities.XmlConfigParser;
23import org.onosproject.net.DeviceId;
24import org.onosproject.net.behaviour.InterfaceConfig;
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030025import org.onosproject.net.device.DeviceInterfaceDescription;
Andreas Papazois92e4a042016-02-24 15:29:30 +020026import org.onosproject.net.driver.AbstractHandlerBehaviour;
27import org.onosproject.netconf.NetconfController;
28import org.onosproject.netconf.NetconfException;
29import org.onosproject.netconf.NetconfSession;
30import org.slf4j.Logger;
31
32import java.io.ByteArrayInputStream;
33import java.nio.charset.StandardCharsets;
Andreas Papazois59e19bb2016-04-12 13:59:58 +030034import java.util.List;
Andreas Papazois92e4a042016-02-24 15:29:30 +020035
36import static com.google.common.base.Preconditions.checkNotNull;
37import static org.slf4j.LoggerFactory.getLogger;
38
39/**
40 * Configures interfaces on Cisco IOS devices.
41 */
42public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour
43 implements InterfaceConfig {
44
45 private final Logger log = getLogger(getClass());
46
47 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030048 * Adds an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030049 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020050 * @param deviceId the device ID
51 * @param intf the name of the interface
52 * @param vlanId the VLAN ID
53 * @return the result of operation
54 */
55 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +030056 public boolean addAccessInterface(DeviceId deviceId, String intf, VlanId vlanId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030057 return addAccessMode(intf, vlanId);
58 }
59
60 /**
61 * Adds an access interface to a VLAN.
62 *
63 * @param intf the name of the interface
64 * @param vlanId the VLAN ID
65 * @return the result of operation
66 */
67 @Override
68 public boolean addAccessMode(String intf, VlanId vlanId) {
Andreas Papazois92e4a042016-02-24 15:29:30 +020069 NetconfController controller = checkNotNull(handler()
70 .get(NetconfController.class));
71
72 NetconfSession session = controller.getDevicesMap().get(handler()
73 .data().deviceId()).getSession();
74 String reply;
75 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030076 reply = session.requestSync(addAccessModeBuilder(intf, vlanId));
Andreas Papazois92e4a042016-02-24 15:29:30 +020077 } catch (NetconfException e) {
78 log.error("Failed to configure VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +030079 vlanId, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +020080 return false;
81 }
82
83 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
84 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
85 }
86
87 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030088 * Builds a request to add an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030089 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020090 * @param intf the name of the interface
91 * @param vlanId the VLAN ID
92 * @return the request string.
93 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +030094 private String addAccessModeBuilder(String intf, VlanId vlanId) {
95 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +020096 rpc.append("<switchport><access><vlan><VLANIDVLANPortAccessMode>");
97 rpc.append(vlanId);
98 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
99 rpc.append("<switchport><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300100 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200101
102 return rpc.toString();
103 }
104
105 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300106 * Removes an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300107 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200108 * @param deviceId the device ID
109 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200110 * @return the result of operation
111 */
112 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300113 public boolean removeAccessInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300114 return removeAccessMode(intf);
115 }
116
117 /**
118 * Removes an access interface to a VLAN.
119 *
120 * @param intf the name of the interface
121 * @return the result of operation
122 */
123 @Override
124 public boolean removeAccessMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200125 NetconfController controller = checkNotNull(handler()
126 .get(NetconfController.class));
127
128 NetconfSession session = controller.getDevicesMap().get(handler()
129 .data().deviceId()).getSession();
130 String reply;
131 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300132 reply = session.requestSync(removeAccessModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200133 } catch (NetconfException e) {
Andreas Papazois827d8d02016-04-15 11:53:16 +0300134 log.error("Failed to remove access mode from device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300135 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200136 return false;
137 }
138
139 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
140 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
141 }
142
143 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300144 * Builds a request to remove an access interface from a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300145 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200146 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200147 * @return the request string.
148 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300149 private String removeAccessModeBuilder(String intf) {
150 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200151 rpc.append("<switchport operation=\"delete\"><access><vlan><VLANIDVLANPortAccessMode>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200152 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
153 rpc.append("<switchport operation=\"delete\"><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300154 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200155
156 return rpc.toString();
157 }
158
159 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300160 * Adds a trunk interface for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300161 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200162 * @param deviceId the device ID
163 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300164 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200165 * @return the result of operation
166 */
167 @Override
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300168 public boolean addTrunkInterface(DeviceId deviceId, String intf, List<VlanId> vlanIds) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300169 return addTrunkMode(intf, vlanIds);
170 }
171
172 /**
173 * Adds a trunk interface for VLANs.
174 *
175 * @param intf the name of the interface
176 * @param vlanIds the VLAN IDs
177 * @return the result of operation
178 */
179 @Override
180 public boolean addTrunkMode(String intf, List<VlanId> vlanIds) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200181 NetconfController controller = checkNotNull(handler()
182 .get(NetconfController.class));
183
184 NetconfSession session = controller.getDevicesMap().get(handler()
185 .data().deviceId()).getSession();
186 String reply;
187 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300188 reply = session.requestSync(addTrunkModeBuilder(intf, vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200189 } catch (NetconfException e) {
190 log.error("Failed to configure trunk mode for VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300191 vlanIds, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200192 return false;
193 }
194
195 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
196 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
197 }
198
199 /**
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300200 * Builds a request to configure an interface as trunk for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300201 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200202 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300203 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200204 * @return the request string.
205 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300206 private String addTrunkModeBuilder(String intf, List<VlanId> vlanIds) {
207 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200208 rpc.append("<switchport><trunk><encapsulation><dot1q/></encapsulation>");
209 rpc.append("</trunk></switchport><switchport><trunk><allowed><vlan>");
210 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300211 rpc.append(getVlansString(vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200212 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk>");
213 rpc.append("</switchport><switchport><mode><trunk/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300214 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200215
216 return rpc.toString();
217 }
218
219 /**
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300220 * Removes trunk mode configuration from an interface.
221 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200222 * @param deviceId the device ID
223 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200224 * @return the result of operation
225 */
226 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300227 public boolean removeTrunkInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300228 return removeTrunkMode(intf);
229 }
230
231 /**
232 * Removes trunk mode configuration from an interface.
233 *
234 * @param intf the name of the interface
235 * @return the result of operation
236 */
237 @Override
238 public boolean removeTrunkMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200239 NetconfController controller = checkNotNull(handler()
240 .get(NetconfController.class));
241
242 NetconfSession session = controller.getDevicesMap().get(handler()
243 .data().deviceId()).getSession();
244 String reply;
245 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300246 reply = session.requestSync(removeTrunkModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200247 } catch (NetconfException e) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300248 log.error("Failed to remove trunk mode from device {} interface {}.",
249 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200250 return false;
251 }
252
253 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
254 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
255}
256
257 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300258 * Builds a request to remove trunk mode configuration from an interface.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300259 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200260 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200261 * @return the request string.
262 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300263 private String removeTrunkModeBuilder(String intf) {
264 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
265 rpc.append("<switchport><mode operation=\"delete\"><trunk/></mode></switchport>");
266 rpc.append("<switchport><trunk operation=\"delete\"><encapsulation>");
267 rpc.append("<dot1q/></encapsulation></trunk></switchport>");
268 rpc.append("<switchport><trunk operation=\"delete\"><allowed><vlan>");
269 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
270 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed>");
271 rpc.append("</trunk></switchport>");
272 rpc.append(getClosingString());
273
274 return rpc.toString();
275 }
276
277 /**
278 * Adds a rate limit on an interface.
279 *
280 * @param intf the name of the interface
281 * @param limit the limit as a percentage
282 * @return the result of operation
283 */
284 @Override
285 public boolean addRateLimit(String intf, short limit) {
286 NetconfController controller = checkNotNull(handler()
287 .get(NetconfController.class));
288
289 NetconfSession session = controller.getDevicesMap().get(handler()
290 .data().deviceId()).getSession();
291 String reply;
292 try {
293 reply = session.requestSync(addRateLimitBuilder(intf, limit));
294 } catch (NetconfException e) {
295 log.error("Failed to configure rate limit {}%% on device {} interface {}.",
296 limit, handler().data().deviceId(), intf, e);
297 return false;
298 }
299
300 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
301 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
302 }
303
304 /**
305 * Builds a request to configure an interface with rate limit.
306 *
307 * @param intf the name of the interface
308 * @param limit the limit as a percentage
309 * @return the request string.
310 */
311 private String addRateLimitBuilder(String intf, short limit) {
312 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
313 rpc.append("<srr-queue><bandwidth><limit>");
314 rpc.append("<EnterBandwidthLimitInterfaceAsPercentage>");
315 rpc.append(limit);
316 rpc.append("</EnterBandwidthLimitInterfaceAsPercentage>");
317 rpc.append("</limit></bandwidth></srr-queue>");
318 rpc.append(getClosingString());
319
320 return rpc.toString();
321 }
322
323 /**
324 * Removes rate limit from an interface.
325 *
326 * @param intf the name of the interface
327 * @return the result of operation
328 */
329 @Override
330 public boolean removeRateLimit(String intf) {
331 NetconfController controller = checkNotNull(handler()
332 .get(NetconfController.class));
333
334 NetconfSession session = controller.getDevicesMap().get(handler()
335 .data().deviceId()).getSession();
336 String reply;
337 try {
338 reply = session.requestSync(removeRateLimitBuilder(intf));
339 } catch (NetconfException e) {
340 log.error("Failed to remove rate limit from device {} interface {}.",
341 handler().data().deviceId(), intf, e);
342 return false;
343 }
344
345 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
346 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
347 }
348
349 /**
350 * Builds a request to remove a rate limit from an interface.
351 *
352 * @param intf the name of the interface
353 * @return the request string.
354 */
355 private String removeRateLimitBuilder(String intf) {
356 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
357 rpc.append("<srr-queue operation=\"delete\"><bandwidth><limit>");
358 rpc.append("</limit></bandwidth></srr-queue>");
359 rpc.append(getClosingString());
360
361 return rpc.toString();
362 }
363
364 /**
365 * Builds the opening of a request for the configuration of an interface.
366 *
367 * @param intf the interface to be configured
368 * @return the opening string
369 */
370 private String getOpeningString(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200371 StringBuilder rpc =
372 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
373 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
374 rpc.append("<edit-config>");
375 rpc.append("<target>");
376 rpc.append("<running/>");
377 rpc.append("</target>");
378 rpc.append("<config>");
379 rpc.append("<xml-config-data>");
380 rpc.append("<Device-Configuration><interface><Param>");
381 rpc.append(intf);
382 rpc.append("</Param>");
383 rpc.append("<ConfigIf-Configuration>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300384
385 return rpc.toString();
386 }
387
388 /**
389 * Builds the closing of a request for the configuration of an interface.
390 *
391 * @return the closing string
392 */
393 private String getClosingString() {
394 StringBuilder rpc = new StringBuilder("</ConfigIf-Configuration>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200395 rpc.append("</interface>");
396 rpc.append("</Device-Configuration>");
397 rpc.append("</xml-config-data>");
398 rpc.append("</config>");
399 rpc.append("</edit-config>");
400 rpc.append("</rpc>");
401
402 return rpc.toString();
403 }
404
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300405 /**
406 * Builds a string with comma separated VLAN-IDs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300407 *
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300408 * @param vlanIds the VLAN IDs
409 * @return the string including the VLAN-IDs
410 */
411 private String getVlansString(List<VlanId> vlanIds) {
412 StringBuilder vlansStringBuilder = new StringBuilder();
413
414 for (int i = 0; i < vlanIds.size(); i++) {
415 vlansStringBuilder.append(vlanIds.get(i));
416
417 if (i != vlanIds.size() - 1) {
418 vlansStringBuilder.append(",");
419 }
420 }
421 return vlansStringBuilder.toString();
422 }
423
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300424 /**
425 * Provides the interfaces configured on a device.
426 *
427 * @param deviceId the device ID
428 * @return the list of the configured interfaces
429 */
430 @Override
431 public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300432 return getInterfaces();
433 }
434
435 /**
436 * Provides the interfaces configured on a device.
437 *
438 * @return the list of the configured interfaces
439 */
440 @Override
441 public List<DeviceInterfaceDescription> getInterfaces() {
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300442 NetconfController controller =
443 checkNotNull(handler().get(NetconfController.class));
444
445 NetconfSession session = controller.getDevicesMap().get(handler()
446 .data().deviceId()).getSession();
447 String reply;
448 try {
449 reply = session.requestSync(getConfigBuilder());
450 } catch (NetconfException e) {
451 log.error("Failed to retrieve configuration from device {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300452 handler().data().deviceId(), e);
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300453 return null;
454 }
455
456 return XmlParserCisco.getInterfacesFromConfig(XmlConfigParser.loadXml(
457 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
458 }
459
460 /**
461 * Builds a request for getting configuration from device.
462 *
463 * @return the request string.
464 */
465 private String getConfigBuilder() {
466 StringBuilder rpc =
467 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
468 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
469 rpc.append("<get-config>");
470 rpc.append("<source>");
471 rpc.append("<running/>");
472 rpc.append("</source>");
473 rpc.append("<filter>");
474 rpc.append("<config-format-xml>");
475 rpc.append("</config-format-xml>");
476 rpc.append("</filter>");
477 rpc.append("</get-config>");
478 rpc.append("</rpc>");
479
480 return rpc.toString();
481 }
482
Andreas Papazois92e4a042016-02-24 15:29:30 +0200483}
484