blob: 1ff2c33cc370fb29804d3a0065ed6c5f480464f7 [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.provider.isis.topology.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onlab.util.Bandwidth;
import org.onosproject.isis.controller.IsisController;
import org.onosproject.isis.controller.topology.IsisLink;
import org.onosproject.isis.controller.topology.IsisLinkListener;
import org.onosproject.isis.controller.topology.IsisLinkTed;
import org.onosproject.isis.controller.topology.IsisRouter;
import org.onosproject.isis.controller.topology.IsisRouterId;
import org.onosproject.isis.controller.topology.IsisRouterListener;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BandwidthCapacity;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which advertises device descriptions to the core.
*/
@Component(immediate = true)
public class IsisTopologyProvider extends AbstractProvider implements DeviceProvider, LinkProvider {
public static final long PSEUDO_PORT = 0xffffffff;
public static final String ADMINISTRATIVEGROUP = "administrativeGroup";
public static final String TE_METRIC = "teMetric";
public static final String MAXRESERVABLEBANDWIDTH = "maxReservableBandwidth";
public static final String ROUTERID = "routerId";
public static final String NEIGHBORID = "neighborId";
private static final Logger log = getLogger(IsisTopologyProvider.class);
// Default values for tunable parameters
private static final String UNKNOWN = "unknown";
final InternalTopologyProvider listener = new InternalTopologyProvider();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceProviderRegistry deviceProviderRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkProviderRegistry linkProviderRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IsisController controller;
//This Interface that defines how this provider can interact with the core.
private LinkProviderService linkProviderService;
// The interface that defines how this Provider can interact with the core
private DeviceProviderService deviceProviderService;
private HashMap<DeviceId, List<PortDescription>> portMap = new HashMap<>();
/**
* Creates an ISIS device provider.
*/
public IsisTopologyProvider() {
super(new ProviderId("l3", "org.onosproject.provider.isis"));
}
@Activate
public void activate() {
deviceProviderService = deviceProviderRegistry.register(this);
linkProviderService = linkProviderRegistry.register(this);
controller.addRouterListener(listener);
controller.addLinkListener(listener);
log.debug("IsisDeviceProvider::activate...!!!!");
}
@Deactivate
public void deactivate() {
log.debug("IsisDeviceProvider::deactivate...!!!!");
deviceProviderRegistry.unregister(this);
deviceProviderService = null;
linkProviderRegistry.unregister(this);
linkProviderService = null;
controller.removeRouterListener(listener);
controller.removeLinkListener(listener);
}
@Override
public void triggerProbe(DeviceId deviceId) {
log.debug("IsisDeviceProvider::triggerProbe...!!!!");
}
@Override
public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
log.debug("IsisDeviceProvider::roleChanged...!!!!");
}
@Override
public boolean isReachable(DeviceId deviceId) {
log.debug("IsisDeviceProvider::isReachable...!!!!");
return true;
}
@Override
public void changePortState(DeviceId deviceId, PortNumber portNumber, boolean enable) {
log.debug("IsisDeviceProvider::changePortState...!!!!");
}
/**
* Builds link description.
*
* @param isisLink ISIS link instance
* @return link description
*/
private LinkDescription buildLinkDes(IsisLink isisLink) {
long srcAddress = 0;
long dstAddress = 0;
boolean localPseduo = false;
boolean remotePseduo = false;
String localSystemId = isisLink.localSystemId();
String remoteSystemId = isisLink.remoteSystemId();
//Changing of port numbers
if (isisLink.interfaceIp() != null) {
//srcAddress = isisLink.interfaceIp().toInt();
srcAddress = (long) Long.parseUnsignedLong(Integer.toBinaryString(isisLink.interfaceIp().toInt()), 2);
}
if (isisLink.neighborIp() != null) {
//dstAddress = isisLink.neighborIp().toInt();
dstAddress = (long) Long.parseUnsignedLong(Integer.toBinaryString(isisLink.neighborIp().toInt()), 2);
}
DeviceId srcId = DeviceId.deviceId(IsisRouterId.uri(localSystemId));
DeviceId dstId = DeviceId.deviceId(IsisRouterId.uri(remoteSystemId));
if (checkIsDis(isisLink.localSystemId())) {
localPseduo = true;
} else if (checkIsDis(isisLink.remoteSystemId())) {
remotePseduo = true;
} else {
log.debug("IsisDeviceProvider::buildLinkDes : unknown type.!");
}
if (localPseduo && srcAddress == 0) {
srcAddress = PSEUDO_PORT;
} else if (remotePseduo && dstAddress == 0) {
dstAddress = PSEUDO_PORT;
}
ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));
DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
if (isisLink != null) {
annotationBuilder = buildAnnotations(annotationBuilder, isisLink);
}
return new DefaultLinkDescription(src, dst, Link.Type.DIRECT, false, annotationBuilder.build());
}
/**
* Return the DIS value from the systemId.
*
* @param systemId system Id.
* @return return true if DIS else false
*/
public static boolean checkIsDis(String systemId) {
StringTokenizer stringTokenizer = new StringTokenizer(systemId, "." + "-");
int count = 0;
while (stringTokenizer.hasMoreTokens()) {
String str = stringTokenizer.nextToken();
if (count == 3) {
int x = Integer.parseInt(str);
if (x > 0) {
return true;
}
}
count++;
}
return false;
}
/**
* Builds port description.
*
* @param deviceId device ID for the port
* @param portNumber port number of the link
* @return list of port description
*/
private List<PortDescription> buildPortDescriptions(DeviceId deviceId,
PortNumber portNumber) {
List<PortDescription> portList;
if (portMap.containsKey(deviceId)) {
portList = portMap.get(deviceId);
} else {
portList = new ArrayList<>();
}
if (portNumber != null) {
PortDescription portDescriptions = new DefaultPortDescription(portNumber, true);
portList.add(portDescriptions);
}
portMap.put(deviceId, portList);
return portList;
}
/**
* Builds the annotation details.
*
* @param annotationBuilder default annotation builder instance
* @param isisLink ISIS link instance
* @return annotation builder instance
*/
private DefaultAnnotations.Builder buildAnnotations(DefaultAnnotations.Builder annotationBuilder,
IsisLink isisLink) {
int administrativeGroup = 0;
long teMetric = 0;
Bandwidth maxReservableBandwidth = Bandwidth.bps(0);
String routerId = null;
String neighborId = null;
//TE Info
IsisLinkTed isisLinkTed = isisLink.linkTed();
log.info("Ted Information: {}", isisLinkTed.toString());
administrativeGroup = isisLinkTed.administrativeGroup();
teMetric = isisLinkTed.teDefaultMetric();
maxReservableBandwidth = isisLinkTed.maximumReservableLinkBandwidth();
routerId = isisLink.localSystemId();
neighborId = isisLink.remoteSystemId();
annotationBuilder.set(ADMINISTRATIVEGROUP, String.valueOf(administrativeGroup));
annotationBuilder.set(TE_METRIC, String.valueOf(teMetric));
annotationBuilder.set(MAXRESERVABLEBANDWIDTH, String.valueOf(maxReservableBandwidth));
annotationBuilder.set(ROUTERID, String.valueOf(routerId));
annotationBuilder.set(NEIGHBORID, String.valueOf(neighborId));
return annotationBuilder;
}
/**
* Internal device provider implementation.
*/
private class InternalTopologyProvider implements IsisRouterListener, IsisLinkListener {
@Override
public void routerAdded(IsisRouter isisRouter) {
String systemId = isisRouter.systemId();
log.info("Added device {}", systemId);
DeviceId deviceId = DeviceId.deviceId(IsisRouterId.uri(systemId));
Device.Type deviceType = Device.Type.ROUTER;
//If our routerType is Dr or Bdr type is PSEUDO
if (isisRouter.isDis()) {
deviceType = Device.Type.ROUTER;
} else {
deviceType = Device.Type.VIRTUAL;
}
ChassisId cId = new ChassisId();
DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
newBuilder.set(AnnotationKeys.TYPE, "L3");
newBuilder.set("RouterId", systemId);
DeviceDescription description =
new DefaultDeviceDescription(IsisRouterId.uri(systemId), deviceType, UNKNOWN, UNKNOWN, UNKNOWN,
UNKNOWN, cId, newBuilder.build());
deviceProviderService.deviceConnected(deviceId, description);
System.out.println("Device added: " + systemId);
}
@Override
public void routerRemoved(IsisRouter isisRouter) {
String systemId = isisRouter.systemId();
log.info("Delete device {}", systemId);
DeviceId deviceId = DeviceId.deviceId(IsisRouterId.uri(systemId));
if (deviceProviderService == null) {
return;
}
deviceProviderService.deviceDisconnected(deviceId);
log.info("delete device {}", systemId);
}
@Override
public void addLink(IsisLink isisLink) {
log.debug("Addlink {}", isisLink.localSystemId());
LinkDescription linkDes = buildLinkDes(isisLink);
//Updating ports of the link
//If already link exists, return
if (linkService.getLink(linkDes.src(), linkDes.dst()) != null || linkProviderService == null) {
return;
}
ConnectPoint destconnectPoint = linkDes.dst();
PortNumber destport = destconnectPoint.port();
if (destport.toLong() != 0) {
deviceProviderService.updatePorts(linkDes.src().deviceId(),
buildPortDescriptions(linkDes.src().deviceId(),
linkDes.src().port()));
deviceProviderService.updatePorts(linkDes.dst().deviceId(),
buildPortDescriptions(linkDes.dst().deviceId(),
linkDes.dst().port()));
registerBandwidth(linkDes, isisLink);
linkProviderService.linkDetected(linkDes);
System.out.println("link desc " + linkDes.toString());
}
}
@Override
public void deleteLink(IsisLink isisLink) {
log.debug("Delete link {}", isisLink.localSystemId());
if (linkProviderService == null) {
return;
}
LinkDescription linkDes = buildLinkDes(isisLink);
linkProviderService.linkVanished(linkDes);
}
/**
* Registers the bandwidth for source and destination points.
*
* @param linkDes link description instance
* @param isisLink ISIS link instance
*/
private void registerBandwidth(LinkDescription linkDes, IsisLink isisLink) {
if (isisLink == null) {
log.error("Could not able to register bandwidth ");
return;
}
IsisLinkTed isisLinkTed = isisLink.linkTed();
Bandwidth maxReservableBw = isisLinkTed.maximumReservableLinkBandwidth();
if (maxReservableBw != null) {
if (maxReservableBw.compareTo(Bandwidth.bps(0)) == 0) {
return;
}
//Configure bandwidth for src and dst port
BandwidthCapacity config = networkConfigService.addConfig(linkDes.src(), BandwidthCapacity.class);
config.capacity(maxReservableBw).apply();
config = networkConfigService.addConfig(linkDes.dst(), BandwidthCapacity.class);
config.capacity(maxReservableBw).apply();
}
}
}
}