blob: fecd3ef9e5b5b8464ec80378162931d97e9b858d [file] [log] [blame]
Andreas Papazois92e4a042016-02-24 15:29:30 +02001/*
Ray Milkey85267002016-11-16 11:06:35 -08002 * Copyright 2016-present Open Networking Laboratory
Andreas Papazois92e4a042016-02-24 15:29:30 +02003 *
Ray Milkey85267002016-11-16 11:06:35 -08004 * 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.
Andreas Papazois92e4a042016-02-24 15:29:30 +020015 *
16 */
17
18package org.onosproject.drivers.cisco;
19
20import org.onlab.packet.VlanId;
21import org.onosproject.drivers.utilities.XmlConfigParser;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.behaviour.InterfaceConfig;
Hyunsun Moon89478662016-06-09 17:52:34 -070024import org.onosproject.net.behaviour.PatchDescription;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070025import org.onosproject.net.behaviour.TunnelDescription;
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030026import org.onosproject.net.device.DeviceInterfaceDescription;
Andreas Papazois92e4a042016-02-24 15:29:30 +020027import org.onosproject.net.driver.AbstractHandlerBehaviour;
28import org.onosproject.netconf.NetconfController;
29import org.onosproject.netconf.NetconfException;
30import org.onosproject.netconf.NetconfSession;
31import org.slf4j.Logger;
32
33import java.io.ByteArrayInputStream;
34import java.nio.charset.StandardCharsets;
Andreas Papazois59e19bb2016-04-12 13:59:58 +030035import java.util.List;
Andreas Papazois92e4a042016-02-24 15:29:30 +020036
37import static com.google.common.base.Preconditions.checkNotNull;
38import static org.slf4j.LoggerFactory.getLogger;
39
40/**
41 * Configures interfaces on Cisco IOS devices.
42 */
43public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour
44 implements InterfaceConfig {
45
46 private final Logger log = getLogger(getClass());
47
48 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030049 * Adds an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030050 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020051 * @param deviceId the device ID
52 * @param intf the name of the interface
53 * @param vlanId the VLAN ID
54 * @return the result of operation
55 */
56 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +030057 public boolean addAccessInterface(DeviceId deviceId, String intf, VlanId vlanId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030058 return addAccessMode(intf, vlanId);
59 }
60
61 /**
62 * Adds an access interface to a VLAN.
63 *
64 * @param intf the name of the interface
65 * @param vlanId the VLAN ID
66 * @return the result of operation
67 */
68 @Override
69 public boolean addAccessMode(String intf, VlanId vlanId) {
Andreas Papazois92e4a042016-02-24 15:29:30 +020070 NetconfController controller = checkNotNull(handler()
71 .get(NetconfController.class));
72
73 NetconfSession session = controller.getDevicesMap().get(handler()
74 .data().deviceId()).getSession();
75 String reply;
76 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +030077 reply = session.requestSync(addAccessModeBuilder(intf, vlanId));
Andreas Papazois92e4a042016-02-24 15:29:30 +020078 } catch (NetconfException e) {
79 log.error("Failed to configure VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +030080 vlanId, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +020081 return false;
82 }
83
84 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
85 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
86 }
87
88 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +030089 * Builds a request to add an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +030090 *
Andreas Papazois92e4a042016-02-24 15:29:30 +020091 * @param intf the name of the interface
92 * @param vlanId the VLAN ID
93 * @return the request string.
94 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +030095 private String addAccessModeBuilder(String intf, VlanId vlanId) {
96 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +020097 rpc.append("<switchport><access><vlan><VLANIDVLANPortAccessMode>");
98 rpc.append(vlanId);
99 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
100 rpc.append("<switchport><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300101 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200102
103 return rpc.toString();
104 }
105
106 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300107 * Removes an access interface to a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300108 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200109 * @param deviceId the device ID
110 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200111 * @return the result of operation
112 */
113 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300114 public boolean removeAccessInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300115 return removeAccessMode(intf);
116 }
117
118 /**
119 * Removes an access interface to a VLAN.
120 *
121 * @param intf the name of the interface
122 * @return the result of operation
123 */
124 @Override
125 public boolean removeAccessMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200126 NetconfController controller = checkNotNull(handler()
127 .get(NetconfController.class));
128
129 NetconfSession session = controller.getDevicesMap().get(handler()
130 .data().deviceId()).getSession();
131 String reply;
132 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300133 reply = session.requestSync(removeAccessModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200134 } catch (NetconfException e) {
Andreas Papazois827d8d02016-04-15 11:53:16 +0300135 log.error("Failed to remove access mode from device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300136 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200137 return false;
138 }
139
140 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
141 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
142 }
143
144 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300145 * Builds a request to remove an access interface from a VLAN.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300146 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200147 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200148 * @return the request string.
149 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300150 private String removeAccessModeBuilder(String intf) {
151 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200152 rpc.append("<switchport operation=\"delete\"><access><vlan><VLANIDVLANPortAccessMode>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200153 rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>");
154 rpc.append("<switchport operation=\"delete\"><mode><access/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300155 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200156
157 return rpc.toString();
158 }
159
160 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300161 * Adds a trunk interface for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300162 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200163 * @param deviceId the device ID
164 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300165 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200166 * @return the result of operation
167 */
168 @Override
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300169 public boolean addTrunkInterface(DeviceId deviceId, String intf, List<VlanId> vlanIds) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300170 return addTrunkMode(intf, vlanIds);
171 }
172
173 /**
174 * Adds a trunk interface for VLANs.
175 *
176 * @param intf the name of the interface
177 * @param vlanIds the VLAN IDs
178 * @return the result of operation
179 */
180 @Override
181 public boolean addTrunkMode(String intf, List<VlanId> vlanIds) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200182 NetconfController controller = checkNotNull(handler()
183 .get(NetconfController.class));
184
185 NetconfSession session = controller.getDevicesMap().get(handler()
186 .data().deviceId()).getSession();
187 String reply;
188 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300189 reply = session.requestSync(addTrunkModeBuilder(intf, vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200190 } catch (NetconfException e) {
191 log.error("Failed to configure trunk mode for VLAN ID {} on device {} interface {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300192 vlanIds, handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200193 return false;
194 }
195
196 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
197 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
198 }
199
200 /**
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300201 * Builds a request to configure an interface as trunk for VLANs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300202 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200203 * @param intf the name of the interface
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300204 * @param vlanIds the VLAN IDs
Andreas Papazois92e4a042016-02-24 15:29:30 +0200205 * @return the request string.
206 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300207 private String addTrunkModeBuilder(String intf, List<VlanId> vlanIds) {
208 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200209 rpc.append("<switchport><trunk><encapsulation><dot1q/></encapsulation>");
210 rpc.append("</trunk></switchport><switchport><trunk><allowed><vlan>");
211 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300212 rpc.append(getVlansString(vlanIds));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200213 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk>");
214 rpc.append("</switchport><switchport><mode><trunk/></mode></switchport>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300215 rpc.append(getClosingString());
Andreas Papazois92e4a042016-02-24 15:29:30 +0200216
217 return rpc.toString();
218 }
219
220 /**
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300221 * Removes trunk mode configuration from an interface.
222 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200223 * @param deviceId the device ID
224 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200225 * @return the result of operation
226 */
227 @Override
Andreas Papazois827d8d02016-04-15 11:53:16 +0300228 public boolean removeTrunkInterface(DeviceId deviceId, String intf) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300229 return removeTrunkMode(intf);
230 }
231
232 /**
233 * Removes trunk mode configuration from an interface.
234 *
235 * @param intf the name of the interface
236 * @return the result of operation
237 */
238 @Override
239 public boolean removeTrunkMode(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200240 NetconfController controller = checkNotNull(handler()
241 .get(NetconfController.class));
242
243 NetconfSession session = controller.getDevicesMap().get(handler()
244 .data().deviceId()).getSession();
245 String reply;
246 try {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300247 reply = session.requestSync(removeTrunkModeBuilder(intf));
Andreas Papazois92e4a042016-02-24 15:29:30 +0200248 } catch (NetconfException e) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300249 log.error("Failed to remove trunk mode from device {} interface {}.",
250 handler().data().deviceId(), intf, e);
Andreas Papazois92e4a042016-02-24 15:29:30 +0200251 return false;
252 }
253
254 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
255 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
256}
257
258 /**
Andreas Papazois827d8d02016-04-15 11:53:16 +0300259 * Builds a request to remove trunk mode configuration from an interface.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300260 *
Andreas Papazois92e4a042016-02-24 15:29:30 +0200261 * @param intf the name of the interface
Andreas Papazois92e4a042016-02-24 15:29:30 +0200262 * @return the request string.
263 */
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300264 private String removeTrunkModeBuilder(String intf) {
265 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
266 rpc.append("<switchport><mode operation=\"delete\"><trunk/></mode></switchport>");
267 rpc.append("<switchport><trunk operation=\"delete\"><encapsulation>");
268 rpc.append("<dot1q/></encapsulation></trunk></switchport>");
269 rpc.append("<switchport><trunk operation=\"delete\"><allowed><vlan>");
270 rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>");
271 rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed>");
272 rpc.append("</trunk></switchport>");
273 rpc.append(getClosingString());
274
275 return rpc.toString();
276 }
277
278 /**
279 * Adds a rate limit on an interface.
280 *
281 * @param intf the name of the interface
282 * @param limit the limit as a percentage
283 * @return the result of operation
284 */
285 @Override
286 public boolean addRateLimit(String intf, short limit) {
287 NetconfController controller = checkNotNull(handler()
288 .get(NetconfController.class));
289
290 NetconfSession session = controller.getDevicesMap().get(handler()
291 .data().deviceId()).getSession();
292 String reply;
293 try {
294 reply = session.requestSync(addRateLimitBuilder(intf, limit));
295 } catch (NetconfException e) {
296 log.error("Failed to configure rate limit {}%% on device {} interface {}.",
297 limit, handler().data().deviceId(), intf, e);
298 return false;
299 }
300
301 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
302 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
303 }
304
305 /**
306 * Builds a request to configure an interface with rate limit.
307 *
308 * @param intf the name of the interface
309 * @param limit the limit as a percentage
310 * @return the request string.
311 */
312 private String addRateLimitBuilder(String intf, short limit) {
313 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
314 rpc.append("<srr-queue><bandwidth><limit>");
315 rpc.append("<EnterBandwidthLimitInterfaceAsPercentage>");
316 rpc.append(limit);
317 rpc.append("</EnterBandwidthLimitInterfaceAsPercentage>");
318 rpc.append("</limit></bandwidth></srr-queue>");
319 rpc.append(getClosingString());
320
321 return rpc.toString();
322 }
323
324 /**
325 * Removes rate limit from an interface.
326 *
327 * @param intf the name of the interface
328 * @return the result of operation
329 */
330 @Override
331 public boolean removeRateLimit(String intf) {
332 NetconfController controller = checkNotNull(handler()
333 .get(NetconfController.class));
334
335 NetconfSession session = controller.getDevicesMap().get(handler()
336 .data().deviceId()).getSession();
337 String reply;
338 try {
339 reply = session.requestSync(removeRateLimitBuilder(intf));
340 } catch (NetconfException e) {
341 log.error("Failed to remove rate limit from device {} interface {}.",
342 handler().data().deviceId(), intf, e);
343 return false;
344 }
345
346 return XmlConfigParser.configSuccess(XmlConfigParser.loadXml(
347 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
348 }
349
350 /**
351 * Builds a request to remove a rate limit from an interface.
352 *
353 * @param intf the name of the interface
354 * @return the request string.
355 */
356 private String removeRateLimitBuilder(String intf) {
357 StringBuilder rpc = new StringBuilder(getOpeningString(intf));
358 rpc.append("<srr-queue operation=\"delete\"><bandwidth><limit>");
359 rpc.append("</limit></bandwidth></srr-queue>");
360 rpc.append(getClosingString());
361
362 return rpc.toString();
363 }
364
365 /**
366 * Builds the opening of a request for the configuration of an interface.
367 *
368 * @param intf the interface to be configured
369 * @return the opening string
370 */
371 private String getOpeningString(String intf) {
Andreas Papazois92e4a042016-02-24 15:29:30 +0200372 StringBuilder rpc =
373 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
374 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
375 rpc.append("<edit-config>");
376 rpc.append("<target>");
377 rpc.append("<running/>");
378 rpc.append("</target>");
379 rpc.append("<config>");
380 rpc.append("<xml-config-data>");
381 rpc.append("<Device-Configuration><interface><Param>");
382 rpc.append(intf);
383 rpc.append("</Param>");
384 rpc.append("<ConfigIf-Configuration>");
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300385
386 return rpc.toString();
387 }
388
389 /**
390 * Builds the closing of a request for the configuration of an interface.
391 *
392 * @return the closing string
393 */
394 private String getClosingString() {
395 StringBuilder rpc = new StringBuilder("</ConfigIf-Configuration>");
Andreas Papazois92e4a042016-02-24 15:29:30 +0200396 rpc.append("</interface>");
397 rpc.append("</Device-Configuration>");
398 rpc.append("</xml-config-data>");
399 rpc.append("</config>");
400 rpc.append("</edit-config>");
401 rpc.append("</rpc>");
402
403 return rpc.toString();
404 }
405
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300406 /**
407 * Builds a string with comma separated VLAN-IDs.
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300408 *
Andreas Papazois59e19bb2016-04-12 13:59:58 +0300409 * @param vlanIds the VLAN IDs
410 * @return the string including the VLAN-IDs
411 */
412 private String getVlansString(List<VlanId> vlanIds) {
413 StringBuilder vlansStringBuilder = new StringBuilder();
414
415 for (int i = 0; i < vlanIds.size(); i++) {
416 vlansStringBuilder.append(vlanIds.get(i));
417
418 if (i != vlanIds.size() - 1) {
419 vlansStringBuilder.append(",");
420 }
421 }
422 return vlansStringBuilder.toString();
423 }
424
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300425 /**
426 * Provides the interfaces configured on a device.
427 *
428 * @param deviceId the device ID
429 * @return the list of the configured interfaces
430 */
431 @Override
432 public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) {
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300433 return getInterfaces();
434 }
435
436 /**
437 * Provides the interfaces configured on a device.
438 *
439 * @return the list of the configured interfaces
440 */
441 @Override
442 public List<DeviceInterfaceDescription> getInterfaces() {
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300443 NetconfController controller =
444 checkNotNull(handler().get(NetconfController.class));
445
446 NetconfSession session = controller.getDevicesMap().get(handler()
447 .data().deviceId()).getSession();
448 String reply;
449 try {
450 reply = session.requestSync(getConfigBuilder());
451 } catch (NetconfException e) {
452 log.error("Failed to retrieve configuration from device {}.",
Andreas Papazois34a82cf2016-04-27 09:09:13 +0300453 handler().data().deviceId(), e);
Andreas Papazois1ed54cf2016-05-04 16:22:40 +0300454 return null;
455 }
456
457 return XmlParserCisco.getInterfacesFromConfig(XmlConfigParser.loadXml(
458 new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
459 }
460
461 /**
462 * Builds a request for getting configuration from device.
463 *
464 * @return the request string.
465 */
466 private String getConfigBuilder() {
467 StringBuilder rpc =
468 new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
469 rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
470 rpc.append("<get-config>");
471 rpc.append("<source>");
472 rpc.append("<running/>");
473 rpc.append("</source>");
474 rpc.append("<filter>");
475 rpc.append("<config-format-xml>");
476 rpc.append("</config-format-xml>");
477 rpc.append("</filter>");
478 rpc.append("</get-config>");
479 rpc.append("</rpc>");
480
481 return rpc.toString();
482 }
483
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700484 @Override
485 public boolean addTunnelMode(String ifaceName, TunnelDescription tunnelDesc) {
486 throw new UnsupportedOperationException("Add tunnel mode is not supported");
487 }
488
489 @Override
490 public boolean removeTunnelMode(String ifaceName) {
491 throw new UnsupportedOperationException("Remove tunnel mode is not supported");
492 }
Hyunsun Moon89478662016-06-09 17:52:34 -0700493
494 @Override
495 public boolean addPatchMode(String ifaceName, PatchDescription patchDesc) {
496 throw new UnsupportedOperationException("Add patch interface is not supported");
497 }
498
499 @Override
500 public boolean removePatchMode(String ifaceName) {
501 throw new UnsupportedOperationException("Remove patch interface is not supported");
502 }
Andreas Papazois92e4a042016-02-24 15:29:30 +0200503}
504