blob: fecd3ef9e5b5b8464ec80378162931d97e9b858d [file] [log] [blame]
/*
* 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");
}
}