| /* |
| * Copyright 2016-present Open Networking Foundation |
| * |
| * 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.osgi.service.component.annotations.Activate; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Deactivate; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.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 com.google.common.base.Preconditions.checkNotNull; |
| 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) |
| protected DeviceProviderRegistry deviceProviderRegistry; |
| @Reference(cardinality = ReferenceCardinality.MANDATORY) |
| protected LinkProviderRegistry linkProviderRegistry; |
| @Reference(cardinality = ReferenceCardinality.MANDATORY) |
| protected NetworkConfigService networkConfigService; |
| @Reference(cardinality = ReferenceCardinality.MANDATORY) |
| protected LinkService linkService; |
| @Reference(cardinality = ReferenceCardinality.MANDATORY) |
| 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) { |
| checkNotNull(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(); |
| |
| 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 = DefaultPortDescription.builder() |
| .withPortNumber(portNumber).isEnabled(true).build(); |
| 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(); |
| } |
| } |
| } |
| } |