| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.onosproject.drivers.cisco; |
| |
| import org.onlab.packet.VlanId; |
| import org.onosproject.drivers.utilities.XmlConfigParser; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.behaviour.InterfaceConfig; |
| import org.onosproject.net.behaviour.PatchDescription; |
| import org.onosproject.net.behaviour.TunnelDescription; |
| import org.onosproject.net.device.DeviceInterfaceDescription; |
| import org.onosproject.net.driver.AbstractHandlerBehaviour; |
| import org.onosproject.netconf.NetconfController; |
| import org.onosproject.netconf.NetconfException; |
| import org.onosproject.netconf.NetconfSession; |
| import org.slf4j.Logger; |
| |
| import java.io.ByteArrayInputStream; |
| import java.nio.charset.StandardCharsets; |
| import java.util.List; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| import static org.slf4j.LoggerFactory.getLogger; |
| |
| /** |
| * Configures interfaces on Cisco IOS devices. |
| */ |
| public class InterfaceConfigCiscoIosImpl extends AbstractHandlerBehaviour |
| implements InterfaceConfig { |
| |
| private final Logger log = getLogger(getClass()); |
| |
| /** |
| * Adds an access interface to a VLAN. |
| * |
| * @param deviceId the device ID |
| * @param intf the name of the interface |
| * @param vlanId the VLAN ID |
| * @return the result of operation |
| */ |
| @Override |
| public boolean addAccessInterface(DeviceId deviceId, String intf, VlanId vlanId) { |
| return addAccessMode(intf, vlanId); |
| } |
| |
| /** |
| * Adds an access interface to a VLAN. |
| * |
| * @param intf the name of the interface |
| * @param vlanId the VLAN ID |
| * @return the result of operation |
| */ |
| @Override |
| public boolean addAccessMode(String intf, VlanId vlanId) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(addAccessModeBuilder(intf, vlanId)); |
| } catch (NetconfException e) { |
| log.error("Failed to configure VLAN ID {} on device {} interface {}.", |
| vlanId, handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to add an access interface to a VLAN. |
| * |
| * @param intf the name of the interface |
| * @param vlanId the VLAN ID |
| * @return the request string. |
| */ |
| private String addAccessModeBuilder(String intf, VlanId vlanId) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<switchport><access><vlan><VLANIDVLANPortAccessMode>"); |
| rpc.append(vlanId); |
| rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>"); |
| rpc.append("<switchport><mode><access/></mode></switchport>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Removes an access interface to a VLAN. |
| * |
| * @param deviceId the device ID |
| * @param intf the name of the interface |
| * @return the result of operation |
| */ |
| @Override |
| public boolean removeAccessInterface(DeviceId deviceId, String intf) { |
| return removeAccessMode(intf); |
| } |
| |
| /** |
| * Removes an access interface to a VLAN. |
| * |
| * @param intf the name of the interface |
| * @return the result of operation |
| */ |
| @Override |
| public boolean removeAccessMode(String intf) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(removeAccessModeBuilder(intf)); |
| } catch (NetconfException e) { |
| log.error("Failed to remove access mode from device {} interface {}.", |
| handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to remove an access interface from a VLAN. |
| * |
| * @param intf the name of the interface |
| * @return the request string. |
| */ |
| private String removeAccessModeBuilder(String intf) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<switchport operation=\"delete\"><access><vlan><VLANIDVLANPortAccessMode>"); |
| rpc.append("</VLANIDVLANPortAccessMode></vlan></access></switchport>"); |
| rpc.append("<switchport operation=\"delete\"><mode><access/></mode></switchport>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Adds a trunk interface for VLANs. |
| * |
| * @param deviceId the device ID |
| * @param intf the name of the interface |
| * @param vlanIds the VLAN IDs |
| * @return the result of operation |
| */ |
| @Override |
| public boolean addTrunkInterface(DeviceId deviceId, String intf, List<VlanId> vlanIds) { |
| return addTrunkMode(intf, vlanIds); |
| } |
| |
| /** |
| * Adds a trunk interface for VLANs. |
| * |
| * @param intf the name of the interface |
| * @param vlanIds the VLAN IDs |
| * @return the result of operation |
| */ |
| @Override |
| public boolean addTrunkMode(String intf, List<VlanId> vlanIds) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(addTrunkModeBuilder(intf, vlanIds)); |
| } catch (NetconfException e) { |
| log.error("Failed to configure trunk mode for VLAN ID {} on device {} interface {}.", |
| vlanIds, handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to configure an interface as trunk for VLANs. |
| * |
| * @param intf the name of the interface |
| * @param vlanIds the VLAN IDs |
| * @return the request string. |
| */ |
| private String addTrunkModeBuilder(String intf, List<VlanId> vlanIds) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<switchport><trunk><encapsulation><dot1q/></encapsulation>"); |
| rpc.append("</trunk></switchport><switchport><trunk><allowed><vlan>"); |
| rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>"); |
| rpc.append(getVlansString(vlanIds)); |
| rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed></trunk>"); |
| rpc.append("</switchport><switchport><mode><trunk/></mode></switchport>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Removes trunk mode configuration from an interface. |
| * |
| * @param deviceId the device ID |
| * @param intf the name of the interface |
| * @return the result of operation |
| */ |
| @Override |
| public boolean removeTrunkInterface(DeviceId deviceId, String intf) { |
| return removeTrunkMode(intf); |
| } |
| |
| /** |
| * Removes trunk mode configuration from an interface. |
| * |
| * @param intf the name of the interface |
| * @return the result of operation |
| */ |
| @Override |
| public boolean removeTrunkMode(String intf) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(removeTrunkModeBuilder(intf)); |
| } catch (NetconfException e) { |
| log.error("Failed to remove trunk mode from device {} interface {}.", |
| handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to remove trunk mode configuration from an interface. |
| * |
| * @param intf the name of the interface |
| * @return the request string. |
| */ |
| private String removeTrunkModeBuilder(String intf) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<switchport><mode operation=\"delete\"><trunk/></mode></switchport>"); |
| rpc.append("<switchport><trunk operation=\"delete\"><encapsulation>"); |
| rpc.append("<dot1q/></encapsulation></trunk></switchport>"); |
| rpc.append("<switchport><trunk operation=\"delete\"><allowed><vlan>"); |
| rpc.append("<VLANIDsAllowedVLANsPortTrunkingMode>"); |
| rpc.append("</VLANIDsAllowedVLANsPortTrunkingMode></vlan></allowed>"); |
| rpc.append("</trunk></switchport>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Adds a rate limit on an interface. |
| * |
| * @param intf the name of the interface |
| * @param limit the limit as a percentage |
| * @return the result of operation |
| */ |
| @Override |
| public boolean addRateLimit(String intf, short limit) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(addRateLimitBuilder(intf, limit)); |
| } catch (NetconfException e) { |
| log.error("Failed to configure rate limit {}%% on device {} interface {}.", |
| limit, handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to configure an interface with rate limit. |
| * |
| * @param intf the name of the interface |
| * @param limit the limit as a percentage |
| * @return the request string. |
| */ |
| private String addRateLimitBuilder(String intf, short limit) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<srr-queue><bandwidth><limit>"); |
| rpc.append("<EnterBandwidthLimitInterfaceAsPercentage>"); |
| rpc.append(limit); |
| rpc.append("</EnterBandwidthLimitInterfaceAsPercentage>"); |
| rpc.append("</limit></bandwidth></srr-queue>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Removes rate limit from an interface. |
| * |
| * @param intf the name of the interface |
| * @return the result of operation |
| */ |
| @Override |
| public boolean removeRateLimit(String intf) { |
| NetconfController controller = checkNotNull(handler() |
| .get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(removeRateLimitBuilder(intf)); |
| } catch (NetconfException e) { |
| log.error("Failed to remove rate limit from device {} interface {}.", |
| handler().data().deviceId(), intf, e); |
| return false; |
| } |
| |
| return XmlConfigParser.configSuccess(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request to remove a rate limit from an interface. |
| * |
| * @param intf the name of the interface |
| * @return the request string. |
| */ |
| private String removeRateLimitBuilder(String intf) { |
| StringBuilder rpc = new StringBuilder(getOpeningString(intf)); |
| rpc.append("<srr-queue operation=\"delete\"><bandwidth><limit>"); |
| rpc.append("</limit></bandwidth></srr-queue>"); |
| rpc.append(getClosingString()); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Builds the opening of a request for the configuration of an interface. |
| * |
| * @param intf the interface to be configured |
| * @return the opening string |
| */ |
| private String getOpeningString(String intf) { |
| StringBuilder rpc = |
| new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "); |
| rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); |
| rpc.append("<edit-config>"); |
| rpc.append("<target>"); |
| rpc.append("<running/>"); |
| rpc.append("</target>"); |
| rpc.append("<config>"); |
| rpc.append("<xml-config-data>"); |
| rpc.append("<Device-Configuration><interface><Param>"); |
| rpc.append(intf); |
| rpc.append("</Param>"); |
| rpc.append("<ConfigIf-Configuration>"); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Builds the closing of a request for the configuration of an interface. |
| * |
| * @return the closing string |
| */ |
| private String getClosingString() { |
| StringBuilder rpc = new StringBuilder("</ConfigIf-Configuration>"); |
| rpc.append("</interface>"); |
| rpc.append("</Device-Configuration>"); |
| rpc.append("</xml-config-data>"); |
| rpc.append("</config>"); |
| rpc.append("</edit-config>"); |
| rpc.append("</rpc>"); |
| |
| return rpc.toString(); |
| } |
| |
| /** |
| * Builds a string with comma separated VLAN-IDs. |
| * |
| * @param vlanIds the VLAN IDs |
| * @return the string including the VLAN-IDs |
| */ |
| private String getVlansString(List<VlanId> vlanIds) { |
| StringBuilder vlansStringBuilder = new StringBuilder(); |
| |
| for (int i = 0; i < vlanIds.size(); i++) { |
| vlansStringBuilder.append(vlanIds.get(i)); |
| |
| if (i != vlanIds.size() - 1) { |
| vlansStringBuilder.append(","); |
| } |
| } |
| return vlansStringBuilder.toString(); |
| } |
| |
| /** |
| * Provides the interfaces configured on a device. |
| * |
| * @param deviceId the device ID |
| * @return the list of the configured interfaces |
| */ |
| @Override |
| public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) { |
| return getInterfaces(); |
| } |
| |
| /** |
| * Provides the interfaces configured on a device. |
| * |
| * @return the list of the configured interfaces |
| */ |
| @Override |
| public List<DeviceInterfaceDescription> getInterfaces() { |
| NetconfController controller = |
| checkNotNull(handler().get(NetconfController.class)); |
| |
| NetconfSession session = controller.getDevicesMap().get(handler() |
| .data().deviceId()).getSession(); |
| String reply; |
| try { |
| reply = session.requestSync(getConfigBuilder()); |
| } catch (NetconfException e) { |
| log.error("Failed to retrieve configuration from device {}.", |
| handler().data().deviceId(), e); |
| return null; |
| } |
| |
| return XmlParserCisco.getInterfacesFromConfig(XmlConfigParser.loadXml( |
| new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8)))); |
| } |
| |
| /** |
| * Builds a request for getting configuration from device. |
| * |
| * @return the request string. |
| */ |
| private String getConfigBuilder() { |
| StringBuilder rpc = |
| new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "); |
| rpc.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); |
| rpc.append("<get-config>"); |
| rpc.append("<source>"); |
| rpc.append("<running/>"); |
| rpc.append("</source>"); |
| rpc.append("<filter>"); |
| rpc.append("<config-format-xml>"); |
| rpc.append("</config-format-xml>"); |
| rpc.append("</filter>"); |
| rpc.append("</get-config>"); |
| rpc.append("</rpc>"); |
| |
| return rpc.toString(); |
| } |
| |
| @Override |
| public boolean addTunnelMode(String ifaceName, TunnelDescription tunnelDesc) { |
| throw new UnsupportedOperationException("Add tunnel mode is not supported"); |
| } |
| |
| @Override |
| public boolean removeTunnelMode(String ifaceName) { |
| throw new UnsupportedOperationException("Remove tunnel mode is not supported"); |
| } |
| |
| @Override |
| public boolean addPatchMode(String ifaceName, PatchDescription patchDesc) { |
| throw new UnsupportedOperationException("Add patch interface is not supported"); |
| } |
| |
| @Override |
| public boolean removePatchMode(String ifaceName) { |
| throw new UnsupportedOperationException("Remove patch interface is not supported"); |
| } |
| } |
| |