blob: 6c6e9914544b76f3bfd808bd14ff2183b815d814 [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;
Hyunsun Moon89478662016-06-09 17:52:34 -070025import org.onosproject.net.behaviour.PatchDescription;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070026import org.onosproject.net.behaviour.TunnelDescription;
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030027import org.onosproject.net.device.DeviceInterfaceDescription;
Andreas Papazois92e4a042016-02-24 15:29:30 +020028import org.onosproject.net.driver.AbstractHandlerBehaviour;
29import org.onosproject.netconf.NetconfController;
30import org.onosproject.netconf.NetconfException;
31import org.onosproject.netconf.NetconfSession;
32import org.slf4j.Logger;
33
34import java.io.ByteArrayInputStream;
35import java.nio.charset.StandardCharsets;
Andreas Papazois59e19bb2016-04-12 13:59:58 +030036import java.util.List;
Andreas Papazois92e4a042016-02-24 15:29:30 +020037
38import static com.google.common.base.Preconditions.checkNotNull;
39import static org.slf4j.LoggerFactory.getLogger;
40
41/**
42 * Configures interfaces on Cisco IOS devices.
43 */
44public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour
45 implements InterfaceConfig {
46
47 private final Logger log = getLogger(getClass());
48
49 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030050 * Adds an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030051 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020052 * @param deviceId the device ID
53 * @param intf the name of the interface
54 * @param vlanId the VLAN ID
55 * @return the result of operation
56 */
57 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +030058 public boolean addAccessInterface(DeviceId deviceId, String intf, VlanId vlanId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030059 return addAccessMode(intf, vlanId);
60 }
61
62 /**
63 * Adds an access interface to a VLAN.
64 *
65 * @param intf the name of the interface
66 * @param vlanId the VLAN ID
67 * @return the result of operation
68 */
69 @Override
70 public boolean addAccessMode(String intf, VlanId vlanId) {
Andreas Papazois92e4a042016-02-24 15:29:30 +020071 NetconfController controller = checkNotNull(handler()
72 .get(NetconfController.class));
73
74 NetconfSession session = controller.getDevicesMap().get(handler()
75 .data().deviceId()).getSession();
76 String reply;
77 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030078 reply = session.requestSync(addAccessModeBuilder(intf, vlanId));
Andreas Papazois92e4a042016-02-24 15:29:30 +020079 } catch (NetconfException e) {
80 log.error("Failed to configure VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +030081 vlanId, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +020082 return false;
83 }
84
85 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
86 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
87 }
88
89 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030090 * Builds a request to add an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030091 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020092 * @param intf the name of the interface
93 * @param vlanId the VLAN ID
94 * @return the request string.
95 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +030096 private String addAccessModeBuilder(String intf, VlanId vlanId) {
97 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +020098 rpc.append("<switchport><access><vlan><VLANIDVLANPortAccessMode>");
99 rpc.append(vlanId);
100 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
101 rpc.append("<switchport><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300102 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200103
104 return rpc.toString();
105 }
106
107 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300108 * Removes an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300109 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200110 * @param deviceId the device ID
111 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200112 * @return the result of operation
113 */
114 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300115 public boolean removeAccessInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300116 return removeAccessMode(intf);
117 }
118
119 /**
120 * Removes an access interface to a VLAN.
121 *
122 * @param intf the name of the interface
123 * @return the result of operation
124 */
125 @Override
126 public boolean removeAccessMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200127 NetconfController controller = checkNotNull(handler()
128 .get(NetconfController.class));
129
130 NetconfSession session = controller.getDevicesMap().get(handler()
131 .data().deviceId()).getSession();
132 String reply;
133 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300134 reply = session.requestSync(removeAccessModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200135 } catch (NetconfException e) {
Andreas Papazois827d8d02016-04-15 11:53:16 +0300136 log.error("Failed to remove access mode from device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300137 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200138 return false;
139 }
140
141 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
142 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
143 }
144
145 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300146 * Builds a request to remove an access interface from a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300147 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200148 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200149 * @return the request string.
150 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300151 private String removeAccessModeBuilder(String intf) {
152 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200153 rpc.append("<switchport operation=\"delete\"><access><vlan><VLANIDVLANPortAccessMode>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200154 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
155 rpc.append("<switchport operation=\"delete\"><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300156 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200157
158 return rpc.toString();
159 }
160
161 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300162 * Adds a trunk interface for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300163 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200164 * @param deviceId the device ID
165 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300166 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200167 * @return the result of operation
168 */
169 @Override
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300170 public boolean addTrunkInterface(DeviceId deviceId, String intf, List<VlanId> vlanIds) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300171 return addTrunkMode(intf, vlanIds);
172 }
173
174 /**
175 * Adds a trunk interface for VLANs.
176 *
177 * @param intf the name of the interface
178 * @param vlanIds the VLAN IDs
179 * @return the result of operation
180 */
181 @Override
182 public boolean addTrunkMode(String intf, List<VlanId> vlanIds) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200183 NetconfController controller = checkNotNull(handler()
184 .get(NetconfController.class));
185
186 NetconfSession session = controller.getDevicesMap().get(handler()
187 .data().deviceId()).getSession();
188 String reply;
189 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300190 reply = session.requestSync(addTrunkModeBuilder(intf, vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200191 } catch (NetconfException e) {
192 log.error("Failed to configure trunk mode for VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300193 vlanIds, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200194 return false;
195 }
196
197 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
198 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
199 }
200
201 /**
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300202 * Builds a request to configure an interface as trunk for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300203 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200204 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300205 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200206 * @return the request string.
207 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300208 private String addTrunkModeBuilder(String intf, List<VlanId> vlanIds) {
209 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200210 rpc.append("<switchport><trunk><encapsulation><dot1q/></encapsulation>");
211 rpc.append("</trunk></switchport><switchport><trunk><allowed><vlan>");
212 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300213 rpc.append(getVlansString(vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200214 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk>");
215 rpc.append("</switchport><switchport><mode><trunk/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300216 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200217
218 return rpc.toString();
219 }
220
221 /**
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300222 * Removes trunk mode configuration from an interface.
223 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200224 * @param deviceId the device ID
225 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200226 * @return the result of operation
227 */
228 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300229 public boolean removeTrunkInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300230 return removeTrunkMode(intf);
231 }
232
233 /**
234 * Removes trunk mode configuration from an interface.
235 *
236 * @param intf the name of the interface
237 * @return the result of operation
238 */
239 @Override
240 public boolean removeTrunkMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200241 NetconfController controller = checkNotNull(handler()
242 .get(NetconfController.class));
243
244 NetconfSession session = controller.getDevicesMap().get(handler()
245 .data().deviceId()).getSession();
246 String reply;
247 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300248 reply = session.requestSync(removeTrunkModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200249 } catch (NetconfException e) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300250 log.error("Failed to remove trunk mode from device {} interface {}.",
251 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200252 return false;
253 }
254
255 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
256 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
257}
258
259 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300260 * Builds a request to remove trunk mode configuration from an interface.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300261 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200262 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200263 * @return the request string.
264 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300265 private String removeTrunkModeBuilder(String intf) {
266 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
267 rpc.append("<switchport><mode operation=\"delete\"><trunk/></mode></switchport>");
268 rpc.append("<switchport><trunk operation=\"delete\"><encapsulation>");
269 rpc.append("<dot1q/></encapsulation></trunk></switchport>");
270 rpc.append("<switchport><trunk operation=\"delete\"><allowed><vlan>");
271 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
272 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed>");
273 rpc.append("</trunk></switchport>");
274 rpc.append(getClosingString());
275
276 return rpc.toString();
277 }
278
279 /**
280 * Adds a rate limit on an interface.
281 *
282 * @param intf the name of the interface
283 * @param limit the limit as a percentage
284 * @return the result of operation
285 */
286 @Override
287 public boolean addRateLimit(String intf, short limit) {
288 NetconfController controller = checkNotNull(handler()
289 .get(NetconfController.class));
290
291 NetconfSession session = controller.getDevicesMap().get(handler()
292 .data().deviceId()).getSession();
293 String reply;
294 try {
295 reply = session.requestSync(addRateLimitBuilder(intf, limit));
296 } catch (NetconfException e) {
297 log.error("Failed to configure rate limit {}%% on device {} interface {}.",
298 limit, handler().data().deviceId(), intf, e);
299 return false;
300 }
301
302 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
303 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
304 }
305
306 /**
307 * Builds a request to configure an interface with rate limit.
308 *
309 * @param intf the name of the interface
310 * @param limit the limit as a percentage
311 * @return the request string.
312 */
313 private String addRateLimitBuilder(String intf, short limit) {
314 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
315 rpc.append("<srr-queue><bandwidth><limit>");
316 rpc.append("<EnterBandwidthLimitInterfaceAsPercentage>");
317 rpc.append(limit);
318 rpc.append("</EnterBandwidthLimitInterfaceAsPercentage>");
319 rpc.append("</limit></bandwidth></srr-queue>");
320 rpc.append(getClosingString());
321
322 return rpc.toString();
323 }
324
325 /**
326 * Removes rate limit from an interface.
327 *
328 * @param intf the name of the interface
329 * @return the result of operation
330 */
331 @Override
332 public boolean removeRateLimit(String intf) {
333 NetconfController controller = checkNotNull(handler()
334 .get(NetconfController.class));
335
336 NetconfSession session = controller.getDevicesMap().get(handler()
337 .data().deviceId()).getSession();
338 String reply;
339 try {
340 reply = session.requestSync(removeRateLimitBuilder(intf));
341 } catch (NetconfException e) {
342 log.error("Failed to remove rate limit from device {} interface {}.",
343 handler().data().deviceId(), intf, e);
344 return false;
345 }
346
347 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
348 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
349 }
350
351 /**
352 * Builds a request to remove a rate limit from an interface.
353 *
354 * @param intf the name of the interface
355 * @return the request string.
356 */
357 private String removeRateLimitBuilder(String intf) {
358 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
359 rpc.append("<srr-queue operation=\"delete\"><bandwidth><limit>");
360 rpc.append("</limit></bandwidth></srr-queue>");
361 rpc.append(getClosingString());
362
363 return rpc.toString();
364 }
365
366 /**
367 * Builds the opening of a request for the configuration of an interface.
368 *
369 * @param intf the interface to be configured
370 * @return the opening string
371 */
372 private String getOpeningString(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200373 StringBuilder rpc =
374 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
375 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
376 rpc.append("<edit-config>");
377 rpc.append("<target>");
378 rpc.append("<running/>");
379 rpc.append("</target>");
380 rpc.append("<config>");
381 rpc.append("<xml-config-data>");
382 rpc.append("<Device-Configuration><interface><Param>");
383 rpc.append(intf);
384 rpc.append("</Param>");
385 rpc.append("<ConfigIf-Configuration>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300386
387 return rpc.toString();
388 }
389
390 /**
391 * Builds the closing of a request for the configuration of an interface.
392 *
393 * @return the closing string
394 */
395 private String getClosingString() {
396 StringBuilder rpc = new StringBuilder("</ConfigIf-Configuration>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200397 rpc.append("</interface>");
398 rpc.append("</Device-Configuration>");
399 rpc.append("</xml-config-data>");
400 rpc.append("</config>");
401 rpc.append("</edit-config>");
402 rpc.append("</rpc>");
403
404 return rpc.toString();
405 }
406
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300407 /**
408 * Builds a string with comma separated VLAN-IDs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300409 *
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300410 * @param vlanIds the VLAN IDs
411 * @return the string including the VLAN-IDs
412 */
413 private String getVlansString(List<VlanId> vlanIds) {
414 StringBuilder vlansStringBuilder = new StringBuilder();
415
416 for (int i = 0; i < vlanIds.size(); i++) {
417 vlansStringBuilder.append(vlanIds.get(i));
418
419 if (i != vlanIds.size() - 1) {
420 vlansStringBuilder.append(",");
421 }
422 }
423 return vlansStringBuilder.toString();
424 }
425
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300426 /**
427 * Provides the interfaces configured on a device.
428 *
429 * @param deviceId the device ID
430 * @return the list of the configured interfaces
431 */
432 @Override
433 public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300434 return getInterfaces();
435 }
436
437 /**
438 * Provides the interfaces configured on a device.
439 *
440 * @return the list of the configured interfaces
441 */
442 @Override
443 public List<DeviceInterfaceDescription> getInterfaces() {
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300444 NetconfController controller =
445 checkNotNull(handler().get(NetconfController.class));
446
447 NetconfSession session = controller.getDevicesMap().get(handler()
448 .data().deviceId()).getSession();
449 String reply;
450 try {
451 reply = session.requestSync(getConfigBuilder());
452 } catch (NetconfException e) {
453 log.error("Failed to retrieve configuration from device {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300454 handler().data().deviceId(), e);
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300455 return null;
456 }
457
458 return XmlParserCisco.getInterfacesFromConfig(XmlConfigParser.loadXml(
459 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
460 }
461
462 /**
463 * Builds a request for getting configuration from device.
464 *
465 * @return the request string.
466 */
467 private String getConfigBuilder() {
468 StringBuilder rpc =
469 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
470 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
471 rpc.append("<get-config>");
472 rpc.append("<source>");
473 rpc.append("<running/>");
474 rpc.append("</source>");
475 rpc.append("<filter>");
476 rpc.append("<config-format-xml>");
477 rpc.append("</config-format-xml>");
478 rpc.append("</filter>");
479 rpc.append("</get-config>");
480 rpc.append("</rpc>");
481
482 return rpc.toString();
483 }
484
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700485 @Override
486 public boolean addTunnelMode(String ifaceName, TunnelDescription tunnelDesc) {
487 throw new UnsupportedOperationException("Add tunnel mode is not supported");
488 }
489
490 @Override
491 public boolean removeTunnelMode(String ifaceName) {
492 throw new UnsupportedOperationException("Remove tunnel mode is not supported");
493 }
Hyunsun Moon89478662016-06-09 17:52:34 -0700494
495 @Override
496 public boolean addPatchMode(String ifaceName, PatchDescription patchDesc) {
497 throw new UnsupportedOperationException("Add patch interface is not supported");
498 }
499
500 @Override
501 public boolean removePatchMode(String ifaceName) {
502 throw new UnsupportedOperationException("Remove patch interface is not supported");
503 }
Andreas Papazois92e4a042016-02-24 15:29:30 +0200504}
505